当前位置:   article > 正文

SpringBoot+rest接口+swagger2生成API文档+validator+mybatis+aop+国际化

api swagger国际化

我的博客园文章地址

代码地址:JillWen_SpringBootDemo

mybatis

1. 添加依赖:

  1. <dependency>
  2. <groupId>org.mybatis.spring.boot</groupId>
  3. <artifactId>mybatis-spring-boot-starter</artifactId>
  4. <version>${mybatis.version}</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>mysql</groupId>
  8. <artifactId>mysql-connector-java</artifactId>
  9. <!--这里如果不写版本会自动继承spring-boot-starter-parent里的版本号-->
  10. <version>${mysql.version}</version>
  11. </dependency>

2. dao层定义UserMapper.xml文件和UserMapper类

3. 使用注意:

  1. 使用mybatisGenerator插件(idea里直接装需要收费,参考:http://blog.csdn.net/luanlouis/article/details/43192131)
  2. 添加依赖
  1. <plugin>
  2. <groupId>org.mybatis.generator</groupId>
  3. <artifactId>mybatis-generator-maven-plugin</artifactId>
  4. <version>${mybatis-generator.version}</version>
  5. <configuration>
  6. <verbose>true</verbose>
  7. <overwrite>true</overwrite>
  8. </configuration>
  9. </plugin>

添加一个“Run运行”选项,使用maven运行mybatis-generator-maven-plugin插件, 在 “Command line” 选项中输入“mybatis-generator:generate -e”

  1. 当mapper.xml文件不是放在resource文件下时,需要加插件将其生成到target里。 每次修改后需要install。
  1. <plugin>
  2. <artifactId>maven-resources-plugin</artifactId>
  3. <version>2.5</version>
  4. <executions>
  5. <execution>
  6. <id>copy-xmls</id>
  7. <phase>process-sources</phase>
  8. <goals>
  9. <goal>copy-resources</goal>
  10. </goals>
  11. <configuration>
  12. <outputDirectory>${basedir}/target/classes</outputDirectory>
  13. <resources>
  14. <resource>
  15. <directory>${basedir}/src/main/java</directory>
  16. <includes>
  17. <include>**/*.xml</include>
  18. </includes>
  19. </resource>
  20. </resources>
  21. </configuration>
  22. </execution>
  23. </executions>
  24. </plugin>
  1. 只添加@Mapper注解或者(@MapperScan("com.example.demo.server.dao")) 时idea会报错,但是可以运行,所以强迫症可以加一个@Repository。

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里主要代码

  1. @Autowired
  2. IUserService userService;
  3. /**
  4. * 查询所有用户
  5. * @return
  6. */
  7. @RequestMapping(value = "/", method = RequestMethod.GET)
  8. public List<User> listAllUsers() {
  9. List<User> users = userService.findAllUsers();
  10. return users;
  11. }
  12. /**
  13. * 根据id查询用户
  14. * @param id
  15. * @return
  16. */
  17. @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  18. public User getUser(@PathVariable("id") int id) {
  19. logger.info("Fetching User with id {}", id);
  20. User user = userService.findById(id);
  21. if (user == null) {
  22. logger.error("User with id {} not found.", id);
  23. }
  24. return user;
  25. }
  26. /**
  27. * 新建一个用户
  28. * @param user
  29. * @return
  30. */
  31. @RequestMapping(value = "/", method = RequestMethod.POST)
  32. public String createUser(@ModelAttribute User user) {
  33. //除了@ModelAttribute绑定参数之外,还可以通过@RequestParam从页面中传递参数/RequestBody ?
  34. logger.info("Creating User : {}", user);
  35. User exitUser = new User();
  36. exitUser.setId(user.getId());
  37. if (userService.isUserExist(exitUser)) {
  38. logger.error("Unable to create. A User with id {} already exist", exitUser.getId());
  39. }
  40. userService.saveUser(user);
  41. return "success";
  42. }
  43. /**
  44. * 根据id更新用户信息
  45. * @param id
  46. * @param user
  47. * @return
  48. */
  49. @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
  50. public String updateUser(@PathVariable("id") int id, @ModelAttribute User user) {
  51. //RequestBody
  52. logger.info("Updating User with id {}", id);
  53. User currentUser = userService.findById(id);
  54. if (currentUser == null) {
  55. logger.error("Unable to update. User with id {} not found.", id);
  56. return "fail";
  57. }
  58. currentUser.setName(user.getName());
  59. currentUser.setAge(user.getAge());
  60. userService.updateUser(currentUser);
  61. return "success";
  62. }
  63. /**
  64. * 根据id删除用户
  65. * @param id
  66. * @return
  67. */
  68. @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
  69. public String deleteUser(@PathVariable("id") int id) {
  70. logger.info("Fetching & Deleting User with id {}", id);
  71. User user = userService.findById(id);
  72. if (user == null) {
  73. logger.error("Unable to delete. User with id {} not found.", id);
  74. return "fail";
  75. }
  76. userService.deleteUserById(id);
  77. return "success";
  78. }
  79. /**
  80. * 删除所有用户
  81. * @return
  82. */
  83. @RequestMapping(value = "/", method = RequestMethod.DELETE)
  84. public String deleteAllUsers() {
  85. logger.info("Deleting All Users");
  86. userService.deleteAllUsers();
  87. return "success";
  88. }

3.使用swagger2生成api文档

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

  1. 引入依赖
  1. <dependency>
  2. <groupId>io.springfox</groupId>
  3. <artifactId>springfox-swagger2</artifactId>
  4. <version>2.2.2</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>io.springfox</groupId>
  8. <artifactId>springfox-swagger-ui</artifactId>
  9. <version>2.2.2</version>
  10. </dependency>
  1. 创建Swagger2配置类
  1. @Configuration
  2. @EnableSwagger2
  3. public class Swagger2 {
  4. @Bean
  5. public Docket createRestApi() {
  6. return new Docket(DocumentationType.SWAGGER_2)
  7. .apiInfo(apiInfo())
  8. .select()
  9. .apis(RequestHandlerSelectors.basePackage("com.example.demo.server.controller"))
  10. .paths(PathSelectors.any())
  11. .build();
  12. }
  13. private ApiInfo apiInfo() {
  14. return new ApiInfoBuilder()
  15. .title("Spring Boot中使用Swagger2构建RESTful APIs")
  16. .description("使用Swagger2构建RESTful APIs")
  17. .termsOfServiceUrl("http://www.wjcoding.cn/")
  18. .contact("Jill")
  19. .version("1.0")
  20. .build();
  21. }
  22. }
  1. controller里使用:
  1. @ApiOperation(value="创建用户", notes="根据User对象创建用户")
  2. @ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User")
  3. @RequestMapping(value = "/", method = RequestMethod.POST)
  4. public String createUser(@ModelAttribute User user) {
  5. //代码略
  6. }
  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

3. 代码中使用国际化

  1. 创建messages.properties(messages_zh_CN.properties,messages_en_US.properties)文件
  2. 代码里先获取区域,再国际化信息:
  1. Locale locale = LocaleContextHolder.getLocale();
  2. (或者Locale locale = RequestContextUtils.getLocale(request);)
  3. String msg = messageSource.getMessage("welcome", null,locale);
  • 区域解析器 默认:AcceptHeaderLocaleResolver 根据HTTP请求的头部信息accept-language来解析区域

  • 会话区域解析器:SessionLocaleResolver

  1. @Bean
  2. public LocaleResolver localeResolver() {
  3. SessionLocaleResolver slr = new SessionLocaleResolver();
  4. //设置默认区域
  5. slr.setDefaultLocale(Locale.CHINA);
  6. return slr;
  7. }
request.getSession().setAttribute(SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME, new Locale("en", "US"))
  • Cookie区域解析器:CookieLocaleResolver
  1. @Bean
  2. public LocaleResolver localeResolver() {
  3. CookieLocaleResolver slr = new CookieLocaleResolver();
  4. //设置默认区域
  5. slr.setDefaultLocale(Locale.CHINA);
  6. slr.setCookieMaxAge(3600);//设置cookie有效期.
  7. returnslr;
  8. }
  • 固定的区域解析器:FixedLocaleResolver
  1. @Bean
  2. public LocaleResolver localeResolver() {
  3. FixedLocaleResolver slr = new FixedLocaleResolver ();
  4. //设置默认区域
  5. slr.setDefaultLocale(Locale.US);
  6. returnslr;
  7. }
  • 使用参数修改用户的区域 将LocaleChangeInterceptor拦截器应用到处理程序映射中,它会发现当前HTTP请求中出现的特殊参数。 其中的参数名称可以通过拦截器的paramName属性进行自定义。 如果这种参数出现在当前请求中,拦截器就会根据参数值来改变用户的区域。
  1. @Bean
  2. public LocaleChangeInterceptor localeChangeInterceptor() {
  3. LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
  4. // 设置请求地址的参数,默认为:locale
  5. // lci.setParamName(LocaleChangeInterceptor.DEFAULT_PARAM_NAME);
  6. return lci;
  7. }
  8. @Override
  9. public void addInterceptors(InterceptorRegistry registry) {
  10. registry.addInterceptor(localeChangeInterceptor());
  11. }

注意这个是可以和会话区域解析器以及Cookie区域解析器一起使用的, 但是不能和FixedLocaleResolver一起使用,否则会抛出异常信息。

aop

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

1. 添加依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-aop</artifactId>
  4. </dependency>

2. 使用:

实现AOP的切面主要有以下几个要素:

  • 使用@Aspect注解将一个java类定义为切面类
  • @Order(i)注解来标识切面的优先级。i的值越小,优先级越高。
    1. 在切入点前的操作,按order的值由小到大执行
    1. 在切入点后的操作,按order的值由大到小执行
  • 使用@Pointcut定义一个切入点,可以是一个规则表达式,比如下例中某个package下的所有函数,也可以是一个注解等。 根据需要在切入点不同位置的切入内容
  • 使用@Before在切入点开始处切入内容
  • 使用@After在切入点结尾处切入内容
  • 使用@AfterReturning在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)
  • 使用@Around在切入点前后切入内容,并自己控制何时执行切入点自身的内容
  • 使用@AfterThrowing用来处理当切入内容部分抛出异常之后的处理逻辑
  1. @Aspect
  2. @Component
  3. @Order(1)
  4. public class WebLogAspect {
  5. private Logger logger = Logger.getLogger(WebLogAspect.class);
  6. ThreadLocal<Long> startTime = new ThreadLocal<>();
  7. @Pointcut("execution(public * com.example.demo.server.controller..*.*(..))")
  8. public void webLog(){}
  9. @Before("webLog()")
  10. public void doBefore(JoinPoint joinPoint) throws Throwable {
  11. startTime.set(System.currentTimeMillis());
  12. // 接收到请求,记录请求内容
  13. ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
  14. HttpServletRequest request = attributes.getRequest();
  15. // 记录下请求内容
  16. logger.info("URL : " + request.getRequestURL().toString());
  17. logger.info("HTTP_METHOD : " + request.getMethod());
  18. logger.info("IP : " + request.getRemoteAddr());
  19. logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
  20. logger.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
  21. }
  22. @AfterReturning(returning = "ret",pointcut = "webLog()")
  23. public void doAfterReturning(Object ret) throws Throwable {
  24. // 处理完请求,返回内容
  25. logger.info("RESPONSE : " + ret);
  26. logger.info("RESPONSE : " + ret);
  27. logger.info("SPEND TIME : " + (System.currentTimeMillis() - startTime.get()));
  28. }
  29. }

