接着上篇博客的代碼繼續寫html
1.接口版本控制java
一個系統上線後會不斷迭代更新,需求也會不斷變化,有可能接口的參數也會發生變化,若是在原有的參數上直接修改,可能會影響線上系統的正常運行,這時咱們就須要設置不一樣的版本,這樣即便參數發生變化,因爲老版本沒有變化,所以不會影響上線系統的運行。web
通常咱們能夠在地址上帶上版本號,也能夠在參數上帶上版本號,還能夠再 header 裏帶上版本號,這裏咱們在地址上帶上版本號,大體的地址如:http://api.example.com/v1/test,其中,v1 即表明的是版本號。具體作法請看代碼:spring
import org.springframework.web.bind.annotation.Mapping; import java.lang.annotation.*; /** * 版本控制 * @author XIHONGLEI * @date 2018-11-15 */ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Mapping public @interface ApiVersion { int value(); }
import org.springframework.web.servlet.mvc.condition.RequestCondition; import javax.servlet.http.HttpServletRequest; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author XIHONGLEI * @date 2018-11-15 */ public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> { // 路徑中版本的前綴, 這裏用 /v[1-9]/的形式 private final static Pattern VERSION_PREFIX_PATTERN = Pattern.compile("v(\\d+)/"); private int apiVersion; public ApiVersionCondition(int apiVersion) { this.apiVersion = apiVersion; } @Override public ApiVersionCondition combine(ApiVersionCondition other) { // 採用最後定義優先原則,則方法上的定義覆蓋類上面的定義 return new ApiVersionCondition(other.getApiVersion()); } @Override public ApiVersionCondition getMatchingCondition(HttpServletRequest request) { Matcher m = VERSION_PREFIX_PATTERN.matcher(request.getRequestURI()); if (m.find()) { Integer version = Integer.valueOf(m.group(1)); if (version >= this.apiVersion) { return this; } } return null; } @Override public int compareTo(ApiVersionCondition other, HttpServletRequest request) { // 優先匹配最新的版本號 return other.getApiVersion() - this.apiVersion; } public int getApiVersion() { return apiVersion; } }
import org.springframework.core.annotation.AnnotationUtils; import org.springframework.web.servlet.mvc.condition.RequestCondition; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import java.lang.reflect.Method; /** * @author XIHONGLEI * @date 2018-11-15 */ public class CustomRequestMappingHandlerMapping extends RequestMappingHandlerMapping { @Override protected RequestCondition<ApiVersionCondition> getCustomTypeCondition(Class<?> handlerType) { ApiVersion apiVersion = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class); return createCondition(apiVersion); } @Override protected RequestCondition<ApiVersionCondition> getCustomMethodCondition(Method method) { ApiVersion apiVersion = AnnotationUtils.findAnnotation(method, ApiVersion.class); return createCondition(apiVersion); } private RequestCondition<ApiVersionCondition> createCondition(ApiVersion apiVersion) { return apiVersion == null ? null : new ApiVersionCondition(apiVersion.value()); } }
#而後在WebConfig配置類中注入Bean import com.hello.config.CustomRequestMappingHandlerMapping; import com.hello.filter.ApiInterceptor; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringBootConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; /** * 配置類 * @author XIHONGLEI * @date 2018-10-31 */ @SpringBootConfiguration public class WebConfig extends WebMvcConfigurationSupport { @Override protected void addInterceptors(InterceptorRegistry registry) { super.addInterceptors(registry); // 將 ApiInterceptor 攔截器類添加進去 registry.addInterceptor(new ApiInterceptor()); } @Override @Bean public RequestMappingHandlerMapping requestMappingHandlerMapping() { RequestMappingHandlerMapping handlerMapping = new CustomRequestMappingHandlerMapping(); handlerMapping.setOrder(0); handlerMapping.setInterceptors(getInterceptors()); return handlerMapping; } }
#最後定義一個帶版本控制的接口 import com.hello.WebConfig; import com.hello.config.ApiVersion; import com.hello.entity.ContractDetailDto; import com.hello.service.CheckPositionService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class HelloController { @Autowired private WebConfig webConfig; @ApiVersion(1) @RequestMapping("{version}/getName") public String vGetName() { return "Hello World! version 1"; } @ApiVersion(2) @RequestMapping("{version}/getName") public String getName() { return "Hello World! version 2"; } }
查看效果:api
2.模板引擎架構
在傳統的 SpringMVC 架構中,咱們通常將 JSP、HTML 頁面放到 webapps 目錄下面,可是 Spring Boot 沒有 webapps,更沒有 web.xml,若是咱們要寫界面的話,該如何作呢?mvc
Spring Boot 官方提供了幾種模板引擎:FreeMarker、Velocity、Thymeleaf、Groovy、mustache、JSP。app
這裏以 FreeMarker 爲例講解 Spring Boot 的使用。webapp
首先引入 FreeMarker 依賴:ide
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency>
在 resources 下面創建兩個目錄:static 和 templates,如圖所示:
其中 static 目錄用於存放靜態資源,譬如:CSS、JS、HTML 等,templates 目錄存放模板引擎文件,咱們能夠在 templates 下面建立一個文件:index.ftl(freemarker 默認後綴爲 .ftl
),並添加內容:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Hello ${name}!</title> </head> <body> Hello ${name}! </body> </html>
而後在POM中配置Resource的時候必定要把全部的資源文件都包括:
<resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.yml</include> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*</include> </includes> <filtering>false</filtering> </resource> </resources>
新建Contrlller:
import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller public class HomeController { @RequestMapping(value = "/index") public ModelAndView index() { ModelAndView view = new ModelAndView("/index"); view.addObject("name","Tom"); return view; } }
看結果: