代码地址: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. 只添加@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里主要代码

@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) {
//除了@ModelAttribute绑定参数之外,还可以通过@RequestParam从页面中传递参数/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的切面主要有以下几个要素:

  • 使用@Aspect注解将一个java类定义为切面类
  • @Order(i)注解来标识切面的优先级。i的值越小,优先级越高。
    1. 在切入点前的操作,按order的值由小到大执行
    1. 在切入点后的操作,按order的值由大到小执行
  • 使用@Pointcut定义一个切入点,可以是一个规则表达式,比如下例中某个package下的所有函数,也可以是一个注解等。 根据需要在切入点不同位置的切入内容
  • 使用@Before在切入点开始处切入内容
  • 使用@After在切入点结尾处切入内容
  • 使用@AfterReturning在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)
  • 使用@Around在切入点前后切入内容,并自己控制何时执行切入点自身的内容
  • 使用@AfterThrowing用来处理当切入内容部分抛出异常之后的处理逻辑
@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. 添加限制

//这里不能用@NotBlank,因为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 注解校验复杂的业务逻辑: 如果需要校验的业务逻辑比较复杂,可以使用@ScriptAssert来指定进行校验的方法, 通过方法来进行复杂业务逻辑的校验,然后返回 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+国际化的更多相关文章

  1. springboot 集成 swagger 自动生成API文档

    Swagger是一个规范和完整的框架,用于生成.描述.调用和可视化RESTful风格的Web服务.简单来说,Swagger是一个功能强大的接口管理工具,并且提供了多种编程语言的前后端分离解决方案. S ...

  2. 干掉 Postman?测试接口直接生成API文档,这个工具贼好用

    大家好,我是小富~ 前几天粉丝群有小伙伴问,有啥好用的API文档工具推荐,无意间发现了一款工具,这里马不停蹄的来给大家分享一下. ShowDoc一个非常适合团队的在线API文档工具,也支持用docke ...

  3. 干掉 Postman?测试接口直接生成API文档,ApiPost真香!

    实不相瞒我的收藏夹里躺着很多优质的开发工具,我有个爱好平时遇到感兴趣的开发工具都会记录下来,然后有时间在慢慢研究.前几天刚给同事分享一款非常好用的API文档工具,真的被惊艳到了,粉丝朋友们也感受一下吧 ...

  4. springboot + swagger2 生成api文档

    直接贴代码: <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-sw ...

  5. SpringBoot系列: 使用 Swagger 生成 API 文档

    SpringBoot非常适合开发 Restful API程序, 我们都知道为API文档非常重要, 但要维护好难度也很大, 原因有: 1. API文档如何能被方便地找到? 以文件的形式编写API文档都有 ...

  6. springfox+swagger2生成API文档

    1.建立一个spring mvc工程: 2.添加POM依赖: <properties> <springfoxversion>2.6.1</springfoxversion ...

  7. SpringBoot结合Swagger2自动生成api文档

    首先在pom.xml中添加如下依赖,其它web,lombok等依赖自行添加 <dependency> <groupId>io.springfox</groupId> ...

  8. Spring Boot 项目学习 (四) Spring Boot整合Swagger2自动生成API文档

    0 引言 在做服务端开发的时候,难免会涉及到API 接口文档的编写,可以经历过手写API 文档的过程,就会发现,一个自动生成API文档可以提高多少的效率. 以下列举几个手写API 文档的痛点: 文档需 ...

  9. SpringBoot中使用springfox+swagger2书写API文档

    随着前后端的分离,借口文档变的尤其重要,springfox是通过注解的形式自动生成API文档,利用它,可以很方便的书写restful API,swagger主要用于展示springfox生成的API文 ...

随机推荐

  1. [置顶] 普通程序员如何入门AI

    毫无疑问,人工智能是目前整个互联网领域最火的行业,随着AlphaGo战胜世界围棋冠军,以及各种无人驾驶.智能家居项目的布道,人们已经意识到了AI就是下一个风口.当然,程序员是我见过对于新技术最敏感的一 ...

  2. 我也说说Emacs吧(3) - 文件基本操作

    Spacemacs文件基本操作 有了前两讲的积累,我们知道了: 1. 我们既要学习emacs的操作,也要学习vi的操作 2. emacs是一个可扩展的平台,我们并不是从头配置,而是使用一套成熟的集成方 ...

  3. Vue(2) : Vue for Gank.io

    简介 最近学习Vue2.0,由于不懂前端知识,学习过程比较缓慢.文档学习过程如下: 通读vue官文 通读vue-router 2中文指南 学习axios 通读vuex官文 数据接口 再次感谢代码家的G ...

  4. 记录一下前端ajax实现增删改功能的步骤

    主要依赖三个按钮:新增,删除,编辑 新增:点击时创建新的LI或者TR并append到父级里,此时无需调动后台接口(如果新增需要弹窗输入val则可以调用): 删除:判断this是否有后台传过来的id值, ...

  5. [Python] re正则表达式指南以及常用操作

    一.语法 1. 使用正则表达式进行匹配的流程 2. Python支持的正则表达式元字符和语法 参考: AstralWind的Python正则表达式指南 官方文档:7.2. re — Regular e ...

  6. CentOS跨网段访问

    centos6.2_64删除虚拟网卡 virbr0 卸载以下组件,然后重启系统 yum remove libvirt yum remove libvirt-python 来源:http://www.i ...

  7. 【转载】VMware vSphere 5 HA详解 1

    很久没有动笔写博客了.总算最近的几项工作告一段落,对iOS和Android的折腾也兴趣稍退,该写点技术博客了. 想写一篇关于VMware HA的博客由来已久,曾经做了些功课,查了不少资料,写了点笔记, ...

  8. GLSL 内建函数

    内建函数基本上可以分为一下三类: (1)它们使用一些简便的方式提供必要的硬件功能,如材质贴图.这些函数单独通过着色器是无法模拟出来的. (2)它们展示了一些可以常简单的写入的繁琐操作(clamp, m ...

  9. 《DSP using MATLAB》示例Example 6.26

    代码: % r = 0.9; theta = (pi/180)*[-55:5:-35, 35:5:55]'; p = r*exp(j*theta); a = poly(p); b = 1; % Dir ...

  10. 【angularJS】简介

    简介 AngularJS 是一个 JavaScript 框架.它可通过 <script> 标签添加到 HTML 页面. AngularJS 通过 指令 扩展了 HTML,且通过 表达式 绑 ...