Spring Boot应用(整合其他工具和框架)


一、Lombok

我们编写pojo时,经常需要编写构造函数和getter、setter方法,属性多的时候,就非常浪费时间,使用lombok插件可以解决这个问题:

在IDEA中安装lombok插件;不安装插件在IDEA中使用lombok的注解虽然编译能通过,但是源码会报错。所以为了让IDEA更好的辨别lombok注解则才安装插件。

需在pom.xml文件中引入依赖

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

然后可以在Bean上使用:
@Data :自动提供getter和setter、hashCode、equals、toString等方法
@Getter:自动提供getter方法
@Setter:自动提供setter方法
@Slf4j:自动在bean中提供log变量,其实用的是slf4j的日志功能

//在编译时自动生成get,set,hashcode,equals,toString等方法
@Data
public class User {
    private Long id;
    private String name;
    private Integer age;
}

二、整合SpringMVC

虽然默认配置已经可以使用SpringMVC了,不过我们有时候需要进行自定义配置。

1、修改日志级别

可以在 application.yml 文件中配置日志级别控制:

#日志记录级别
logging:
  level:
    cn.rewind: debug
    org.springframework: info

2、修改端口

#修改tomcat的端口
server:
  port: 80

3、访问静态资源

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

默认的静态资源路径为:
classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public

只要静态资源放在这些目录中任何一个,SpringMVC都会帮我们处理。
习惯会把静态资源放在 classpath:/static/ 目录下。

在这里插入图片描述
可通过路径直接访问静态资源:js文件、图片等。

注意:如果访问图片时候没有显示;可以先将项目先clean再启动,或者创建 public、resources 文件夹,然后图片放置到public或resources中。

4、添加拦截器

拦截器不是一个普通属性,而是一个类,所以就要用到java配置方式了。

以下为官方文档说明翻译
如果你想要保持Spring Boot 的一些默认MVC特征,同时又想自定义一些MVC配置(包括:拦截器,格式化器,视图控制器、消息转换器 等等),你应该让一个类实现 WebMvcConfigurer ,并且添加 @Configuration 注解,但是千万不要加 @EnableWebMvc 注解。

如果你想要自定义 HandlerMapping 、 HandlerAdapter 、ExceptionResolver 等组件,你可以创建一个 ebMvcRegistrationsAdapter 实例 来提供以上组件。

如果你想要完全自定义SpringMVC,不保留SpringBoot提供的一切特征,你可以自己定义类并且添加@Configuration 注解和 @EnableWebMvc 注解。

总结通过实现 WebMvcConfigurer 并添加 @Configuration 注解来实现自定义部分SpringMvc配置。

(1)创建拦截器com\rewind\interceptor\MyInterceptor.java

@Slf4j
public class MyInterceptor implements HandlerInterceptor {
    //在目标方法执行之前 执行
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        log.debug("MyInterceptor的preHandle方法");
        return true;
    }

    //在目标方法执行之后 视图对象返回之前执行
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        log.debug("MyInterceptor的postHandle方法");
    }

     //在流程都执行完毕后 执行
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        log.debug("MyInterceptor的afterCompletion方法");
    }
}

(2)定义配置类com\rewind\config\MvcConfig.java,用于注册拦截器

@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("/*");
    }
}

三、整合jdbc和事务

1、事务

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 使用的时候设置在对应的类或方法上即可。

值得注意的是:如果需要使用 synchronized 进行并发控制的话,synchronized 作用范围一定要比 @Transactional 大,否则仍会出现超卖问题。synchronized 代码块可以加在 Controller

@Service
public class UserService {
    public User queryById(Long id){
        //根据id查询
        return new User();
    }

    @Transactional
    public void saveUser(User user){
        System.out.println("新增用户...");
    }
}

2、连接池

才引入jdbc启动器的时候,SpringBoot已经自动帮我们引入了一个连接池:
HikariCP应该是目前速度最快的连接池了

因此,我们只需要指定连接池参数即可;打开 application.yml 添加修改配置如下:

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=GMT%2B8
    username: root
    password: root

url后面的参数?useSSL=false&serverTimezone=GMT%2B8

(1)useSSL=false:

MySQL在高版本需要指明是否进行SSL连接。
使用该参数可禁用SSL

   SSL协议提供服务主要:         
       1)认证用户服务器,确保数据发送到正确的服务器;    .
       2)加密数据,防止数据传输途中被窃取使用;
       3)维护数据完整性,验证数据在传输过程中是否丢失;

   当前支持SSL协议两层:
            SSL记录协议(SSL Record Protocol):建立靠传输协议(TCP)高层协议提供数据封装、压缩、加密等基本功能支持
        SSL握手协议(SSL Handshake Protocol):建立SSL记录协议用于实际数据传输始前通讯双进行身份认证、协商加密
        算法、 交换加密密钥等。

(2)serverTimezone=GMT%2B8 指定时区

这个时区要设置好,不然会出现时差,如果你设置serverTimezone=UTC,连接不报错,但是我们在用java代码插入到数据库时间的时候却出现了问题。

比如在java代码里面插入的时间为:2018-06-24 17:29:56
但是在数据库里面显示的时间却为:2018-06-24 09:29:56

有了8个小时的时差UTC代表的是全球标准时间 ,但是我们使用的时间是北京时区也就是东八区,领先UTC八个小时。

//北京时间东八区
serverTimezone=GMT%2B8 
//或者使用上海时间
serverTimezone=Asia/Shanghai

四、整合Mybatis

1、依赖

<!--springboot整合mybatis依赖-->
<dependencies>
    <dependency>
         <groupId>org.mybatis.spring.boot</groupId>
         <artifactId>mybatis-spring-boot-starter</artifactId>
         <version>2.0.1</version>
     </dependency>
</dependencies>

<!--将配置文件放在 resource 文件夹中
对于 Maven 项目,可指定 POM 文件的 resource
注意!Maven 多模块项目的扫描路径需以 classpath*: 开头 (即加载多个 jar 包下的 XML 文件)-->
<build>
  <resources>
      <resource>
          <!-- xml放在java目录下-->
          <directory>src/main/java</directory>
          <includes>
              <include>**/*.xml</include>
          </includes>
      </resource>
      <!--指定资源的位置(xml放在resources下,可以不用指定)-->
      <resource>
          <directory>src/main/resources</directory>
      </resource>
  </resources>
</build>

2、配置application.yml

# mybatis配置
mybatis:
  # 实体类别名包路径
  type-aliases-package: com.rewind.pojo
  # 映射文件路径
  # mapper-locations: classpath:mappers/*.xml
  configuration:
    # 控制台输出执行sql
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

3、配置mapper扫描

需要注意,这里没有配置mapper接口扫描包,因此我们需要给每一个Mapper接口添加 @Mapper 注解,才能被识别。

@Mapper
public interface UserMapper {
}

或者,我们也可以不加注解,而是在启动类上添加扫描包注解(推荐):

@SpringBootApplication
@MapperScan("com.rewind.mapper")
public class Application {
    public static void main(String[] args) {
        // 启动代码
        SpringApplication.run(Application.class, args);
    }
}

五、整合MyBatisPlus

1、依赖

<!-- mybatis - plus -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.0.5</version>
</dependency>

2、配置xml路径

#配置mapper xml文件的路径
mybatis-plus:
  mapper-locations: classpath:com/rewind/test01/mapper/xml/*.xml

3、启动类

@MapperScan("com.rewind.test01.mapper")

六、通用mapper方式整合Mybatis

1、引入依赖坐标

 <!-- 通用mapper -->
<dependency>
     <groupId>tk.mybatis</groupId>
     <artifactId>mapper-spring-boot-starter</artifactId>
     <version>2.1.5</version>
 </dependency>

注意:一旦引入了通用Mapper的启动器,会覆盖Mybatis官方启动器的功能,因此需要移除对官方Mybatis启动器的依赖。

2、编写UserMapper

编写UserMapper
无需任何配置就可以使用了。如果有特殊需要,可以到通用mapper官网查看
https://github.com/abel533/Mapper/wiki/3.config

import cn.rewind.pojo.User;
import tk.mybatis.mapper.common.Mapper;

public interface UserMapper extends Mapper<User> {
}

包别导错了

3、修改启动类上的注解

把启动类上的@MapperScan注解修改为通用mapper中自带的:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tk.mybatis.spring.annotation.MapperScan;

//Springboot项目启动器
@SpringBootApplication
//通用mapper
@MapperScan("cn.rewind.mapper")
public class Application {

    public static void main(String[] args) {

        SpringApplication.run(Application.class,args);
    }
} 

4、在User实体类上加JPA注解

//在编译时自动生成get,set,hashcode,equals,toString等方法
@Data
@Table(name = "tb_user")
public class User {
    //主键
    @Id
    //主键回填,即新增数据时,对象中主键是没有值的,新增后在数据库中生成主键,然后回填到对象中
    @KeySql(useGeneratedKeys = true)
    private Long id;

    //当对象属性和数据库字段名称相同,或符合驼峰命名法,或符合user_name --> userName时,此注解可不加
    //否则应在注解内的name属性中指定相应的数据库字段名称
    //@Column(name = "user_name")
    private String userName;

  ``private String name;

    private Integer age;
}
通用mapper不认识int类型,尽量都用包装类。

5、编写UserService

@Service
public class UserService {

   @Autowired
   private UserMapper userMapper;

    //根据id查询user
    public User findUserById(long id){
        User user = userMapper.selectByPrimaryKey(id);
        return user;
    }

    //新增保存用户
    @Transactional
    public void saveUser(User user){
        //选择性新增,如果属性为空,则不出现在insert语句上
        userMapper.insertSelective(user);
    }
}

6、编写Controller

@RestController
public class HelloController {
    @Autowired
    private UserService userService;

    /**
    * 根据id获取用户
    */
    @GetMapping("/user/{id}")
    public User queryById(@PathVariable Long id){
        return userService.queryById(id);
    }
}

