1. 程式人生 > >SpringBoot+rest接口+swagger2生成API文檔+validator+mybatis+aop+國際化

SpringBoot+rest接口+swagger2生成API文檔+validator+mybatis+aop+國際化

create dea ppi pro time success 類定義 -- sse

代碼地址:JillWen_SpringBootDemo

mybatis

1. 添加依賴:

<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis.version}</version>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<!--這裏如果不寫版本會自動繼承spring-boot-starter-parent裏的版本號-->
			<version>${mysql.version}</version>
</dependency>

2. dao層定義UserMapper.xml文件和UserMapper類

3. 使用註意:

  1. 使用mybatisGenerator插件(idea裏直接裝需要收費,參考:http://blog.csdn.net/luanlouis/article/details/43192131)
  2. 添加依賴
<plugin>
               <groupId>org.mybatis.generator</groupId>
               <artifactId>mybatis-generator-maven-plugin</artifactId>
               <version>${mybatis-generator.version}</version>
               <configuration>
                   <verbose>true</verbose>
                   <overwrite>true</overwrite>
               </configuration>
</plugin>

添加一個“Run運行”選項,使用maven運行mybatis-generator-maven-plugin插件, 在 “Command line” 選項中輸入“mybatis-generator:generate -e”

  1. 當mapper.xml文件不是放在resource文件下時,需要加插件將其生成到target裏。 每次修改後需要install。
<plugin>
				<artifactId>maven-resources-plugin</artifactId>
				<version>2.5</version>
				<executions>
					<execution>
						<id>copy-xmls</id>
						<phase>process-sources</phase>
						<goals>
							<goal>copy-resources</goal>
						</goals>
						<configuration>
							<outputDirectory>${basedir}/target/classes</outputDirectory>
							<resources>
								<resource>
									<directory>${basedir}/src/main/java</directory>
									<includes>
										<include>**/*.xml</include>
									</includes>
								</resource>
							</resources>
						</configuration>
					</execution>
				</executions>
</plugin>
  1. [email protected](@MapperScan("com.example.demo.server.dao")) 時idea會報錯,但是可以運行,[email protected]

restful接口

1. restful接口定義

(參考:http://websystique.com/spring-boot/spring-boot-rest-api-example/):

  • GET request to /users/ returns a list of users
  • GET request to /users/1 returns the user with ID 1
  • POST request to /users/ with a user object as JSON creates a new user
  • PUT request to /users/1 with a user object as JSON updates the user with ID 1
  • DELETE request to /users/1 deletes the user with ID 1
  • DELETE request to /users/ deletes all the users

2. controller裏主要代碼

@Autowired
   IUserService userService;

   /**
    * 查詢所有用戶
    * @return
    */
   @RequestMapping(value = "/", method = RequestMethod.GET)
   public List<User> listAllUsers() {
       List<User> users = userService.findAllUsers();
       return users;
   }

   /**
    * 根據id查詢用戶
    * @param id
    * @return
    */
   @RequestMapping(value = "/{id}", method = RequestMethod.GET)
   public User getUser(@PathVariable("id") int id) {
       logger.info("Fetching User with id {}", id);
       User user = userService.findById(id);
       if (user == null) {
           logger.error("User with id {} not found.", id);
       }
       return user;
   }

   /**
    * 新建一個用戶
    * @param user
    * @return
    */
   @RequestMapping(value = "/", method = RequestMethod.POST)
   public String createUser(@ModelAttribute  User user) {
       [email protected],[email protected]/RequestBody ?
       logger.info("Creating User : {}", user);
       User exitUser = new User();
       exitUser.setId(user.getId());
       if (userService.isUserExist(exitUser)) {
           logger.error("Unable to create. A User with id {} already exist", exitUser.getId());
       }
       userService.saveUser(user);
       return "success";
   }

   /**
    * 根據id更新用戶信息
    * @param id
    * @param user
    * @return
    */
   @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
   public String updateUser(@PathVariable("id") int id, @ModelAttribute User user) {
       //RequestBody
       logger.info("Updating User with id {}", id);

       User currentUser = userService.findById(id);

       if (currentUser == null) {
           logger.error("Unable to update. User with id {} not found.", id);
           return "fail";
       }
       currentUser.setName(user.getName());
       currentUser.setAge(user.getAge());
       userService.updateUser(currentUser);
       return "success";
   }

   /**
    * 根據id刪除用戶
    * @param id
    * @return
    */
   @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
   public String deleteUser(@PathVariable("id") int id) {
       logger.info("Fetching & Deleting User with id {}", id);

       User user = userService.findById(id);
       if (user == null) {
           logger.error("Unable to delete. User with id {} not found.", id);
           return "fail";
       }
       userService.deleteUserById(id);
       return "success";
   }


   /**
    * 刪除所有用戶
    * @return
    */
   @RequestMapping(value = "/", method = RequestMethod.DELETE)
   public String deleteAllUsers() {
       logger.info("Deleting All Users");

       userService.deleteAllUsers();
       return "success";
   }

測試(使用postman):

查詢所有用戶

技術分享

查詢id為1的用戶

技術分享

創建一個用戶

技術分享

更新id為1的用戶

技術分享

技術分享

 

3.使用swagger2生成api文檔

(參考http://blog.didispace.com/springbootswagger2/)

  1. 引入依賴
<dependency>
           <groupId>io.springfox</groupId>
           <artifactId>springfox-swagger2</artifactId>
           <version>2.2.2</version>
       </dependency>
       <dependency>
           <groupId>io.springfox</groupId>
           <artifactId>springfox-swagger-ui</artifactId>
           <version>2.2.2</version>
</dependency>
  1. 創建Swagger2配置類
@Configuration
@EnableSwagger2
public class Swagger2 {
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.example.demo.server.controller"))
                .paths(PathSelectors.any())
                .build();
    }
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Spring Boot中使用Swagger2構建RESTful APIs")
                .description("使用Swagger2構建RESTful APIs")
                .termsOfServiceUrl("http://www.wjcoding.cn/")
                .contact("Jill")
                .version("1.0")
                .build();
    }
}
  1. controller裏使用:
