SpringBoot实践
5.SpringBoot实践
接下来,我们来看看如何用SpringBoot来玩转以前的SSM,我们沿用之前讲解SSM用到的数据库tb_user和实体类User
5.1.整合SpringMVC
虽然默认配置已经可以使用SpringMVC了,不过我们有时候需要进行自定义配置。
5.1.1.修改端口
查看SpringBoot的全局属性可知,端口通过以下方式配置:
# 映射端口
server:
port: 80
重启服务后测试:

5.1.2.访问静态资源
现在,我们的项目是一个jar工程,那么就没有webapp,我们的静态资源该放哪里呢?
回顾我们上面看的源码,有一个叫做ResourceProperties的类,里面就定义了静态资源的默认查找路径:

默认的静态资源路径为:
- classpath:/META-INF/resources/
- classpath:/resources/
- classpath:/static/
- classpath:/public
只要静态资源放在这些目录中任何一个,SpringMVC都会帮我们处理。
我们习惯会把静态资源放在classpath:/static/目录下。我们创建目录,并且添加一些静态资源:

重启项目后测试:

5.1.3.添加拦截器
拦截器也是我们经常需要使用的,在SpringBoot中该如何配置呢?
拦截器不是一个普通属性,而是一个类,所以就要用到java配置方式了。在SpringBoot官方文档中有这么一段说明:
If you want to keep Spring Boot MVC features and you want to add additional MVC configuration (interceptors, formatters, view controllers, and other features), you can add your own
@Configurationclass of typeWebMvcConfigurerbut without@EnableWebMvc. If you wish to provide custom instances ofRequestMappingHandlerMapping,RequestMappingHandlerAdapter, orExceptionHandlerExceptionResolver, you can declare aWebMvcRegistrationsAdapterinstance to provide such components.If you want to take complete control of Spring MVC, you can add your own
@Configurationannotated with@EnableWebMvc.
翻译:
如果你想要保持Spring Boot 的一些默认MVC特征,同时又想自定义一些MVC配置(包括:拦截器,格式化器, 视图控制器、消息转换器 等等),你应该让一个类实现
WebMvcConfigurer,并且添加@Configuration注解,但是千万不要加@EnableWebMvc注解。如果你想要自定义HandlerMapping、HandlerAdapter、ExceptionResolver等组件,你可以创建一个WebMvcRegistrationsAdapter实例 来提供以上组件。如果你想要完全自定义SpringMVC,不保留SpringBoot提供的一切特征,你可以自己定义类并且添加
@Configuration注解和@EnableWebMvc注解
总结:通过实现WebMvcConfigurer并添加@Configuration注解来实现自定义部分SpringMvc配置。
首先我们定义一个拦截器:
package cn.clocktt.interceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginInterceptor implements HandlerInterceptor {
private Logger logger = LoggerFactory.getLogger(LoginInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
logger.debug("preHandle method is now running!");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
logger.debug("postHandle method is now running!");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
logger.debug("afterCompletion method is now running!");
}
}
然后,我们定义配置类,注册拦截器:
package cn.clocktt.configuration;
import cn.clocktt.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MvcConfig implements WebMvcConfigurer {
/**
* 通过@Bean注解,将我们定义的拦截器注册到Spring容器
* @return
*/
@Bean
public LoginInterceptor getLoginInterceptor(){
return new LoginInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 通过registry来注册拦截器,通过addPathPatterns来添加拦截路径
registry.addInterceptor(this.getLoginInterceptor()).addPathPatterns("/**");
}
}
结构如下:

接下来运行并查看日志:
你会发现日志中什么都没有,因为我们记录的log级别是debug,默认是显示info以上,我们需要进行配置。
SpringBoot通过logging.level.*=debug来配置日志级别,*号位置表示填写包名
# 设置cn.clocktt包的日志级别为debug
logging:
level:
cn.clocktt: debug
再次运行查看:

可以发现拦截器和日志均正常工作
5.2.整合数据库驱动和事务
加入数据库驱动的依赖,SpringBoot并不知道我们用的什么数据库,这里我们选择MySQL:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
至于事务,SpringBoot中通过注解来控制。就是我们熟知的@Transactional
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User queryById(Long id){
return userMapper.selectByPrimaryKey(id);
}
@Transactional
public void deleteById(Long id){
userMapper.deleteByPrimaryKey(id);
}
}
5.3.整合连接池
其实,在刚才引入jdbc启动器的时候,SpringBoot已经自动帮我们引入了一个连接池:

HikariCP应该是目前速度最快的连接池了,我们看看它与c3p0的对比:

因此,我们只需要指定连接池参数即可:
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/leyou
username: root
password: root
5.4.整合mybatis
我们直接使用通用mapper来整合
通用Mapper的作者也为自己的插件编写了启动器,我们直接引入即可:
<!-- 通用mapper -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.0.2</version>
</dependency>
只需要配置一下别名扫描和继承通用mapper的接口即可
# mybatis 别名扫描
mybatis:
type-aliases-package: cn.clocktt.pojo
package cn.clocktt.mapper;
import cn.clocktt.pojo.User;
import tk.mybatis.mapper.common.Mapper;
public interface UserMapper extends Mapper<User> {
}
关于pojo中的成员属性的数据类型一定要使用包装类,不然生成的SQL语句根本都不对。
package cn.clocktt.pojo;
import tk.mybatis.mapper.annotation.KeySql;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
@Table(name = "tb_user")
public class User {
//@Id代表是主键
@Id
//@keySql表示主键是否自增
@KeySql(useGeneratedKeys = true)
private Integer id;
private String name;
private Integer age;
//@Transient 表示该字段不是持久化字段,即不不是表中的字段
@Transient
private String detail;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", detail='" + detail + '\'' +
'}';
}
}
测试UserMapper接口
引入测试jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>

package cn.clocktt.mapper;
import cn.clocktt.pojo.User;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.*;
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
public void queryUser(){
User user = userMapper.selectByPrimaryKey(1);
System.out.println(user);
}
}
测试结果:

Service层
package cn.clocktt.service;
import cn.clocktt.mapper.UserMapper;
import cn.clocktt.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User findUserById(int id){
User user = userMapper.selectByPrimaryKey(id);
return User;
}
//事务控制
@Transactional
public void addUser(User user){
userMapper.insertSelective(user);
}
//事务控制
@Transactional
public void deleteUser(int id){
userMapper.deleteByPrimaryKey(id);
}
}
Controller层
package cn.clocktt.controller;
import cn.clocktt.pojo.User;
import cn.clocktt.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/user/{id}")
public User queryUserById(@PathVariable int id){
User user = userService.findUserById(id);
return user;
}
@RequestMapping("/user/add")
public String addUser(User user){
userService.addUser(user);
return "success";
}
@RequestMapping("/user/delete")
public String deleteUserById(int id){
userService.deleteUser(id);
return "success";
}
}
使用get方式测试
-查询用户

-增加用户

-删除用户

本案例的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.clocktt.demo</groupId>
<artifactId>SpringBootDemo</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--通用mapper-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.0.2</version>
</dependency>
<!--spring测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
</project>
目录结构


浙公网安备 33010602011771号