redis基于注解方式实现
package com.zhk.study.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* ElementType.METHOD:该注解作用于方法上
* RetentionPolicy.RUNTIME:表示它在运行时
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiIdempotent {
}
package com.zhk.study.annotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
/**
* 接口幂等性拦截器
*/
@Component
public class ApiIdempotentInterceptor implements HandlerInterceptor {
@Autowired
private TokenService tokenService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (!(handler instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
ApiIdempotent methodAnnotation = method.getAnnotation(ApiIdempotent.class);
if (methodAnnotation != null) {
check(request);// 幂等性校验, 校验通过则放行, 校验失败则抛出异常, 并通过统一异常处理返回友好提示
}
return true;
}
private void check(HttpServletRequest request) {
tokenService.checkToken(request);
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
}
package com.zhk.study.annotation;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class ExceptionAdvice {
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ServerResponse responseCode(Exception e) {
return ServerResponse.error(e.getMessage());
}
}
package com.zhk.study.annotation;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
@Configuration
public class JedisConfig {
@Bean(name = "jedisPoolConfig")
public JedisPoolConfig jedisPoolConfig(){
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(500);
jedisPoolConfig.setMaxIdle(200);
jedisPoolConfig.setNumTestsPerEvictionRun(1024);
jedisPoolConfig.setTimeBetweenEvictionRunsMillis(30000);
jedisPoolConfig.setMinEvictableIdleTimeMillis(-1);
jedisPoolConfig.setSoftMinEvictableIdleTimeMillis(10000);
jedisPoolConfig.setMaxWaitMillis(1500);
jedisPoolConfig.setTestOnBorrow(true);
jedisPoolConfig.setTestWhileIdle(true);
jedisPoolConfig.setTestOnReturn(false);
jedisPoolConfig.setJmxEnabled(true);
jedisPoolConfig.setBlockWhenExhausted(false);
return jedisPoolConfig;
}
@Bean
public JedisPool redisPool() {
String host = "127.0.0.1";
int port = 6379;
return new JedisPool( jedisPoolConfig(),host,port,
150000,"qv8sqntqmmv5");
}
}
package com.zhk.study.annotation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
@Component
@Slf4j
public class JedisUtil {
@Autowired
private JedisPool jedisPool;
private Jedis getJedis() {
return jedisPool.getResource();
}
/**
* 设值
*
* @param key
* @param value
* @return
*/
public String set(String key, String value) {
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.set(key, value);
} catch (Exception e) {
log.error("set key:{} value:{} error", key, value, e);
return null;
} finally {
close(jedis);
}
}
/**
* 设值
*
* @param key
* @param value
* @param expireTime 过期时间, 单位: s
* @return
*/
public String set(String key, String value, int expireTime) {
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.setex(key, expireTime, value);
} catch (Exception e) {
log.error("set key:{} value:{} expireTime:{} error", key, value, expireTime, e);
return null;
} finally {
close(jedis);
}
}
/**
* 取值
*
* @param key
* @return
*/
public String get(String key) {
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.get(key);
} catch (Exception e) {
log.error("get key:{} error", key, e);
return null;
} finally {
close(jedis);
}
}
/**
* 删除key
*
* @param key
* @return
*/
public Long del(String key) {
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.del(key.getBytes());
} catch (Exception e) {
log.error("del key:{} error", key, e);
return null;
} finally {
close(jedis);
}
}
/**
* 判断key是否存在
*
* @param key
* @return
*/
public Boolean exists(String key) {
System.out.println(key);
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.exists(key.getBytes());
} catch (Exception e) {
log.error("exists key:{} error", key, e);
return null;
} finally {
close(jedis);
}
}
/**
* 设值key过期时间
*
* @param key
* @param expireTime 过期时间, 单位: s
* @return
*/
public Long expire(String key, int expireTime) {
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.expire(key.getBytes(), expireTime);
} catch (Exception e) {
log.error("expire key:{} error", key, e);
return null;
} finally {
close(jedis);
}
}
/**
* 获取剩余时间
*
* @param key
* @return
*/
public Long ttl(String key) {
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.ttl(key);
} catch (Exception e) {
log.error("ttl key:{} error", key, e);
return null;
} finally {
close(jedis);
}
}
private void close(Jedis jedis) {
if (null != jedis) {
jedis.close();
}
}
}
package com.zhk.study.annotation;
public enum ResponseCode {
// 系统模块
SUCCESS(0, "操作成功"),
ERROR(1, "操作失败"),
SERVER_ERROR(500, "服务器异常"),
// 通用模块 1xxxx
ILLEGAL_ARGUMENT(10000, "参数不合法"),
REPETITIVE_OPERATION(10001, "请勿重复操作");
ResponseCode(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
private Integer code;
private String msg;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
package com.zhk.study.annotation;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.io.Serializable;
public class ServerResponse implements Serializable{
private static final long serialVersionUID = 7498483649536881777L;
private Integer status;
private String msg;
private Object data;
public ServerResponse() {
}
public ServerResponse(Integer status, String msg, Object data) {
this.status = status;
this.msg = msg;
this.data = data;
}
@JsonIgnore
public boolean isSuccess() {
return this.status == ResponseCode.SUCCESS.getCode();
}
public static ServerResponse success() {
return new ServerResponse(ResponseCode.SUCCESS.getCode(), null, null);
}
public static ServerResponse success(String msg) {
return new ServerResponse(ResponseCode.SUCCESS.getCode(), msg, null);
}
public static ServerResponse success(Object data) {
return new ServerResponse(ResponseCode.SUCCESS.getCode(), null, data);
}
public static ServerResponse success(String msg, Object data) {
return new ServerResponse(ResponseCode.SUCCESS.getCode(), msg, data);
}
public static ServerResponse error(String msg) {
return new ServerResponse(ResponseCode.ERROR.getCode(), msg, null);
}
public static ServerResponse error(Object data) {
return new ServerResponse(ResponseCode.ERROR.getCode(), null, data);
}
public static ServerResponse error(String msg, Object data) {
return new ServerResponse(ResponseCode.ERROR.getCode(), msg, data);
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
package com.zhk.study.annotation;
/**
* 业务逻辑异常
*/
public class ServiceException extends RuntimeException{
private String code;
private String msg;
public ServiceException() {
}
public ServiceException(String msg) {
this.msg = msg;
}
public ServiceException(String code, String msg) {
this.code = code;
this.msg = msg;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
package com.zhk.study.annotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/token")
public class TokenController {
@Autowired
private TokenService tokenService;
@GetMapping("/create")
public ServerResponse token() {
return tokenService.createToken();
}
@ApiIdempotent
@PostMapping("/testIdempotence")
public ServerResponse testIdempotence() {
return tokenService.testIdempotence();
}
}
package com.zhk.study.annotation;
import javax.servlet.http.HttpServletRequest;
public interface TokenService {
ServerResponse createToken();
void checkToken(HttpServletRequest request);
ServerResponse testIdempotence();
}
package com.zhk.study.annotation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.util.UUID;
@Service
public class TokenServiceImpl implements TokenService {
private static final String TOKEN_NAME = "token";
private static final String TOKEN_PREFIX = "token:";
// 过期时间, 60s, 一分钟
private static final Integer EXPIRE_TIME_MINUTE = 60 * 5;
@Autowired
private JedisUtil jedisUtil;
@Override
public ServerResponse createToken() {
String str = UUID.randomUUID().toString().replaceAll("-", "");
StringBuilder token = new StringBuilder();
token.append(TOKEN_PREFIX).append(str);
System.out.println(token.toString()+":::::"+ token.toString());
jedisUtil.set(token.toString(), token.toString(), EXPIRE_TIME_MINUTE);
return ServerResponse.success(token.toString());
}
@Override
public void checkToken(HttpServletRequest request) {
String token = request.getHeader(TOKEN_NAME);
if (StringUtils.isBlank(token)) {// header中不存在token
token = request.getParameter(TOKEN_NAME);
if (StringUtils.isBlank(token)) {// parameter中也不存在token
throw new ServiceException(ResponseCode.ILLEGAL_ARGUMENT.getMsg());
}
}
if (!jedisUtil.exists(token)) {
throw new ServiceException(ResponseCode.REPETITIVE_OPERATION.getMsg());
}
Long del = jedisUtil.del(token);
if (del <= 0) {
throw new ServiceException(ResponseCode.REPETITIVE_OPERATION.getMsg());
}
}
@Override
public ServerResponse testIdempotence() {
return ServerResponse.success("testIdempotence: success");
}
}
package com.zhk.study.annotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Web配置文件
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private ApiIdempotentInterceptor apiIdempotentInterceptor;
/**
* 跨域
* @return
*/
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
final CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(apiIdempotentInterceptor).addPathPatterns("/**");
}
}
用法切记 创建token的时候 传token这个token有点恶心 是这种 自己可以改一下 本人懒