@ApiOperation(value="創建用戶", notes="根據User對象創建用戶")
    @ApiImplicitParam(name = "user", value = "用戶詳細實體user", required = true, dataType = "User")
    @RequestMapping(value = "/", method = RequestMethod.POST)
    public String createUser(@ModelAttribute  User user) {
    //代碼略
    }
  1. 查看api文檔: 啟動Spring Boot程序,訪問:http://localhost:8080/swagger-ui.html

技術分享

國際化

(參考博客:http://412887952-qq-com.iteye.com/blog/2312274)

1. 頁面中使用國際化

創建messages.properties(messages_zh_CN.properties,messages_en_US.properties)文件 thymeleaf裏使用#{key}顯示,例如:<p th:text="#{welcome}"></p>

2. 國際化文件相關配置

#指定message的basename,多個以逗號分隔,如果不加包名的話,默認從classpath路徑開始,默認: messages spring.messages.basename=i18n/messages #設定加載的資源文件緩存失效時間,-1的話為永不過期,默認為-1 spring.messages.cache-seconds=3600 #設定Message bundles的編碼,默認: UTF-8 #spring.messages.encoding=UTF-8

驗證:火狐地址欄裏輸入about:config回車,搜索accept_languages,改成en_US,en

技術分享

技術分享

3. 代碼中使用國際化

  1. 創建messages.properties(messages_zh_CN.properties,messages_en_US.properties)文件
  2. 代碼裏先獲取區域,再國際化信息:
Locale locale = LocaleContextHolder.getLocale();
(或者Locale locale = RequestContextUtils.getLocale(request);)
String msg = messageSource.getMessage("welcome", null,locale);
  • 區域解析器 默認:AcceptHeaderLocaleResolver 根據HTTP請求的頭部信息accept-language來解析區域

  • 會話區域解析器:SessionLocaleResolver

@Bean
  public LocaleResolver localeResolver() {
      SessionLocaleResolver slr = new SessionLocaleResolver();
      //設置默認區域
      slr.setDefaultLocale(Locale.CHINA);
      return slr;
  }
request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, new Locale("en", "US"))
  • Cookie區域解析器:CookieLocaleResolver
@Bean
    public LocaleResolver localeResolver() {
       CookieLocaleResolver slr = new CookieLocaleResolver();
        //設置默認區域
        slr.setDefaultLocale(Locale.CHINA);
        slr.setCookieMaxAge(3600);//設置cookie有效期.
        returnslr;
    }
  • 固定的區域解析器:FixedLocaleResolver
