SpringBoot学习之整合Mybatis+Redis

一、SpringBoot简单介绍

百度百科是这样的:

Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。通过这种方式,Spring Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。

其他人概括是这样的:

(1)它是Spring的升级版,Spring容器能做到的事情,它都能做到,而且更简便,从配置形式上来说,SpringBoot完全抛弃了繁琐的XML文件配置方式,而是替代性地用注解方式来实现,虽然本质来说,是差不多的(类似包扫描,注解扫描,类加载之类)。 
(2)SpringBoot集成的插件更多,从而使用很多服务,都只是引入一个依赖,几个注解和Java类就可以用了,具体的参考相关手册。 

(3)在Web应用开发这一块,之前的应用一般来说是打包成war包,再发布到相关服务器容器下(例如Tomcat),虽然SpringBoot也可以这么做,但在SpringBoot下更常见的形式是将SpringBoot应用打包成可执行jar包文件。之所以这么做,源于你可以直接将SpringBoot应用看成是一个Java Application,其Web应用可以没有webapp目录(更不用说web.xml了),它推荐使用html页面,并将其作为静态资源使用。 

二、框架搭建

(1)整体结构如下:


(2)pom文件如下所示

<?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>SpringBootTest</groupId>
    <artifactId>springbootdemo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>spring-web-demo</name>
    <description>demo for spring boot</description>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.0.RELEASE</version>
        <relativePath/>
    </parent>
    <dependencies>
        <!--  web启动依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--日志打印依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </dependency>
        <!--- redis依赖 -->
        <!-- 自动配置Redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- mybatis依赖-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!-- mysql数据库依赖-->
        <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.21</version>
        </dependency>
        <!--分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>4.2.1</version>
        </dependency>
        <!--通用Mapper-->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper</artifactId>
            <version>3.3.9</version>
        </dependency>
        <!--SpringBoot测试依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.jayway.jsonpath</groupId>
            <artifactId>json-path</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

(3)log配置和application配置

扫描二维码关注公众号,回复: 3264707 查看本文章
spring.datasource.url=jdbc:mysql://localhost:3306/cqx
spring.datasource.username=root
spring.datasource.password=123
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=localhost
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)
spring.redis.timeout=0


<?xml version="1.0" encoding="UTF-8"?>

<configuration debug="false">
    <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
    <property name="LOG_HOME" value="D:/Mytest/SpringBoot/logs" />
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>
    <!-- 按照每天生成info日志文件 -->
    <appender name="LOGINFO"  class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${LOG_HOME}/SpringBoot_info.log.%d{yyyy-MM-dd}.log</FileNamePattern>
            <!--日志文件保留天数-->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <!--这里设置日志级别为info-->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <!--日志文件最大的大小-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>
    <!-- 按照每天生成erro日志文件 -->
    <appender name="LOGERROR"  class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${LOG_HOME}/SpringBootDemo_error.log.%d{yyyy-MM-dd}.log</FileNamePattern>
            <!--日志文件保留天数-->
            <MaxHistory>30</MaxHistory>
        </rollingPolicy>
        <!--这里设置日志级别为info-->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>error</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
        <!--日志文件最大的大小-->
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
            <MaxFileSize>10MB</MaxFileSize>
        </triggeringPolicy>
    </appender>
    <!-- 日志输出级别 -->
    <root level="DEBUG">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="LOGERROR" />
        <appender-ref ref="LOGINFO" />
    </root>
</configuration>

(4)建立bean类 User.class

package com.server.bean;

/**
 * Created by c00415904 on 2017/9/21.
 */
public class User {
    private String username;
    private String userpassword;
    public User(){}
    public User(String username,String userpassword){
        this.userpassword=userpassword;
        this.username=username;
    }
    public String getUsername(){
        return this.username;
    }
    public String getUserpassword(){
        return this.userpassword;
    }
    public void setUsername(String username){
        this.username=username;
    }
    public void setUserpassword(String password){
        this.userpassword=password;
    }
}

(5)数据库持久化层接口Dao 对接Mybaits,开启catch功能

package com.server.dao;

import com.server.bean.User;
import org.apache.ibatis.annotations.*;
import org.springframework.cache.annotation.Cacheable;

/**
 * Created by c00415904 on 2017/9/21.
 */
