手段は、次のことを達成するためにどのくらいの頻度べき等:
- データベースは、データベースにデータを確保することができ、一意のインデックスを作成する唯一のものです。
- トークントークンを取得するために、各インターフェース要求の前に機構、再度とき、次の要求は、このトークンヘッダプラス体で、その後明後日は、トークンを除去することにより、検証場合、再度次の要求判定トークン。
- 他のSQLは、データを更新できない場合に悲観的ロックと楽観的ロックは、悲観的ロック(データベースエンジンに固有のインデックス、テーブル全体をロックする方法でなければならない条件を選択し、その時のInnoDBで)更新の各々を保証することができます。
- 存在しない場合に好ましいデータがデータベースを照会することによって存在するかどうか、を決定する最初の問合せの後、存在する場合、それは要求されたことを説明したが、要求を直接拒否し、それは初めて、直接放出することを意味します。
ビルド・サービスAPIをRedisの
最初のRedis、1。サーバ構築することである
2、スタータspringboot、または春jedisをカプセル化することができるRedisの中に導入されます。主な用途は、それはセットバックAPIメソッドだと方法がここで我々はSpringbootパッケージredisTempateを使用し、存在していることです。
Redisのツールを作成します
@Component
public class RedisService {
@Autowired
private RedisTemplate redisTemplate;
/**
* 写如缓存
*
* @param key
* @param value
* @return
*/
public boolean set(final String key, Object value) {
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
operations.set(key, value);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 写入缓存,带超时失效
*
* @param key
* @param value
* @param expireTime
* @return
*/
public boolean setEX(final String key, Object value, Long expireTime) {
boolean result = false;
try {
ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
operations.set(key, value, expireTime);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 检查key是否存在
*
* @param key
* @return
*/
public boolean exists(final String key) {
return redisTemplate.hasKey(key);
}
/**
* 读取缓存
*
* @param key
* @return
*/
public Object get(final String key) {
Object result = null;
try {
ValueOperations operations = redisTemplate.opsForValue();
result = operations.get(key);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 删除key
*
* @return
*/
public boolean remove(final String key) {
if (exists(key)) {
redisTemplate.delete(key);
return true;
}
return false;
}
/**
* redisTemplate 序列化使用的jdkSerializeable, 存储二进制字节码, 所以自定义序列化类
* @param redisConnectionFactory
* @return
*/
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 使用Jackson2JsonRedisSerialize 替换默认序列化
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// 设置value的序列化规则和 key的序列化规则
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
コメントのカテゴリを追加します。
/**
* @author Administrator
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckRedo {
/**
* 默认值
* @return
*/
String value() default "";
}
カスタムインターセプタは、カスタムアノテーションは、インターセプタ参加スキャン:
@Component
public class AutoIdInterceptor implements HandlerInterceptor {
@Autowired
private TokenService tokenService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (!(handler instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
CheckRedo checkRedo = method.getAnnotation(CheckRedo.class);
if (checkRedo!=null){
//幂等性校验
return tokenService.checkToken(request);
}
return true;
}
}
インターセプタはwebconfigurationに参加します:
@Component
public class WebConfiguration implements WebMvcConfigurer{
@Resource
private AutoIdInterceptor autoIdInterceptor;
/**
* 添加拦截器
*
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(autoIdInterceptor);
}
}
トークンインタフェース定義を分析
public interface TokenService {
/**
* 创建token
* @return
*/
public String creatToken();
/**
*检查token请求
* @return
*/
public boolean checkToken(HttpServletRequest request) throws Exception;
}
そのインタフェースの特定の実装では、処理ロジックが決定します。
@Component
public class TokenServiceImpl implements TokenService {
@Autowired
RedisService redisService;
@Override
public String creatToken() {
String tokenStr = null;
try {
String uuid = UUID.randomUUID().toString();
StringBuilder sb = new StringBuilder();
tokenStr = sb.append(Constant.redis_prefix).append(uuid).toString();
if (redisService.set(tokenStr, tokenStr)) {
return tokenStr;
}
} catch (Exception e) {
e.printStackTrace();
}
return tokenStr;
}
@Override
public boolean checkToken(HttpServletRequest request) throws Exception {
String token = request.getHeader(Constant.redis_prefix);
if (StringUtils.isEmpty(token)) {
token = request.getParameter(Constant.redis_prefix);
if (StringUtils.isEmpty(token)) {
throw new Exception("token 不能为空或者为null");
}
}
if (!redisService.exists(token)) {
throw new Exception("redis 中不存在此 token:" + token);
}
boolean remove = redisService.remove(token);
if (!remove) {
throw new Exception("redis 中删除key失败");
}
return true;
}
}
、コントローラレイヤ処理制御
/**
* @author zhengzheng046
*/
@RestController
public class BusinessController {
@Autowired
TokenService tokenService;
@GetMapping("/getToken")
public String getToken() {
String token = tokenService.creatToken();
if (!StringUtils.isEmpty(token)) {
System.out.println("token:"+token);
return token;
}
return null;
}
@CheckRedo
@PostMapping("/checkToken")
public String checkToken() {
System.out.println("进入方法,测试完成");
return "success";
}
}
概要:
この記事では、アクセストークンを達成し、冪等の判断・インタフェースを実現するために、Springboot +がRedisのでかどうかを判断します。