@Bean
    public LocaleResolver localeResolver() {
       FixedLocaleResolver slr = new FixedLocaleResolver ();
        //設置默認區域
        slr.setDefaultLocale(Locale.US);
        returnslr;
    }
  • 使用參數修改用戶的區域 將LocaleChangeInterceptor攔截器應用到處理程序映射中,它會發現當前HTTP請求中出現的特殊參數。 其中的參數名稱可以通過攔截器的paramName屬性進行自定義。 如果這種參數出現在當前請求中,攔截器就會根據參數值來改變用戶的區域。
@Bean
 public LocaleChangeInterceptor localeChangeInterceptor() {
        LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
        // 設置請求地址的參數,默認為:locale
        // lci.setParamName(LocaleChangeInterceptor.DEFAULT_PARAM_NAME);
        return lci;
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
   registry.addInterceptor(localeChangeInterceptor());
}

註意這個是可以和會話區域解析器以及Cookie區域解析器一起使用的, 但是不能和FixedLocaleResolver一起使用,否則會拋出異常信息。

驗證:

技術分享

技術分享

技術分享

aop

(參考:http://blog.didispace.com/springbootaoplog/)

1. 添加依賴

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2. 使用:

實現AOP的切面主要有以下幾個要素:

  • [email protected]
  • @Order(i)註解來標識切面的優先級。i的值越小,優先級越高。
    1. 在切入點前的操作,按order的值由小到大執行
    1. 在切入點後的操作,按order的值由大到小執行
  • [email protected],可以是一個規則表達式,比如下例中某個package下的所有函數,也可以是一個註解等。 根據需要在切入點不同位置的切入內容
  • [email protected]
  • [email protected]
  • [email protected](可以用來對處理返回值做一些加工處理)
  • [email protected],並自己控制何時執行切入點自身的內容
  • [email protected]之後的處理邏輯
@Aspect
@Component
@Order(1)
public class WebLogAspect {
    private Logger logger = Logger.getLogger(WebLogAspect.class);
    ThreadLocal<Long> startTime = new ThreadLocal<>();

    @Pointcut("execution(public * com.example.demo.server.controller..*.*(..))")
    public void webLog(){}

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        startTime.set(System.currentTimeMillis());
        // 接收到請求,記錄請求內容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 記錄下請求內容
        logger.info("URL : " + request.getRequestURL().toString());
        logger.info("HTTP_METHOD : " + request.getMethod());
        logger.info("IP : " + request.getRemoteAddr());
        logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        logger.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
    }

    @AfterReturning(returning = "ret",pointcut = "webLog()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 處理完請求,返回內容
        logger.info("RESPONSE : " + ret);
        logger.info("RESPONSE : " + ret);
        logger.info("SPEND TIME : " + (System.currentTimeMillis() - startTime.get()));
    }
}


validator

(參考http://www.jianshu.com/p/a9b1e2f7a749)

1. 添加限制

[email protected],因為id類型為int
  private int id;

  //使用groups屬性來給分組命名,然後在需要的地方指定命令即可
  @NotBlank(groups=NAME.class)
  private String name;

  @Min(1)
  private Integer age;

2. 使用驗證

@RestController
public class ValidateController {
    @RequestMapping(value="testUser")
    public void testStudent(@Validated User user) {
    }

    @RequestMapping(value="testUser1")
    public void testStudent1(@Validated(User.NAME.class) User user) {
    }
}

使用 @ScriptAssert 註解校驗復雜的業務邏輯: 如果需要校驗的業務邏輯比較復雜,[email protected], 通過方法來進行復雜業務邏輯的校驗,然後返回 true或false來表明是否校驗成功。

@ScriptAssert(lang="javascript",script="com.learn.validate.domain
.Student.checkParams(_this.name,_this.age,_this.classes)",
groups=CHECK.class)
public class Student {
//其他代碼
/註意進行校驗的方法要寫成靜態方法,否則會出現
 //TypeError: xxx is not a function 的錯誤
 public static boolean checkParams(String name,int age,String classes) {
  if(name!=null&&age>8&classes!=null)
  {
   return true;
  }
  else
  {
   return false;
  }
 }
}

3. 註意:

在Hibernate Validator(org.hibernate.validator.constraints)中:

@NotEmpty://CharSequence, Collection, Map 和 Array 對象不能是 null 並且相關對象的 size 大於 0。 @NotBlank://String 不是 null 且去除兩端空白字符後的長度(trimmed length)大於 0。

驗證:

技術分享

SpringBoot+rest接口+swagger2生成API文檔+validator+mybatis+aop+國際化