5. Spring Boot实践
接下来,我们来看看如何用SpringBoot来整合SSM,在数据库中引入一张用户表tb_user和实体类User。
tb_user表:详见 资料\tb_user.sql 文件,将该文件导入数据库中。
/* Navicat MySQL Data Transfer Source Server : local3306 Source Server Version : 50622 Source Host : localhost:3306 Source Database : springboot_test Target Server Type : MYSQL Target Server Version : 50622 File Encoding : 65001 Date: 2019-04-14 18:39:07 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for tb_user -- ---------------------------- DROP TABLE IF EXISTS `tb_user`; CREATE TABLE `tb_user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_name` varchar(100) DEFAULT NULL COMMENT '用户名', `password` varchar(100) DEFAULT NULL COMMENT '密码', `name` varchar(100) DEFAULT NULL COMMENT '姓名', `age` int(10) DEFAULT NULL COMMENT '年龄', `sex` tinyint(1) DEFAULT NULL COMMENT '性别,1男性,2女性', `birthday` date DEFAULT NULL COMMENT '出生日期', `note` varchar(255) DEFAULT NULL COMMENT '备注', `created` datetime DEFAULT NULL COMMENT '创建时间', `updated` datetime DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (`id`), UNIQUE KEY `username` (`user_name`) ) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of tb_user -- ---------------------------- INSERT INTO `tb_user` VALUES ('1', 'zhangsan', '123456', '张三', '30', '1', '1964-08-08', '张三同学在学Java', '2014-09-19 16:56:04', '2014-09-21 11:24:59'); INSERT INTO `tb_user` VALUES ('2', 'lisi', '123456', '李四', '21', '2', '1995-01-01', '李四同学在传智学Java', '2014-09-19 16:56:04', '2014-09-19 16:56:04'); INSERT INTO `tb_user` VALUES ('3', 'wangwu', '123456', '王五', '22', '2', '1994-01-01', '王五同学在学php', '2014-09-19 16:56:04', '2014-09-19 16:56:04'); INSERT INTO `tb_user` VALUES ('4', 'zhangliu', '123456', '张六', '20', '1', '1996-09-01', '张六同学在传智播客学Java', '2014-09-19 16:56:04', '2014-09-19 16:56:04'); INSERT INTO `tb_user` VALUES ('5', 'lina', '123456', '李娜', '28', '1', '1988-01-01', '李娜同学在传智播客学Java', '2014-09-19 16:56:04', '2014-09-19 16:56:04'); INSERT INTO `tb_user` VALUES ('6', 'lilei', '123456', '李雷', '23', '1', '1993-08-08', '李雷同学在传智播客学Java', '2014-09-20 11:41:15', '2014-09-20 11:41:15'); INSERT INTO `tb_user` VALUES ('7', 'hanmeimei', '123456', '韩梅梅', '24', '2', '1992-08-08', '韩梅梅同学在传智播客学php', '2014-09-20 11:41:15', '2014-09-20 11:41:15'); INSERT INTO `tb_user` VALUES ('8', 'itcast', '123456', '传智播客', '21', '2', '2008-07-08', '传智播客搞IT教育', '2014-09-20 11:41:15', '2014-09-20 11:41:15'); INSERT INTO `tb_user` VALUES ('9', 'heima', '123456', '黑马', '18', '2', '2012-08-08', '黑马是传智播客高端品牌', '2014-09-20 11:41:15', '2014-09-20 11:41:15'); INSERT INTO `tb_user` VALUES ('10', 'linus', '123456', '林纳斯', '45', '2', '1971-08-08', '林纳斯搞了linux又搞git', '2014-09-20 11:41:15', '2014-09-20 11:41:15'); INSERT INTO `tb_user` VALUES ('11', 'leijun', '123456', '雷布斯', '33', '2', '1983-08-08', '小爱同学;are you ok', '2014-09-20 11:41:15', '2014-09-20 11:41:15'); INSERT INTO `tb_user` VALUES ('12', 'madaye', '123456', '马大爷', '46', '2', '1980-08-08', '马大爷花呗可以不还吗', '2014-09-20 11:41:15', '2014-09-20 11:41:15');
创建springboot_demo\src\main\java\com\itterence\pojo\User.java 如下:
package com.itterence.pojo; import java.util.Date; public class User { // id private Long id; // 用户名 private String userName; // 密码 private String password; // 姓名 private String name; // 年龄 private Integer age; // 性别,1男性,2女性 private Integer sex; // 出生日期 private Date birthday; // 创建时间 private Date created; // 更新时间 private Date updated; // 备注 private String note; // getter和setter省略 }
5.1. Lombok
我们编写pojo时,经常需要编写构造函数和getter、setter方法,属性多的时候,就非常浪费时间,使用lombok插件可以解决这个问题:
在IDEA中安装lombok插件;不安装插件在IDEA中使用lombok的注解虽然编译能通过,但是源码会报错。所以为了让IDEA更好的辨别lombok注解则才安装插件。
注:新版Idea默认是安装好的,如下图,无需再安装了
需要在maven工程中的 文件引入依赖:
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
然后可以在Bean上使用:
@Data :自动提供getter和setter、hashCode、equals、toString等方法
@Getter:自动提供getter方法
@Setter:自动提供setter方法
@Slf4j:自动在bean中提供log变量,其实用的是slf4j的日志功能。
例如;在javabean上加@Data,那么就可以省去getter和setter等方法的编写,lombok插件会自动生成。
5.2. 整合SpringMVC
虽然默认配置已经可以使用SpringMVC了,不过我们有时候需要进行自定义配置。
可以在 application.yml 文件中配置日志级别控制:
logging: level: com.itterence: debug org.springframework: info
5.2.1. 修改端口
查看SpringBoot的全局属性可知,端口通过以下方式配置:
修改 配置文件,添加如下配置:
# 映射端口 server: port: 80
重启服务后测试:
5.2.2. 访问静态资源
现在,我们的项目是一个jar工程,那么就没有webapp,我们的静态资源该放哪里呢?
回顾我们在上面看的源码,有一个叫做ResourceProperties的类,里面就定义了静态资源的默认查找路径:
默认的静态资源路径为:
classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public
只要静态资源放在这些目录中任何一个,SpringMVC都会帮我们处理。
我们习惯会把静态资源放在 classpath:/static/ 目录下。我们创建目录 static ,并且从资料文件夹中复制 itcast.gif 和 test.js 如下:
重启项目后测试:
注意:如果访问图片时候没有显示;可以先将项目先clean再启动,或者创建 public、resources 文件夹,然后 图片放置到public或resources中。
5.2.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 @Configuration class of type WebMvcConfigurer but without @EnableWebMvc . If you wish to provide custom instances of RequestMappingHandlerMapping , RequestMappingHandlerAdapter , or
ExceptionHandlerExceptionResolver , you can declare a WebMvcRegistrationsAdapter instance to provide such components.
If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc .
翻译:
如果你想要保持Spring Boot 的一些默认MVC特征,同时又想自定义一些MVC配置(包括:拦截器,格式化器, 视图控制器、消息转换器 等等),你应该让一个类实现 WebMvcConfigurer ,并且添加 @Configuration 注解,但是千万不要加 @EnableWebMvc 注解。如果你想要自定义 HandlerMapping 、 HandlerAdapter 、
ExceptionResolver 等组件,你可以创建一个 WebMvcRegistrationsAdapter 实例 来提供以上组件。 如果你想要完全自定义SpringMVC,不保留SpringBoot提供的一切特征,你可以自己定义类并且添加
@Configuration 注解和 @EnableWebMvc 注解
总结:通过实现 WebMvcConfigurer 并添加 @Configuration 注解来实现自定义部分SpringMvc配置。
1. 创建 springboot_demo\src\main\java\com\itterence\interceptor\MyInterceptor.java 拦截器,内容如下:
package com.itterence.interceptor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Slf4j public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { log.debug("这是MyInterceptor拦截器的preHandle方法"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { log.debug("这是MyInterceptor拦截器的postHandle方法"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { log.debug("这是MyInterceptor拦截器的afterCompletion方法"); } }
2. 定义配置类 heima-springboot\src\main\java\com\itheima\config\MvcConfig.java ,用于注册拦截器,内容如下:
package com.itterence.config; import com.itterence.interceptor.MyInterceptor; 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 { /** * 将拦截器注册到spring ioc容器 * /@return myInterceptor */ @Bean public MyInterceptor myInterceptor(){ return new MyInterceptor(); } /** * 重写该方法;往拦截器链添加自定义拦截器 * @param registry 拦截器链 */ @Override public void addInterceptors(InterceptorRegistry registry) { //通过registry添加myInterceptor拦截器,并设置拦截器路径为 /* registry.addInterceptor(myInterceptor()).addPathPatterns("/*"); } }
结构如下:
接下来访问http://localhost/hello 并查看日志:
5.3. 整合jdbc和事务
spring中的jdbc连接和事务是配置中的重要一环,在SpringBoot中该如何处理呢?
答案是不需要处理,我们只要找到SpringBoot提供的启动器即可,在 pom.xml 文件中添加如下依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency>
当然,不要忘了数据库驱动,SpringBoot并不知道我们用的什么数据库,这里我们选择MySQL;同样的在 pom.xml 文件中添加如下依赖:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.46</version> </dependency>
至于事务,SpringBoot中通过注解来控制。就是我们熟知的@Transactional 使用的时候设置在对应的类或方法上即可。
创建 springboot_demo\src\main\java\com\itterence\service\UserService.java 业务类如下:
package com.itterence.service; import com.itterence.pojo.User; import org.springframework.transaction.annotation.Transactional; public class UserService { public User queryById(Long id){ //根据id查询 return new User(); } @Transactional public void saveUser(User user){ System.out.println("新增用户..."); } }
5.4. 整合连接池
其实,在刚才引入jdbc启动器的时候,SpringBoot已经自动帮我们引入了一个连接池:
HikariCP应该是目前速度最快的连接池了,我们看看它与c3p0的对比:
因此,我们只需要指定连接池参数即可;打开 application.yml 添加修改配置如下:
spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://192.168.1.105:3306/demo_springboot username: root password: 646453
【注意】
把 JdbcConfig 类中的druid的配置删除或注释;
在配置完hikari数据库连接池后的 application.yml 文件如下:
启动项目,访问 http://localhost/hello ;查看后台输出,一样可以在HelloController中获取到datasource。