@Mapper
public interface UserDao
{
    @Cacheable(value = "username",key = "#p0")
    @Select("select *  from user_table where username = #{username}")
    User findByName(@Param("username") String name);


    @Insert("insert into user_table values (#{username},#{userpassword})")
    int insertUser(@Param("username")String username,@Param("userpassword")String userpassword);


    @Select("select count(*) from user_table")
    int findCount();


    @Delete("delete from user_table where username = #{username}")
    int deleteByName(@Param("username") String username);

    @Update("update user_table set userpassword = #{userpassword} where username= #{username}")
    int updateUser(@Param("username") String username,@Param("userpassword") String userpassword);

}

(6)服务对外接口  TestInterFace 以及实现类 TestInterFaceImpl

package com.server.service.dao;

import com.server.bean.User;
import org.springframework.stereotype.Service;

/**
 * Created by c00415904 on 2017/9/21.
 */
public interface TestInterFace {
    public int testInterFace();
    public User testUser(String username);
    public int testinsertUser(String username,String userpassword);
}

package com.server.service.impl;

import com.server.bean.User;
import com.server.dao.UserDao;
import com.server.service.dao.TestInterFace;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * Created by c00415904 on 2017/9/21.
 */
@Service
public class TestInterFaceImpl implements TestInterFace {
    @Autowired
    private UserDao userDao;

    @Override
    public int testInterFace() {
        return userDao.findCount();
    }

    @Override
    public User testUser(String username) {
        return userDao.findByName(username);
    }

    @Override
    public int testinsertUser(String username, String userpassword) {
        return userDao.insertUser(username,userpassword);
    }
}

(7)controller类  所有的rest入口

package com.server.controller;

import com.server.bean.User;
import com.server.service.dao.TestInterFace;
import com.server.service.impl.TestInterFaceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * Created by c00415904 on 2017/9/21.
 */
@Controller
public class UserController {
    private final Logger log = LoggerFactory.getLogger(UserController.class);
    @Autowired
    private TestInterFace testInterFace;
    @RequestMapping("/getuser")
    @ResponseBody
    User getUser(@RequestParam("name") String name)
    {
        log.warn("Get user {}",name);
        return testInterFace.testUser(name);
    }
    @RequestMapping("/adduser")
    @ResponseBody
    String addUser(String name,String password)
    {
        try {
            log.warn("Insert user,{},{}", name, password);
            if (testInterFace.testinsertUser(name, password) >= 0) {
                return "ok";
            } else {
                return "error";
            }
        }catch (Exception ex){
            log.error("error add user:{}",ex);
            return "error";
        }
    }
}

package com.server.controller;

import com.server.service.dao.TestInterFace;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * Created by c00415904 on 2017/9/21.
 */
@Controller
public class TestController
{
    private final Logger log = LoggerFactory.getLogger(TestController.class);
    @Autowired
    private TestInterFace testInterFace;
    @RequestMapping("/num")
    @ResponseBody
    int num()
    {
        log.info("get num");
        return testInterFace.testInterFace();
    }
}

(8)redis和mybits配置类,mybits配置未使用不做解析

package com.server.config.redis;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

import javax.print.DocFlavor;

/**
 * Created by c00415904 on 2018/6/21.
 */
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport{
    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.timeout}")
    private int timeout;
    @Bean
    public CacheManager cacheManager(@SuppressWarnings("rawtypes")RedisTemplate redisTemplate){
        RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
        //设置过期时间
        cacheManager.setDefaultExpiration(10000);
        return cacheManager;
    }
    @Bean
    public RedisTemplate<String,String> redisTemplate(RedisConnectionFactory factory){
        //创建一个模板类
        StringRedisTemplate template = new StringRedisTemplate();
        //将刚才的redis连接工厂设置到模板类中
        template.setConnectionFactory(factory);
        //设置序列化工具
        setSerializer(template);
        template.afterPropertiesSet();
        return template;
    }
    private void setSerializer(StringRedisTemplate template){
        @SuppressWarnings({"rawtypes","unchecked"})
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        template.setValueSerializer(jackson2JsonRedisSerializer);
    }
}

(9)程序启动类

package com.server;

import com.server.config.redis.RedisConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;

/**
 * Created by c00415904 on 2017/9/8.
 * 程序的入口
 */
@SpringBootApplication
@EnableCaching
@ComponentScan(basePackages={"com.server"})//添加的注解,扫描自动注入的接口和类
public class Application
{
    public static void main(String[] args)
    {
        SpringApplication.run(Application.class,args);
    }
}


三、程序测试


看下程序日志:

2018-06-22 11:28:50.078 [http-nio-8080-exec-9] DEBUG o.s.boot.web.filter.OrderedRequestContextFilter - Bound request context to thread: org.apache.catalina.connector.RequestFacade@3774a2cd
2018-06-22 11:28:50.078 [http-nio-8080-exec-9] DEBUG org.springframework.web.servlet.DispatcherServlet - DispatcherServlet with name 'dispatcherServlet' processing POST request for [/getuser]
2018-06-22 11:28:50.078 [http-nio-8080-exec-9] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Looking up handler method for path /getuser
2018-06-22 11:28:50.079 [http-nio-8080-exec-9] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Returning handler method [com.server.bean.User com.server.controller.UserController.getUser(java.lang.String)]
2018-06-22 11:28:50.079 [http-nio-8080-exec-9] DEBUG o.s.b.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'userController'
2018-06-22 11:28:50.079 [http-nio-8080-exec-9] WARN  com.server.controller.UserController - Get user cqx5
2018-06-22 11:28:50.079 [http-nio-8080-exec-9] DEBUG o.s.data.redis.core.RedisConnectionUtils - Opening RedisConnection
2018-06-22 11:28:50.080 [http-nio-8080-exec-9] DEBUG o.s.data.redis.core.RedisConnectionUtils - Closing Redis Connection
2018-06-22 11:28:50.081 [http-nio-8080-exec-9] DEBUG org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
2018-06-22 11:28:50.081 [http-nio-8080-exec-9] DEBUG org.mybatis.spring.SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@45ee034e] was not registered for synchronization because synchronization is not active
2018-06-22 11:28:50.081 [http-nio-8080-exec-9] DEBUG o.springframework.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
2018-06-22 11:28:50.084 [http-nio-8080-exec-9] DEBUG o.m.spring.transaction.SpringManagedTransaction - JDBC Connection [ProxyConnection[PooledConnection[com.mysql.jdbc.JDBC4Connection@1e4779db]]] will not be managed by Spring
2018-06-22 11:28:50.084 [http-nio-8080-exec-9] DEBUG com.server.dao.UserDao.findByName - ==>  Preparing: select * from user_table where username = ? 
2018-06-22 11:28:50.084 [http-nio-8080-exec-9] DEBUG com.server.dao.UserDao.findByName - ==> Parameters: cqx5(String)
2018-06-22 11:28:50.085 [http-nio-8080-exec-9] DEBUG com.server.dao.UserDao.findByName - <==      Total: 1
2018-06-22 11:28:50.086 [http-nio-8080-exec-9] DEBUG org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@45ee034e]
2018-06-22 11:28:50.086 [http-nio-8080-exec-9] DEBUG o.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
2018-06-22 11:28:50.086 [http-nio-8080-exec-9] DEBUG o.s.data.redis.core.RedisConnectionUtils - Opening RedisConnection
2018-06-22 11:28:50.087 [http-nio-8080-exec-9] DEBUG o.s.data.redis.core.RedisConnectionUtils - Closing Redis Connection
2018-06-22 11:28:50.088 [http-nio-8080-exec-9] DEBUG o.s.w.s.m.m.a.RequestResponseBodyMethodProcessor - Written [com.server.bean.User@7d5b8022] as "application/json" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@497d4c96]
2018-06-22 11:28:50.088 [http-nio-8080-exec-9] DEBUG org.springframework.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2018-06-22 11:28:50.088 [http-nio-8080-exec-9] DEBUG org.springframework.web.servlet.DispatcherServlet - Successfully completed request
2018-06-22 11:28:50.088 [http-nio-8080-exec-9] DEBUG o.s.boot.web.filter.OrderedRequestContextFilter - Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@3774a2cd

第一次的时候,redis没有缓存,所以查询了数据库,然后写入了缓存。

再运行一下查询postman,第二次测试查看日志:


只查询了redis缓存。


注意:需要启动redis服务:


猜你喜欢

转载自blog.csdn.net/chaiqunxing51/article/details/80771030