インターフェイスのトランザクションは冪等4つの方法を達成します

手段は、次のことを達成するためにどのくらいの頻度べき等:

  1. データベースは、データベースにデータを確保することができ、一意のインデックスを作成する唯一のものです。
  2. トークントークンを取得するために、各インターフェース要求の前に機構、再度とき、次の要求は、このトークンヘッダプラス体で、その後明後日は、トークンを除去することにより、検証場合、再度次の要求判定トークン。
  3. 他のSQLは、データを更新できない場合に悲観的ロックと楽観的ロックは、悲観的ロック(データベースエンジンに固有のインデックス、テーブル全体をロックする方法でなければならない条件を選択し、その時のInnoDBで)更新の各々を保証することができます。
  4. 存在しない場合に好ましいデータがデータベースを照会することによって存在するかどうか、を決定する最初の問合せの後、存在する場合、それは要求されたことを説明したが、要求を直接拒否し、それは初めて、直接放出することを意味します。
    ここに画像を挿入説明
    ビルド・サービス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のでかどうかを判断します。

公開された21元の記事 ウォンの賞賛4 ビュー505

おすすめ

転載: blog.csdn.net/weixin_39617728/article/details/105006615