├── README.md ├── pom.xml └── src └── main ├── java └── com │ └── fei │ └── springboot │ ├── Application.java │ ├── config │ ├── mybatis │ │ ├── DatasourceConfig.java │ │ ├── MybatisConfiguration.java │ │ └── SqlPrintInterceptor.java │ └── redis │ │ └── RedisConfiguration.java │ ├── controller │ └── UserController.java │ ├── dao │ ├── UserMapper.java │ └── UserMapper.xml │ ├── domain │ └── User.java │ └── service │ └── UserService.java └── resources ├── application.yml ├── logback.xml └── mybatis-config.xml /README.md: -------------------------------------------------------------------------------- 1 | # spring-boot-mybatis-redis 2 | spring boot+mybatis+redis数据缓存整合 3 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | com.fei.springboot 4 | springboot-mybatis-redis 5 | 0.0.1-SNAPSHOT 6 | 7 | 8 | 9 | alimaven 10 | http://maven.aliyun.com/nexus/content/repositories/central/ 11 | 12 | true 13 | 14 | 15 | true 16 | 17 | 18 | 19 | 20 | 21 | 22 | alimaven 23 | http://maven.aliyun.com/nexus/content/repositories/central/ 24 | 25 | true 26 | 27 | 28 | true 29 | 30 | 31 | 32 | 33 | 34 | 35 | UTF-8 36 | UTF-8 37 | 38 | UTF-8 39 | 40 | 1.5.2.RELEASE 41 | 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-starter-parent 46 | 1.5.2.RELEASE 47 | 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-starter-web 53 | 54 | 55 | 56 | org.mybatis.spring.boot 57 | mybatis-spring-boot-starter 58 | 1.3.0 59 | 60 | 61 | 62 | org.springframework.boot 63 | spring-boot-starter-redis 64 | 1.4.3.RELEASE 65 | 66 | 67 | 68 | mysql 69 | mysql-connector-java 70 | 71 | 72 | com.alibaba 73 | druid 74 | 1.1.10 75 | 76 | 77 | 78 | 79 | com.github.pagehelper 80 | pagehelper 81 | 4.1.6 82 | 83 | 84 | 85 | 86 | 87 | src 88 | 89 | 90 | maven-compiler-plugin 91 | 92 | 93 | 1.7 94 | 1.7 95 | UTF-8 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /src/main/java/com/fei/springboot/Application.java: -------------------------------------------------------------------------------- 1 | package com.fei.springboot; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.boot.builder.SpringApplicationBuilder; 7 | import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer; 8 | import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer; 9 | import org.springframework.boot.web.support.SpringBootServletInitializer; 10 | import org.springframework.context.annotation.ComponentScan; 11 | 12 | @EnableAutoConfiguration 13 | @ComponentScan(basePackages={"com.fei.springboot"}) 14 | @SpringBootApplication 15 | public class Application extends SpringBootServletInitializer implements EmbeddedServletContainerCustomizer{ 16 | 17 | @Override 18 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 19 | return application.sources(Application.class); 20 | } 21 | 22 | 23 | public static void main(String[] args) throws Exception { 24 | SpringApplication.run(Application.class, args); 25 | } 26 | 27 | public void customize(ConfigurableEmbeddedServletContainer configurableEmbeddedServletContainer) { 28 | // configurableEmbeddedServletContainer.setPort(9090); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/fei/springboot/config/mybatis/DatasourceConfig.java: -------------------------------------------------------------------------------- 1 | package com.fei.springboot.config.mybatis; 2 | 3 | import java.sql.SQLException; 4 | 5 | import javax.sql.DataSource; 6 | 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.beans.factory.annotation.Value; 10 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 11 | import org.springframework.boot.web.servlet.ServletRegistrationBean; 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.context.annotation.Configuration; 14 | import org.springframework.context.annotation.Primary; 15 | 16 | import com.alibaba.druid.pool.DruidDataSource; 17 | import com.alibaba.druid.support.http.StatViewServlet; 18 | import com.alibaba.druid.support.http.WebStatFilter; 19 | 20 | @Configuration 21 | public class DatasourceConfig { 22 | private Logger logger = LoggerFactory.getLogger(DatasourceConfig.class); 23 | 24 | @Value("${spring.datasource.url}") 25 | private String dbUrl; 26 | 27 | @Value("${spring.datasource.type}") 28 | private String dbType; 29 | 30 | @Value("${spring.datasource.username}") 31 | private String username; 32 | 33 | @Value("${spring.datasource.password}") 34 | private String password; 35 | 36 | @Value("${spring.datasource.driver-class-name}") 37 | private String driverClassName; 38 | 39 | @Value("${spring.datasource.initialSize}") 40 | private int initialSize; 41 | 42 | @Value("${spring.datasource.minIdle}") 43 | private int minIdle; 44 | 45 | @Value("${spring.datasource.maxActive}") 46 | private int maxActive; 47 | 48 | @Value("${spring.datasource.maxWait}") 49 | private int maxWait; 50 | 51 | @Value("${spring.datasource.timeBetweenEvictionRunsMillis}") 52 | private int timeBetweenEvictionRunsMillis; 53 | 54 | @Value("${spring.datasource.minEvictableIdleTimeMillis}") 55 | private int minEvictableIdleTimeMillis; 56 | 57 | @Value("${spring.datasource.validationQuery}") 58 | private String validationQuery; 59 | 60 | @Value("${spring.datasource.testWhileIdle}") 61 | private boolean testWhileIdle; 62 | 63 | @Value("${spring.datasource.testOnBorrow}") 64 | private boolean testOnBorrow; 65 | 66 | @Value("${spring.datasource.testOnReturn}") 67 | private boolean testOnReturn; 68 | 69 | @Value("${spring.datasource.poolPreparedStatements}") 70 | private boolean poolPreparedStatements; 71 | 72 | @Value("${spring.datasource.filters}") 73 | private String filters; 74 | 75 | @Value("${spring.datasource.connectionProperties}") 76 | private String connectionProperties; 77 | 78 | @Value("${spring.datasource.useGlobalDataSourceStat}") 79 | private boolean useGlobalDataSourceStat; 80 | 81 | @Value("${spring.datasource.druidLoginName}") 82 | private String druidLoginName; 83 | 84 | @Value("${spring.datasource.druidPassword}") 85 | private String druidPassword; 86 | 87 | @Bean(name="dataSource",destroyMethod = "close", initMethod="init") 88 | @Primary //不要漏了这 89 | public DataSource dataSource(){ 90 | DruidDataSource datasource = new DruidDataSource(); 91 | try { 92 | datasource.setUrl(this.dbUrl); 93 | datasource.setDbType(dbType); 94 | datasource.setUsername(username); 95 | datasource.setPassword(password); 96 | datasource.setDriverClassName(driverClassName); 97 | datasource.setInitialSize(initialSize); 98 | datasource.setMinIdle(minIdle); 99 | datasource.setMaxActive(maxActive); 100 | datasource.setMaxWait(maxWait); 101 | datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); 102 | datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); 103 | datasource.setValidationQuery(validationQuery); 104 | datasource.setTestWhileIdle(testWhileIdle); 105 | datasource.setTestOnBorrow(testOnBorrow); 106 | datasource.setTestOnReturn(testOnReturn); 107 | datasource.setPoolPreparedStatements(poolPreparedStatements); 108 | datasource.setFilters(filters); 109 | } catch (SQLException e) { 110 | logger.error("druid configuration initialization filter", e); 111 | } 112 | return datasource; 113 | } 114 | 115 | ///////// 下面是druid 监控访问的设置 ///////////////// 116 | @Bean 117 | public ServletRegistrationBean druidServlet() { 118 | ServletRegistrationBean reg = new ServletRegistrationBean(); 119 | reg.setServlet(new StatViewServlet()); 120 | reg.addUrlMappings("/druid/*"); //url 匹配 121 | reg.addInitParameter("allow", "192.168.16.110,127.0.0.1"); // IP白名单 (没有配置或者为空,则允许所有访问) 122 | reg.addInitParameter("deny", "192.168.16.111"); //IP黑名单 (存在共同时,deny优先于allow) 123 | reg.addInitParameter("loginUsername", this.druidLoginName);//登录名 124 | reg.addInitParameter("loginPassword", this.druidPassword);//登录密码 125 | reg.addInitParameter("resetEnable", "false"); // 禁用HTML页面上的“Reset All”功能 126 | return reg; 127 | } 128 | 129 | @Bean(name="druidWebStatFilter") 130 | public FilterRegistrationBean filterRegistrationBean() { 131 | FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); 132 | filterRegistrationBean.setFilter(new WebStatFilter()); 133 | filterRegistrationBean.addUrlPatterns("/*"); 134 | filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); //忽略资源 135 | filterRegistrationBean.addInitParameter("profileEnable", "true"); 136 | filterRegistrationBean.addInitParameter("principalCookieName", "USER_COOKIE"); 137 | filterRegistrationBean.addInitParameter("principalSessionName", "USER_SESSION"); 138 | return filterRegistrationBean; 139 | } 140 | 141 | } -------------------------------------------------------------------------------- /src/main/java/com/fei/springboot/config/mybatis/MybatisConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.fei.springboot.config.mybatis; 2 | 3 | import java.io.IOException; 4 | import java.util.Properties; 5 | 6 | import javax.sql.DataSource; 7 | 8 | import org.apache.commons.logging.Log; 9 | import org.apache.commons.logging.LogFactory; 10 | import org.apache.ibatis.plugin.Interceptor; 11 | import org.apache.ibatis.session.SqlSessionFactory; 12 | import org.mybatis.spring.SqlSessionFactoryBean; 13 | import org.mybatis.spring.SqlSessionTemplate; 14 | import org.mybatis.spring.annotation.MapperScan; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.beans.factory.annotation.Qualifier; 17 | import org.springframework.beans.factory.annotation.Value; 18 | import org.springframework.boot.autoconfigure.AutoConfigureAfter; 19 | import org.springframework.boot.context.properties.ConfigurationProperties; 20 | import org.springframework.context.annotation.Bean; 21 | import org.springframework.context.annotation.Configuration; 22 | import org.springframework.context.annotation.Primary; 23 | import org.springframework.core.io.DefaultResourceLoader; 24 | import org.springframework.core.io.Resource; 25 | import org.springframework.core.io.support.PathMatchingResourcePatternResolver; 26 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 27 | import org.springframework.transaction.PlatformTransactionManager; 28 | import org.springframework.transaction.annotation.EnableTransactionManagement; 29 | import org.springframework.transaction.annotation.TransactionManagementConfigurer; 30 | 31 | import com.github.pagehelper.PageHelper; 32 | /** 33 | * mybatis的相关配置设置 34 | * @author Jfei 35 | * 36 | */ 37 | @Configuration 38 | @AutoConfigureAfter(DatasourceConfig.class) 39 | @ConfigurationProperties 40 | @EnableTransactionManagement 41 | //@MapperScan("com.fei.springboot.dao") 42 | public class MybatisConfiguration implements TransactionManagementConfigurer{ 43 | 44 | private static Log logger = LogFactory.getLog(MybatisConfiguration.class); 45 | 46 | // 配置类型别名 47 | @Value("${mybatis.typeAliasesPackage}") 48 | private String typeAliasesPackage; 49 | 50 | // 配置mapper的扫描,找到所有的mapper.xml映射文件 51 | // @Value("${mybatis.mapperLocations : classpath:com/fei/springboot/dao/*.xml}") 52 | @Value("${mybatis.mapperLocations}") 53 | private String mapperLocations; 54 | 55 | // 加载全局的配置文件 56 | @Value("${mybatis.configLocation}") 57 | private String configLocation; 58 | 59 | @Autowired 60 | private DataSource dataSource; 61 | 62 | // 提供SqlSeesion 63 | @Bean(name = "sqlSessionFactory") 64 | @Primary 65 | public SqlSessionFactory sqlSessionFactory() { 66 | try { 67 | SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean(); 68 | sessionFactoryBean.setDataSource(dataSource); 69 | 70 | // 读取配置 71 | sessionFactoryBean.setTypeAliasesPackage(typeAliasesPackage); 72 | 73 | //设置mapper.xml文件所在位置 74 | Resource[] resources = new PathMatchingResourcePatternResolver().getResources(mapperLocations); 75 | sessionFactoryBean.setMapperLocations(resources); 76 | //设置mybatis-config.xml配置文件位置 77 | sessionFactoryBean.setConfigLocation(new DefaultResourceLoader().getResource(configLocation)); 78 | 79 | //添加分页插件、打印sql插件 80 | Interceptor[] plugins = new Interceptor[]{pageHelper(),sqlPrintInterceptor()}; 81 | sessionFactoryBean.setPlugins(plugins); 82 | 83 | return sessionFactoryBean.getObject(); 84 | } catch (IOException e) { 85 | logger.error("mybatis resolver mapper*xml is error",e); 86 | return null; 87 | } catch (Exception e) { 88 | logger.error("mybatis sqlSessionFactoryBean create error",e); 89 | return null; 90 | } 91 | } 92 | 93 | @Bean 94 | public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { 95 | return new SqlSessionTemplate(sqlSessionFactory); 96 | } 97 | 98 | //事务管理 99 | @Bean 100 | public PlatformTransactionManager annotationDrivenTransactionManager() { 101 | return new DataSourceTransactionManager(dataSource); 102 | } 103 | 104 | //将要执行的sql进行日志打印(不想拦截,就把这方法注释掉) 105 | @Bean 106 | public SqlPrintInterceptor sqlPrintInterceptor(){ 107 | return new SqlPrintInterceptor(); 108 | } 109 | 110 | /** 111 | * 分页插件 112 | * @param dataSource 113 | * @return 114 | */ 115 | 116 | // 117 | // 118 | // 119 | // 120 | // 121 | // 122 | // 123 | // 124 | // 125 | // 126 | // 127 | // 128 | // 129 | // 130 | // 131 | // 132 | // 133 | // 134 | // 135 | // 136 | // 137 | // 138 | // 139 | // 140 | // 141 | @Bean 142 | public PageHelper pageHelper() { 143 | PageHelper pageHelper = new PageHelper(); 144 | Properties p = new Properties(); 145 | p.setProperty("offsetAsPageNum", "true"); 146 | p.setProperty("rowBoundsWithCount", "true"); 147 | p.setProperty("reasonable", "true"); 148 | p.setProperty("returnPageInfo", "check"); 149 | p.setProperty("params", "count=countSql"); 150 | pageHelper.setProperties(p); 151 | return pageHelper; 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/main/java/com/fei/springboot/config/mybatis/SqlPrintInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.fei.springboot.config.mybatis; 2 | import org.apache.commons.logging.Log; 3 | import org.apache.commons.logging.LogFactory; 4 | import org.apache.ibatis.executor.Executor; 5 | import org.apache.ibatis.mapping.BoundSql; 6 | import org.apache.ibatis.mapping.MappedStatement; 7 | import org.apache.ibatis.mapping.ParameterMapping; 8 | import org.apache.ibatis.mapping.ParameterMode; 9 | import org.apache.ibatis.plugin.*; 10 | import org.apache.ibatis.reflection.MetaObject; 11 | import org.apache.ibatis.session.Configuration; 12 | import org.apache.ibatis.session.ResultHandler; 13 | import org.apache.ibatis.session.RowBounds; 14 | import org.apache.ibatis.type.TypeHandlerRegistry; 15 | 16 | import java.text.DateFormat; 17 | import java.text.SimpleDateFormat; 18 | import java.util.Date; 19 | import java.util.List; 20 | import java.util.Properties; 21 | import java.util.regex.Matcher; 22 | 23 | /** 24 | * MyBatis 将mybatis要执行的sql拦截打印出来 25 | * 26 | * @since 1.0.0 27 | */ 28 | @Intercepts 29 | ({ 30 | @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}), 31 | @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}) 32 | }) 33 | public class SqlPrintInterceptor implements Interceptor { 34 | 35 | private static Log logger = LogFactory.getLog(SqlPrintInterceptor.class); 36 | 37 | private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 38 | 39 | @Override 40 | public Object intercept(Invocation invocation) throws Throwable { 41 | MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0]; 42 | Object parameterObject = null; 43 | if (invocation.getArgs().length > 1) { 44 | parameterObject = invocation.getArgs()[1]; 45 | } 46 | 47 | long start = System.currentTimeMillis(); 48 | 49 | Object result = invocation.proceed(); 50 | 51 | String statementId = mappedStatement.getId(); 52 | BoundSql boundSql = mappedStatement.getBoundSql(parameterObject); 53 | Configuration configuration = mappedStatement.getConfiguration(); 54 | String sql = getSql(boundSql, parameterObject, configuration); 55 | 56 | long end = System.currentTimeMillis(); 57 | long timing = end - start; 58 | if(logger.isInfoEnabled()){ 59 | logger.info("执行sql耗时:" + timing + " ms" + " - id:" + statementId + " - Sql:" ); 60 | logger.info(" "+sql); 61 | } 62 | 63 | return result; 64 | } 65 | 66 | @Override 67 | public Object plugin(Object target) { 68 | if (target instanceof Executor) { 69 | return Plugin.wrap(target, this); 70 | } 71 | return target; 72 | } 73 | 74 | @Override 75 | public void setProperties(Properties properties) { 76 | } 77 | 78 | private String getSql(BoundSql boundSql, Object parameterObject, Configuration configuration) { 79 | String sql = boundSql.getSql().replaceAll("[\\s]+", " "); 80 | List parameterMappings = boundSql.getParameterMappings(); 81 | TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry(); 82 | if (parameterMappings != null) { 83 | for (int i = 0; i < parameterMappings.size(); i++) { 84 | ParameterMapping parameterMapping = parameterMappings.get(i); 85 | if (parameterMapping.getMode() != ParameterMode.OUT) { 86 | Object value; 87 | String propertyName = parameterMapping.getProperty(); 88 | if (boundSql.hasAdditionalParameter(propertyName)) { 89 | value = boundSql.getAdditionalParameter(propertyName); 90 | } else if (parameterObject == null) { 91 | value = null; 92 | } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { 93 | value = parameterObject; 94 | } else { 95 | MetaObject metaObject = configuration.newMetaObject(parameterObject); 96 | value = metaObject.getValue(propertyName); 97 | } 98 | sql = replacePlaceholder(sql, value); 99 | } 100 | } 101 | } 102 | return sql; 103 | } 104 | 105 | private String replacePlaceholder(String sql, Object propertyValue) { 106 | String result; 107 | if (propertyValue != null) { 108 | if (propertyValue instanceof String) { 109 | result = "'" + propertyValue + "'"; 110 | } else if (propertyValue instanceof Date) { 111 | result = "'" + DATE_FORMAT.format(propertyValue) + "'"; 112 | } else { 113 | result = propertyValue.toString(); 114 | } 115 | } else { 116 | result = "null"; 117 | } 118 | return sql.replaceFirst("\\?", Matcher.quoteReplacement(result)); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/com/fei/springboot/config/redis/RedisConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.fei.springboot.config.redis; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | import org.springframework.cache.CacheManager; 6 | import org.springframework.cache.annotation.CachingConfigurerSupport; 7 | import org.springframework.cache.annotation.EnableCaching; 8 | import org.springframework.cache.interceptor.KeyGenerator; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | import org.springframework.data.redis.cache.RedisCacheManager; 12 | import org.springframework.data.redis.connection.RedisConnectionFactory; 13 | import org.springframework.data.redis.core.RedisTemplate; 14 | import org.springframework.data.redis.core.StringRedisTemplate; 15 | import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 16 | 17 | import com.fasterxml.jackson.annotation.PropertyAccessor; 18 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 19 | import com.fasterxml.jackson.databind.ObjectMapper; 20 | 21 | @Configuration 22 | @EnableCaching 23 | public class RedisConfiguration extends CachingConfigurerSupport{ 24 | 25 | // 缓存数据时Key的生成器,可以依据业务和技术场景自行定制 26 | @Bean 27 | public KeyGenerator keyGenerator() { 28 | return new KeyGenerator() { 29 | @Override 30 | public Object generate(Object target, Method method, Object... params) { 31 | StringBuilder sb = new StringBuilder(); 32 | //类名+方法名 33 | sb.append(target.getClass().getName()); 34 | sb.append(method.getName()); 35 | for (Object obj : params) { 36 | sb.append(obj.toString()); 37 | } 38 | return sb.toString(); 39 | } 40 | 41 | }; 42 | } 43 | 44 | @SuppressWarnings("rawtypes") 45 | @Bean 46 | public CacheManager cacheManager(RedisTemplate redisTemplate) { 47 | RedisCacheManager rcm = new RedisCacheManager(redisTemplate); 48 | //设置缓存过期时间 49 | // rcm.setDefaultExpiration(60);//秒,便于测试 50 | return rcm; 51 | } 52 | 53 | @Bean 54 | public RedisTemplate redisTemplate(RedisConnectionFactory factory) { 55 | StringRedisTemplate template = new StringRedisTemplate(factory); 56 | Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); 57 | ObjectMapper om = new ObjectMapper(); 58 | om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); 59 | om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); 60 | jackson2JsonRedisSerializer.setObjectMapper(om); 61 | template.setValueSerializer(jackson2JsonRedisSerializer); 62 | template.afterPropertiesSet(); 63 | return template; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/fei/springboot/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.fei.springboot.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.stereotype.Controller; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.ResponseBody; 8 | 9 | import com.fei.springboot.domain.User; 10 | import com.fei.springboot.service.UserService; 11 | import com.github.pagehelper.PageInfo; 12 | 13 | @Controller 14 | @RequestMapping("/user") 15 | public class UserController { 16 | 17 | 18 | @Autowired 19 | private UserService userService; 20 | 21 | @RequestMapping("/hello") 22 | @ResponseBody 23 | public String hello(){ 24 | return "hello"; 25 | } 26 | /** 27 | * 测试插入 28 | * @return 29 | */ 30 | @RequestMapping("/add") 31 | @ResponseBody 32 | public String add(String id,String userName){ 33 | User u = new User(); 34 | u.setId(id); 35 | u.setUserName(userName); 36 | this.userService.insertUser(u); 37 | return u.getId()+" " + u.getUserName(); 38 | } 39 | 40 | /** 41 | * 测试根据id查询 42 | * @return 43 | */ 44 | @RequestMapping("/get/{id}") 45 | @ResponseBody 46 | public String findById(@PathVariable("id")String id){ 47 | User u = this.userService.findById(id); 48 | return u== null ? "找不到对象" :( u.getId()+" " + u.getUserName()); 49 | } 50 | 51 | 52 | /** 53 | * 测试修改 54 | * @return 55 | */ 56 | @RequestMapping("/update") 57 | @ResponseBody 58 | public String update(String id,String userName){ 59 | User u = new User(); 60 | u.setId(id); 61 | u.setUserName(userName); 62 | this.userService.updateUser(u); 63 | return u.getId()+" " + u.getUserName(); 64 | } 65 | 66 | /** 67 | * 测试删除 68 | * @return 69 | */ 70 | @RequestMapping("/delete/{id}") 71 | @ResponseBody 72 | public String delete(@PathVariable("id")String id){ 73 | this.userService.deleteById(id); 74 | return "success"; 75 | } 76 | 77 | /** 78 | * 测试全部 79 | * @return 80 | */ 81 | @RequestMapping("/deleteAll") 82 | @ResponseBody 83 | public String deleteAll(){ 84 | this.userService.deleteAll(); 85 | return "success"; 86 | } 87 | 88 | 89 | 90 | /** 91 | * 测试分页插件 92 | * @return 93 | */ 94 | @RequestMapping("/queryPage") 95 | @ResponseBody 96 | public String queryPage(){ 97 | PageInfo page = this.userService.queryPage("tes", 1, 2); 98 | System.out.println("总页数=" + page.getPages()); 99 | System.out.println("总记录数=" + page.getTotal()) ; 100 | for(User u : page.getList()){ 101 | System.out.println(u.getId() + " \t " + u.getUserName()); 102 | } 103 | return page.toString(); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/com/fei/springboot/dao/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.fei.springboot.dao; 2 | 3 | import java.util.List; 4 | 5 | import org.apache.ibatis.annotations.Delete; 6 | import org.apache.ibatis.annotations.Insert; 7 | import org.apache.ibatis.annotations.Mapper; 8 | import org.apache.ibatis.annotations.Param; 9 | import org.apache.ibatis.annotations.Select; 10 | import org.apache.ibatis.annotations.Update; 11 | 12 | import com.fei.springboot.domain.User; 13 | 14 | @Mapper 15 | public interface UserMapper { 16 | 17 | @Insert("insert sys_user(id,user_name) values(#{id},#{userName})") 18 | void insert(User u); 19 | 20 | @Update("update sys_user set user_name = #{userName} where id=#{id} ") 21 | void update(User u); 22 | 23 | @Delete("delete from sys_user where id=#{id} ") 24 | void delete(@Param("id")String id); 25 | 26 | @Select("select id,user_name from sys_user where id=#{id} ") 27 | User find(@Param("id")String id); 28 | 29 | //注:方法名和要UserMapper.xml中的id一致 30 | List query(@Param("userName")String userName); 31 | 32 | @Delete("delete from sys_user") 33 | void deleteAll(); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/fei/springboot/dao/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 14 | -------------------------------------------------------------------------------- /src/main/java/com/fei/springboot/domain/User.java: -------------------------------------------------------------------------------- 1 | package com.fei.springboot.domain; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 放进redis中的对象,必须Serializable序列化 7 | * @author Jfei 8 | * 9 | */ 10 | public class User { 11 | 12 | 13 | private String id; 14 | 15 | private String userName; 16 | 17 | public String getId() { 18 | return id; 19 | } 20 | 21 | public void setId(String id) { 22 | this.id = id; 23 | } 24 | 25 | public String getUserName() { 26 | return userName; 27 | } 28 | 29 | public void setUserName(String userName) { 30 | this.userName = userName; 31 | } 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/fei/springboot/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.fei.springboot.service; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.cache.annotation.CacheConfig; 5 | import org.springframework.cache.annotation.CacheEvict; 6 | import org.springframework.cache.annotation.CachePut; 7 | import org.springframework.cache.annotation.Cacheable; 8 | import org.springframework.stereotype.Service; 9 | import org.springframework.transaction.annotation.Isolation; 10 | import org.springframework.transaction.annotation.Propagation; 11 | import org.springframework.transaction.annotation.Transactional; 12 | 13 | import com.fei.springboot.dao.UserMapper; 14 | import com.fei.springboot.domain.User; 15 | import com.github.pagehelper.Page; 16 | import com.github.pagehelper.PageHelper; 17 | import com.github.pagehelper.PageInfo; 18 | 19 | @Service 20 | @CacheConfig(cacheNames="userCache") // 本类内方法指定使用缓存时,默认的名称就是userCache 21 | @Transactional(propagation=Propagation.REQUIRED,readOnly=false,rollbackFor=Exception.class) 22 | public class UserService { 23 | 24 | @Autowired 25 | private UserMapper userMapper; 26 | 27 | // 因为必须要有返回值,才能保存到数据库中,如果保存的对象的某些字段是需要数据库生成的, 28 | //那保存对象进数据库的时候,就没必要放到缓存了 29 | @CachePut(key="#p0.id") //#p0表示第一个参数 30 | //必须要有返回值,否则没数据放到缓存中 31 | public User insertUser(User u){ 32 | this.userMapper.insert(u); 33 | //u对象中可能只有只几个有效字段,其他字段值靠数据库生成,比如id 34 | return this.userMapper.find(u.getId()); 35 | } 36 | 37 | 38 | @CachePut(key="#p0.id") 39 | public User updateUser(User u){ 40 | this.userMapper.update(u); 41 | //可能只是更新某几个字段而已,所以查次数据库把数据全部拿出来全部 42 | return this.userMapper.find(u.getId()); 43 | } 44 | 45 | @Cacheable(key="#p0") // @Cacheable 会先查询缓存,如果缓存中存在,则不执行方法 46 | public User findById(String id){ 47 | System.err.println("根据id=" + id +"获取用户对象,从数据库中获取"); 48 | return this.userMapper.find(id); 49 | } 50 | 51 | @CacheEvict(key="#p0") //删除缓存名称为userCache,key等于指定的id对应的缓存 52 | public void deleteById(String id){ 53 | this.userMapper.delete(id); 54 | } 55 | 56 | //清空缓存名称为userCache(看类名上的注解)下的所有缓存 57 | //如果数据失败了,缓存时不会清除的 58 | @CacheEvict(allEntries = true) 59 | public void deleteAll(){ 60 | this.userMapper.deleteAll(); 61 | } 62 | 63 | public PageInfo queryPage(String userName,int pageNum,int pageSize){ 64 | Page page = PageHelper.startPage(pageNum, pageSize); 65 | //PageHelper会自动拦截到下面这查询sql 66 | this.userMapper.query(userName); 67 | return page.toPageInfo(); 68 | } 69 | 70 | 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | config: classpath:logback.xml 3 | path: d:/logs 4 | server: 5 | port: 80 6 | session-timeout: 60 7 | 8 | 9 | mybatis: 10 | mapperLocations: classpath:/com/fei/springboot/dao/*.xml 11 | typeAliasesPackage: com.fei.springboot.dao 12 | mapperScanPackage: com.fei.springboot.dao 13 | configLocation: classpath:/mybatis-config.xml 14 | 15 | spring: 16 | datasource: 17 | name: db 18 | type: com.alibaba.druid.pool.DruidDataSource 19 | url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8 20 | username: root 21 | password: root 22 | driver-class-name: com.mysql.jdbc.Driver 23 | minIdle: 5 24 | maxActive: 100 25 | initialSize: 10 26 | maxWait: 60000 27 | timeBetweenEvictionRunsMillis: 60000 28 | minEvictableIdleTimeMillis: 300000 29 | validationQuery: select 'x' 30 | testWhileIdle: true 31 | testOnBorrow: false 32 | testOnReturn: false 33 | poolPreparedStatements: true 34 | maxPoolPreparedStatementPerConnectionSize: 50 35 | removeAbandoned: true 36 | filters: stat # ,wall,log4j # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 37 | connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 38 | useGlobalDataSourceStat: true # 合并多个DruidDataSource的监控数据 39 | druidLoginName: wjf # 登录druid的账号 40 | druidPassword: wjf # 登录druid的密码 41 | cachePrepStmts: true # 开启二级缓存 42 | redis: 43 | database: 0 44 | host: 127.0.0.1 45 | port: 6379 46 | password: 47 | pool: 48 | max-active: 8 49 | max-wait: -1 50 | max-idle: 8 51 | min-idle: 0 52 | timeout: 0 -------------------------------------------------------------------------------- /src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |     8 |     9 |       %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 10 |     11 |   12 | 13 | 14 | ${LOG_PATH}/info.log 15 | 16 | ${LOG_PATH}/info-%d{yyyyMMdd}.log.%i 17 | 18 | 500MB 19 | 20 | 2 21 | 22 | 23 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n 24 | 25 | 26 | 27 | 28 | 29 | 30 | ERROR 31 | 32 | ${LOG_PATH}/error.log 33 | 34 | ${LOG_PATH}/error-%d{yyyyMMdd}.log.%i 35 | 36 | 37 | 500MB 38 | 39 | 2 40 | 41 | 42 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%msg%n 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/main/resources/mybatis-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | --------------------------------------------------------------------------------