Open IMBAzxt opened 6 years ago
mybatis配置,使用如下方式可以配置当个mapper
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.zhengxt.dao.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
使用如下配置可以进行通配所有的mapper
<!-- 配置mybatisSqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!--<property name="configLocation" value="classpath:mybatis/mybatis.xml"/>-->
<!--<property name="mapperLocations" value="classpath*:com/itclj/magpie/**/*Mapper.xml"/>-->
</bean>
<!-- 配置SqlSessionTemplate -->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<!-- 配置mybatis mapper接口 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.zhengxt.dao"/>
<property name="sqlSessionTemplateBeanName" value="sqlSessionTemplate"/>
</bean>
<!-- 使用annotation注解方式配置事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
UserMapper.class
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{userId}")
Users getUser(@Param("userId") int userId);
}
mybatis的增删改查功能实现。 spring-mybatis.xml文件改动,增加configLocation属性。
<!-- 配置mybatisSqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
增加mybatis的配置文件mybatis-config.xml,注意需要添加对应的头部信息。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias type="com.zhengxt.Users" alias="Users" />
</typeAliases>
<mappers>
<mapper resource="mapper/usersMapper.xml" />
</mappers>
</configuration>
添加usersMapper.xml文件。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zhengxt.dao.UserMapper">
<resultMap type="Users" id="userMap">
<id property="id" column="id" />
<result property="username" column="username" />
<result property="password" column="password" />
<result property="passwordSalt" column="password_salt" />
</resultMap>
<!-- 增加一个用户;useGeneratedKeys="true"表示给主键设置自增长;keyProperty="id"表示将自增长后的Id赋值给实体类中的id字段。 -->
<insert id="addUser" useGeneratedKeys="true" keyProperty="id" parameterType="Users">
insert into users(username,password,password_salt) values(#{username},#{password},#{passwordSalt})
</insert>
<!-- 根据用户ID查找用户 -->
<select id="findUserById" parameterType="int" resultMap="userMap">
select * from users where id = #{id}
</select>
<!-- 更改用户信息 -->
<update id="updateUser" parameterType="Users">
update users set username=#{username},password=#{password},password_salt=#{passwordSalt} where id=#{id}
</update>
<!-- 删除用户信息 -->
<delete id="deleteUser" parameterType="int">
delete from Users where id = #{id}
</delete>
<!-- 查找所有用户 -->
<select id="findAllUsers" resultType="Users">
select * from users
</select>
</mapper>
在UserMapper中添加对应的接口
public interface UserMapper {
Users findUserById(int id);
void addUser(Users users);
void updateUser(Users users);
void deleteUser(int id);
Users[] findAllUsers();
}
测试
@Autowired
UserMapper userMapper;
static int userId = 0;
@Test
public void testAddUser() {
Users users = new Users();
users.setUsername("test001");
users.setPassword("password");
users.setPasswordSalt("salt");
userMapper.addUser(users);
userId = users.getId();
}
@Test
public void testFindUser() {
Assert.assertEquals("test001", userMapper.findUserById(userId).getUsername());
}
@Test
public void testFindAllUser() {
Users[] users = userMapper.findAllUsers();
System.out.println(users.length);
}
@Test
public void testUpdateUser() {
Users users = userMapper.findUserById(userId);
users.setPassword("passwd");
userMapper.updateUser(users);
Assert.assertEquals("passwd", userMapper.findUserById(userId).getPassword());
}
@Test
public void testDeleteUser() {
userMapper.deleteUser(userId);
Assert.assertEquals(null, userMapper.findUserById(userId));
}
springmvc集成
新增加spring-core和spring-webmvc的依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!--配置SpringMVC分发器,拦截所有请求-->
<servlet>
<servlet-name>SpringMVCMyBatis</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:SpringMVC-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVCMyBatis</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--配置过滤器,解决POST乱码问题-->
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<!-- 设置使用注解的类所在的jar包 -->
<context:component-scan base-package="com.zhengxt.controller" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
controller
@Controller
public class HelloWorld {
/**
* 简单页面
*
* @param model
* @return
*/
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String printHello(ModelMap model) {
model.addAttribute("message", "Hello Spring MVC Framework!");
return "hello";
}
/**
* 表单
*
* @param model
* @return
*/
@RequestMapping(value = "/student", method = RequestMethod.GET)
public ModelAndView student(ModelMap model) {
model.addAttribute("message", "Hello Spring MVC Framework!");
return new ModelAndView("student", "command", new Student());
}
@RequestMapping(value = "/addStudent", method = RequestMethod.POST)
public String addStudent(@ModelAttribute("SpringWeb") Student student,
ModelMap model) {
model.addAttribute("name", student.getName());
model.addAttribute("age", student.getAge());
model.addAttribute("id", student.getId());
return "result";
}
@RequestMapping(value = "/index", method = RequestMethod.GET)
public String index() {
return "hello";
}
}
- 最后添加对应的jsp。
springmvc实现rest api,参考
<!--jackson 配置 springmvc返回json -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</mvc:message-converters>
</mvc:annotation-driven>
restcontroller类编写如下
/**
* 使用@RestController,可以省略掉@ResponseBody注解,即返回结果序列化。
*
* @author ThinkPad
*/
@RestController
@RequestMapping(value = "api")
public class ApiREST {
@GetMapping(value = "testGet", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
public Response testGet() {
return new Response().success("test rest api,method:get");
}
@PutMapping(value = "testPut", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
public Response testPut() {
return new Response().success("test rest api,method:get");
}
@PostMapping(value = "testPost", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
public Response testPost() {
return new Response().success("test rest api,method:post");
}
@DeleteMapping(value = "testDelete", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
public Response testDelete() {
return new Response().success("test rest api,method:delete");
}
}
controller层集成junit测试
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.zhengxt;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhengxt.dto.Response;
import com.zhengxt.entity.Users;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
/**
*
* @author ThinkPad
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
"classpath:spring.xml",
"classpath:springmvc-servlet.xml"})
@WebAppConfiguration
public class RestApiTest {
@Autowired
WebApplicationContext wac;
MockMvc mockMvc;
int id = 1001;
String username = "张三";
@Before
public void setup() {
this.mockMvc = webAppContextSetup(this.wac).build();
}
@Test
public void testGet() throws Exception {
String result = mockMvc.perform(
get("/api/testGet/" + id) //请求地址
.header("Accept-Encoding", "UTF-8") //添加头部信息
.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE) //返回的数据格式
.param("username", username) //添加参数(可以添加多个)
)
.andDo(print()) //打印出请求信息
.andExpect(status().isOk()) //判断返回是否成功
.andExpect(jsonPath("$.data.id").value(id))
.andExpect(jsonPath("$.data.username").value(username))
.andReturn().getResponse().getContentAsString(); //将相应的数据转换为字符串
// jackson字符串转对象
ObjectMapper mapper = new ObjectMapper();
Response<Users> resp = mapper.readValue(result, new TypeReference<Response<Users>>() {
});
Users users = resp.getData();
Assert.assertEquals(String.valueOf(id), String.valueOf(users.getId()));
Assert.assertEquals(username, users.getUsername());
}
@Test
public void testPost() throws Exception {
Users users = new Users();
users.setId(id);
users.setUsername(username);
mockMvc.perform(
post("/api/testPost")
.flashAttr("users", users) //@ModelAttribute("users") Users users,这种情况需要使用flashAttr来进行传值
// .content(mapper.writeValueAsString(users))
.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
)
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.id").value(id))
.andExpect(jsonPath("$.data.username").value(username))
.andReturn()
.getResponse()
.getContentAsString();
}
@Test
public void testPut() throws Exception {
Users users = new Users();
users.setId(id);
users.setUsername(username);
mockMvc.perform(
put("/api/testPut")
.flashAttr("users", users) //@ModelAttribute("users") Users users,这种情况需要使用flashAttr来进行传值
// .content(mapper.writeValueAsString(users))
.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
)
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.id").value(id))
.andExpect(jsonPath("$.data.username").value(username))
.andReturn()
.getResponse()
.getContentAsString();
}
@Test
public void testDelete() throws Exception {
mockMvc.perform(
delete("/api/testDelete/" + id)
.contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)
)
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.data").value(id))
.andReturn()
.getResponse()
.getContentAsString();
}
}
添加依赖包
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.4.0</version>
<scope>test</scope>
</dependency>
springmv rest api获取request、response的方法
@Controller
class Action{
@RequestMapping("/path")
public String getReqAndRes(HttpServletRequest request, HttpServletResponse response){
/** 相关业务代码 此时可以直接使用request response对象 */
}
}
利用spring web提供的@ModelAttribute注解
public class BaseAction{
protected HttpServletRequest request;
protected HttpServletResponse response;
protected HttpSession session;
@ModelAttribute
public void setReqAndRes(HttpServletRequest request, HttpServletResponse response){
this.request = request;
this.response = response;
this.session = request.getSession();
}
/** 其他业务代码 */
}
踩坑一:多端跨域问题,解决方法https://github.com/IMBAzxt/SpringMVCMyBatis/issues/4 踩坑二:使用@ModelAttribute注解接收不到请求过来的数据,错误理解@RequestBody和@ModelAttribute的区别。
@RequestBody和@ModelAttribute的区别
通过上面的issue,本篇全部使用@requestbody来接收,代码做相应的修改。
集成redis,使用redis做二级缓存。参考
<!-- spring-redis实现 -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.0.6.RELEASE</version>
</dependency>
<!-- redis客户端jar -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
# postgres settings
jdbc.driverClass=org.postgresql.Driver
jdbc.jdbcUrl=jdbc:postgresql://127.0.0.1:5432/shiro
jdbc.user=postgres
jdbc.password=kgpgadmin
redis.host=127.0.0.1 redis.port=6379 redis.pass=
redis.maxIdle=300 redis.maxActive=600 redis.maxWait=1000 redis.testOnBorrow=true
- spring-redis配置文件
<?xml version="1.0" encoding="GBK"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
">
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- redis数据源 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxTotal" value="${redis.maxActive}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<!-- 连接池配置,类似数据库连接池 -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" >
<property name="hostName" value="${redis.host}"></property>
<property name="port" value="${redis.port}"></property>
<property name="password" value="${redis.pass}"></property>
<property name="poolConfig" ref="poolConfig"></property>
</bean>
<!-- 使用中间类解决RedisCache.jedisConnectionFactory的静态注入,从而使MyBatis实现第三方缓存 -->
<bean id="redisCacheTransfer" class="com.zhengxt.dao.cache.RedisCacheTransfer">
<property name="jedisConnectionFactory" ref="jedisConnectionFactory" />
</bean>
- RedisDAO
package com.zhengxt.dao.cache;
import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.apache.ibatis.cache.Cache; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer; import redis.clients.jedis.exceptions.JedisConnectionException;
/*
@author ThinkPad */ public class RedisDAO implements Cache {
private static final Logger logger = LoggerFactory.getLogger(RedisDAO.class);
private static JedisConnectionFactory jedisConnectionFactory;
private final String id;
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public static void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) { RedisDAO.jedisConnectionFactory = jedisConnectionFactory; }
public RedisDAO(final String id) { if (id == null) { throw new IllegalArgumentException("Cache instances require an ID"); } logger.debug("MybatisRedisCache:id=" + id); this.id = id; }
public String getId() { return this.id; }
public void putObject(Object key, Object value) { RedisConnection connection = null; try { connection = jedisConnectionFactory.getConnection(); RedisSerializer
public Object getObject(Object key) { Object result = null; RedisConnection connection = null; try { connection = jedisConnectionFactory.getConnection(); RedisSerializer
public Object removeObject(Object key) { RedisConnection connection = null; Object result = null; try { connection = jedisConnectionFactory.getConnection(); RedisSerializer
public void clear() { RedisConnection connection = null; try { connection = jedisConnectionFactory.getConnection(); connection.flushDb(); connection.flushAll(); } catch (JedisConnectionException e) { logger.error("redis clear error", e); } finally { if (connection != null) { connection.close(); } } }
public int getSize() { int result = 0; RedisConnection connection = null; try { connection = jedisConnectionFactory.getConnection(); result = Integer.valueOf(connection.dbSize().toString()); } catch (JedisConnectionException e) { logger.error("redis get size error", e); } finally { if (connection != null) { connection.close(); } } return result; }
public ReadWriteLock getReadWriteLock() { return this.readWriteLock; }
}
- RedisCacheTransfer
package com.zhengxt.dao.cache;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
/*
- 测试
package com.zhengxt.dao.cache;
import static org.junit.Assert.*; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/*
@author ThinkPad */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:spring.xml") public class RedisDAOTest { private static final Logger logger = LoggerFactory.getLogger(RedisDAOTest.class); @Autowired JedisConnectionFactory jedisConnectionFactory;
RedisDAO redis;
@Before public void setup() { RedisDAO.setJedisConnectionFactory(jedisConnectionFactory); redis = new RedisDAO("111"); }
@Test public void testPutObject() { redis.putObject("001", "this is a test message!"); }
@Test public void testGetObject() { String result = String.valueOf(redis.getObject("001")); assertEquals("this is a test message!", result); logger.info(result); }
@Test public void testGetSize() { logger.info("redis size:" + redis.getSize()); }
@Test public void testRemoveObject() { assertNotNull(redis.removeObject("001")); assertNotEquals("this is a test message!", redis.getObject("001")); }
@Test public void testClear() { redis.clear(); logger.info("redis size:" + redis.getSize()); } }
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- aop注解 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.1</version>
</dependency>
<!-- 自动为切面方法中匹配的方法所在的类生成代理对象。 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.stereotype.Component;
/*
@author ThinkPad */ @Aspect @Component public class RedisAspect {
private static final Logger logger = LoggerFactory.getLogger(RedisAspect.class);
@Autowired JedisConnectionFactory jedisConnectionFactory;
@Around("execution( com.zhengxt.service..find*(..))") public Object findDataByRedisCache(ProceedingJoinPoint joinPoint) { logger.info("----- findDataFromRedisCache ----- "); RedisDAO.setJedisConnectionFactory(jedisConnectionFactory); RedisDAO redis = new RedisDAO("findData"); String key = makeRedisKey(joinPoint); Object result = redis.getObject(key); if (result == null) { try { result = joinPoint.proceed(); logger.info("----- saveDataToRedisCache ----- "); redis.putObject(key, result); } catch (Throwable ex) { logger.error("proceed find method error", ex); } } return result; }
/**
- 使用xml配置切换如下,效果等同注解:
@author ThinkPad */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface GetCache {
String key() default ""; //键值
long time() default 0; //缓存过期时间 }
- GetCache的切面,[参考](https://docs.spring.io/spring/docs/4.2.9.RELEASE/spring-framework-reference/htmlsingle/#aop-ataspectj-advice-params-names)
@Component @Aspect public class CacheAspect {
private static final Logger logger = LoggerFactory.getLogger(CacheAspect.class);
@Autowired JedisConnectionFactory jedisConnectionFactory;
@Pointcut("@annotation(com.zhengxt.dao.cache.GetCache)") public void getCache() { logger.info("annotation @GetCache pointcut"); }
@Around(value = "getCache() && @annotation(getCache)") public Object findDataByRedisCache(ProceedingJoinPoint joinPoint, GetCache getCache) { logger.info("----- findDataFromRedisCache ----- "); RedisDAO.setJedisConnectionFactory(jedisConnectionFactory); RedisDAO redis = new RedisDAO("findData"); String key = getCache.key(); //如果注解指定key,使用注解的key,否则按照规则生成key if ("".equals(key)) { key = makeRedisKey(joinPoint); } Object result = redis.getObject(key); if (result == null) { try { result = joinPoint.proceed(); logger.info("----- saveDataToRedisCache ----- "); //缓存过期时间逻辑处理 long time = getCache.time(); if (time == 0) { redis.putObject(key, result); } else { redis.putObject(key, result, time); } } catch (Throwable ex) { logger.error("proceed find method error", ex); } } return result; }
/**