7、测试

启动项目,当访问localhost/user/1时,即会把id为1的用户信息 打印到网页上

七、Junit测试

1、依赖

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

2、编写测试类

com\rewind\service\UserServiceTest

在测试类上面必须要添加 @SpringBootTest 注解

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {
    @Autowired
    private UserService userService;

    @Test
    public void queryById() {
        User user = userService.queryById(1L);
        System.out.println("user = " + user);
    }
    @Test
    public void saveUser() {
        User user = new User();
        user.setUserName("test");
    }
}

八、整合Redis

1、依赖

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

2、配置application.yml

spring:
  redis:
    host: localhost
    port: 6379

3、测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTest {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void test(){
        //string 字符串
        //redisTemplate.opsForValue().set("str", "rewind");
        redisTemplate.boundValueOps("str").set("rewind");
        System.out.println("str = " + redisTemplate.opsForValue().get("str"));

        //hash 散列
        redisTemplate.boundHashOps("h_key").put("name", "rewind");
        redisTemplate.boundHashOps("h_key").put("age", 13);
        //获取所有域
        Set set = redisTemplate.boundHashOps("h_key").keys();
        System.out.println(" hash散列的所有域:" + set);
        //获取所有值
        List list = redisTemplate.boundHashOps("h_key").values();
        System.out.println(" hash散列的所有域的值:" + list);

        //list 列表
        redisTemplate.boundListOps("l_key").leftPush("c");
        redisTemplate.boundListOps("l_key").leftPush("b");
        redisTemplate.boundListOps("l_key").leftPush("a");
        //获取全部元素
        list = redisTemplate.boundListOps("l_key").range(0, -1);
        System.out.println(" list列表中的所有元素:" + list);

        // set 集合
        redisTemplate.boundSetOps("s_key").add("a", "b", "c");
        set = redisTemplate.boundSetOps("s_key").members();
        System.out.println(" set集合中的所有元素:" + set);

        // sorted set 有序集合
        redisTemplate.boundZSetOps("z_key").add("a", 30);
        redisTemplate.boundZSetOps("z_key").add("b", 20);
        redisTemplate.boundZSetOps("z_key").add("c", 10);
        set = redisTemplate.boundZSetOps("z_key").range(0, -1);
        System.out.println(" zset有序集合中的所有元素:" + set);
    }
}

结果

在这里插入图片描述

九、热部署

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>

项目或者页面修改以后:Ctrl+F9

十、项目部署

1、项目打包

(1) 添加项目的pom.xml插件;

在pom.xml要显式的加入插件spring-boot-maven-plugin,否则无法产生 jar 清单文件,导致打出来的 jar 无法使用命令运行;

注意:是插件,不是依赖

<build>
        <plugins>
            <!-- 打jar包时如果不配置该插件,打出来的jar包没有清单文件 -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
</build>

(2)使用maven的命令package打包;

打包路径
在这里插入图片描述

(3)运行

运行打出来的包;使用命令: java –jar 包全名 或者写一个 bat 文件,里面包含 java –jar 包全名;这样就可以双击启动应用。
如执行上述打出来的jar的命令为:

java -jar myspringboot-1.0-SNAPSHOT.jar

测试则可使用浏览器访问:http://localhost/user/8


  目录