validator

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

1. 添加限制

  1. //这里不能用@NotBlank,因为id类型为int
  2. private int id;
  3. //使用groups属性来给分组命名,然后在需要的地方指定命令即可
  4. @NotBlank(groups=NAME.class)
  5. private String name;
  6. @Min(1)
  7. private Integer age;

2. 使用验证

  1. @RestController
  2. public class ValidateController {
  3. @RequestMapping(value="testUser")
  4. public void testStudent(@Validated User user) {
  5. }
  6. @RequestMapping(value="testUser1")
  7. public void testStudent1(@Validated(User.NAME.class) User user) {
  8. }
  9. }

使用 @ScriptAssert 注解校验复杂的业务逻辑: 如果需要校验的业务逻辑比较复杂,可以使用@ScriptAssert来指定进行校验的方法, 通过方法来进行复杂业务逻辑的校验,然后返回 true或false来表明是否校验成功。

  1. @ScriptAssert(lang="javascript",script="com.learn.validate.domain
  2. .Student.checkParams(_this.name,_this.age,_this.classes)",
  3. groups=CHECK.class)
  4. public class Student {
  5. //其他代码
  6. /注意进行校验的方法要写成静态方法,否则会出现
  7. //TypeError: xxx is not a function 的错误
  8. public static boolean checkParams(String name,int age,String classes) {
  9. if(name!=null&&age>8&classes!=null)
  10. {
  11. return true;
  12. }
  13. else
  14. {
  15. return false;
  16. }
  17. }
  18. }

3. 注意:

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

@NotEmpty://CharSequence, Collection, Map 和 Array 对象不能是 null 并且相关对象的 size 大于 0。 @NotBlank://String 不是 null 且去除两端空白字符后的长度(trimmed length)大于 0。

转载于:https://my.oschina.net/u/1171648/blog/1531817

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/58783
推荐阅读
相关标签
  

闽ICP备14008679号