什么是前后端分離開發(fā)?
前后端分離開發(fā),就是在項(xiàng)目開發(fā)過程中,對于前端的代碼專門由前端的開發(fā)人員開發(fā),后端代碼由后端人員負(fù)責(zé),這樣可以做到分工明確、各司其職,進(jìn)而提高開發(fā)效率,前后端代碼并行開發(fā),加快項(xiàng)目的開發(fā)進(jìn)度。目前前后端分離被各大公司使用,成為項(xiàng)目開發(fā)的主流開發(fā)方式。
前后端分離開發(fā)后,工程結(jié)構(gòu)也會發(fā)生變化,即前后端代碼不會混在同一個maven工程中,而是分為前端工程和后端工程。
- 后端:負(fù)責(zé)處理、存儲數(shù)據(jù)。
- 前端:負(fù)責(zé)顯示數(shù)據(jù)。
- 后端工程——>打包部署到tomcat。
- 前端工程——>打包部署到nginx。
前端和后端開發(fā)人員通過 接口 進(jìn)行數(shù)據(jù)的交換。
開發(fā)流程
前后端分離開發(fā)時面臨一個問題,就是前端人員和后端人員如何進(jìn)行配合(請求路徑、參數(shù)傳遞、請求方式、后端如何響應(yīng)等)來共同完成一個任務(wù)呢?
接口(API接口):就是一個http的請求地址,主要就是去定義:請求路徑、請求方式、請求參數(shù)、響應(yīng)數(shù)據(jù)等內(nèi)容。
- 后端編寫和維護(hù)接口文檔,在 API 變化時更新接口文檔
- 后端根據(jù)接口文檔進(jìn)行接口開發(fā)
- 前端根據(jù)接口文檔進(jìn)行開發(fā) + Mock平臺
- 開發(fā)完成后聯(lián)調(diào)和提交測試
推薦幾個接口規(guī)范工具:postman、eolinker
前后端僅僅通過異步接口(AJAX/JSONP)來編程,前后端都各自有自己的開發(fā)流程,構(gòu)建工具,測試集合,關(guān)注點(diǎn)分離,前后端變得相對獨(dú)立并解耦合。
Swagger
Swagger是什么?
Swagger 是一個規(guī)范和完整的框架,用于生成、描述、調(diào)用和可視化 RESTful 風(fēng)格的 Web 服務(wù)的接口文檔。
目前的項(xiàng)目基本都是前后端分離,后端為前端提供接口的同時,還需同時提供接口的說明文檔。但我們的代碼總是會根據(jù)實(shí)際情況來實(shí)時更新,這個時候有可能會忘記更新接口的說明文檔,造成一些不必要的問題。
用人話說,swagger就是幫你寫接口說明文檔的。更具體地,可以看下面的圖片,swagger官方建議使用下面的紅字部分,這篇博客主要是記錄如何,使用swagger自動生成Api文檔的,所以只介紹swagger-ui,其他的…以后我用到會再整理。
文章來源:http://www.zghlxwxcb.cn/news/detail-456053.html
基本使用
knife4j是java mvc框架集成swagger生成api文檔的增強(qiáng)解決方案。文章來源地址http://www.zghlxwxcb.cn/news/detail-456053.html
- 導(dǎo)入坐標(biāo)
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
- 配置WebMvcConfig類
public class WebMvcConfig extends WebMvcConfigurationSupport {
/**
* 設(shè)置靜態(tài)資源映射。
*
* @param registry
*/
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
log.info("開始進(jìn)行靜態(tài)資源映射...");
// addResourceHandler("/backend/**"):攔截請求信息,addResourceLocations("classpath:/backend/"):文件真實(shí)地址。
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
}
/**
* 擴(kuò)展mvc框架的消息轉(zhuǎn)換器。
*
* @param converters
*/
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
log.info("加入全局消息轉(zhuǎn)換器...");
// 創(chuàng)建消息轉(zhuǎn)換器對象,
MappingJackson2HttpMessageConverter messageConverter=new MappingJackson2HttpMessageConverter();
// 設(shè)置對象轉(zhuǎn)換器,底層使用Jackson將java對象轉(zhuǎn)為json。
messageConverter.setObjectMapper(new JacksonObjectMapper());
// 將上面的消息轉(zhuǎn)換器添加到mvc框架的轉(zhuǎn)換器集合中。放在集合的第一位,會先使用我們加入的全局消息轉(zhuǎn)換器
converters.add( 0,messageConverter);
}
@Bean
public Docket createRestApi() {
// 文檔類型
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.jie.reggie.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("瑞吉外賣")
.version("1.0")
.description("瑞吉外賣接口文檔")
.build();
}
}
- 配置LoginCheckFilter類
/**
* @author 小杰 檢查用戶是否已經(jīng)登錄的過濾器。
*/
@Slf4j
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
// 專門用來進(jìn)行路徑比較的。路徑匹配器,支持通配符。
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws ServletException, IOException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
// 1.獲取本次請求的uri
String requestURI = httpServletRequest.getRequestURI();
log.info("獲取到的uri:{}", requestURI);
// 定義所有不處理的請求路徑。
String[] urls =
new String[]{
"/backend/**",
"/front/**",
"/employee/login",
"/employee/logout",
"/common/**",
"/user/login",
"/user/sendMsg",
"/doc.html",
"/webjars/**",
"/swagger-resources",
"/v2/api-docs"
};
// 2、判斷本次請求是否需要處理,
boolean check = check(urls, requestURI);
// - 如果不需要處理,就直接放行,
if (check) {
log.info("請求不需要處理:{}", requestURI);
chain.doFilter(httpServletRequest, httpServletResponse);
return;
}
// 3.判斷登錄狀態(tài),
// 后臺員工登錄- 如果已登錄,就直接放行
if (httpServletRequest.getSession().getAttribute("employee") != null) {
log.info("用戶已登錄,登錄的id為: {}", httpServletRequest.getSession().getAttribute("employee"));
// 把id保存到當(dāng)前ThreadLocal線程中。
Long empId = (Long) httpServletRequest.getSession().getAttribute("employee");
BaseContext.setCurrentId(empId);
// 放行。
chain.doFilter(httpServletRequest, httpServletResponse);
return;
}
// 用戶登錄- 如果已登錄,就直接放行
if (httpServletRequest.getSession().getAttribute("user") != null) {
log.info("用戶已登錄,登錄的id為: {}", httpServletRequest.getSession().getAttribute("user"));
// 把id保存到當(dāng)前ThreadLocal線程中。
Long userId = (Long) httpServletRequest.getSession().getAttribute("user");
BaseContext.setCurrentId(userId);
// 放行。
chain.doFilter(httpServletRequest, httpServletResponse);
return;
}
// 如果未登錄,則返回未登錄結(jié)果.通過輸出流方式向客戶端響應(yīng)數(shù)據(jù)。
httpServletResponse.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
log.info("用戶未登錄。。。");
return;
}
/**
* 進(jìn)行路徑匹配,檢查本次請求是否需要匹配。
*
* @param requestURI 待匹配的uri
* @param urls 所有不處理的請求路徑數(shù)組。。
* @return 匹配成功返回true,否則返回false。
*/
public boolean check(String[] urls, String requestURI) {
for (String url : urls) {
if (PATH_MATCHER.match(url, requestURI)) {
return true;
}
}
return false;
}
}
參考
- 超詳細(xì)的前后端分離開發(fā)
- swagger詳解
到了這里,關(guān)于前后端分離開發(fā)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!