Custom parser needs to implement HandlerMethodArgumentResolver
an interface, HandlerMethodArgumentResolver
the interface comprising two interface functions:
public interface HandlerMethodArgumentResolver {
boolean supportsParameter(MethodParameter var1);
@Nullable
Object resolveArgument(MethodParameter var1, @Nullable ModelAndViewContainer var2, NativeWebRequest var3, @Nullable WebDataBinderFactory var4) throws Exception;
}
Custom parser UserArgumentResolver
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import com.imooc.miaosha.access.UserContext;
import com.imooc.miaosha.domain.MiaoshaUser;
import com.imooc.miaosha.service.MiaoshaUserService;
/**
*
* @Description: 自定义解析器 从Session、数据库或者缓存中查。
* @param:
* @return:
* @date: 2019/6/26 8:32
*/
@Service
public class UserArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
Class<?> clazz = parameter.getParameterType();
return clazz==MiaoshaUser.class;
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
return UserContext.getUser();
}
}
Which is to preserve the current thread UserContext user classes
import com.imooc.miaosha.domain.MiaoshaUser;
public class UserContext {
private static ThreadLocal<User> userHolder = new ThreadLocal<User>();
public static void setUser(MiaoshaUser user) {
userHolder.set(user);
}
public static MiaoshaUser getUser() {
return userHolder.get();
}
}
In order to achieve the purpose of limiting the use of annotations
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Retention(RUNTIME)
@Target(METHOD)
public @interface AccessLimit {
int seconds();
int maxCount();
boolean needLogin() default true;
}
1. defines an interceptor acquires token-> implantation method parameter information back to the user from the redis
2. redisSerice equal to a redisTemple free to add and delete display cache operation, not here in the repeat wrote
3. accessLimit.seconds (); Get cache expiration time, to set the redis accessLimit.maxCount (); obtaining the expiration time of the number of accesses
Interceptor configured to intercept injection adapter
import com.alibaba.fastjson.JSON;
import com.imooc.miaosha.domain.MiaoshaUser;
import com.imooc.miaosha.redis.AccessKey;
import com.imooc.miaosha.redis.RedisService;
import com.imooc.miaosha.result.CodeMsg;
import com.imooc.miaosha.result.Result;
import com.imooc.miaosha.service.MiaoshaUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
@Service
public class AccessInterceptor extends HandlerInterceptorAdapter{
@Autowired
MiaoshaUserService userService;
@Autowired
RedisService redisService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if(handler instanceof HandlerMethod) {
MiaoshaUser user = getUser(request, response);
UserContext.setUser(user);
HandlerMethod hm = (HandlerMethod)handler;
AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);
if(accessLimit == null) {
return true;
}
int seconds = accessLimit.seconds();
int maxCount = accessLimit.maxCount();
boolean needLogin = accessLimit.needLogin();
String key = request.getRequestURI();
if(needLogin) {
if(user == null) {
render(response, CodeMsg.SESSION_ERROR);
return false;
}
key += "_" + user.getId();
}else {
//do nothing
}
AccessKey ak = AccessKey.withExpire(seconds);//获取指定前缀
Integer count = redisService.get(ak, key, Integer.class);
if(count == null) {
redisService.set(ak, key, 1);
}else if(count < maxCount) {
redisService.incr(ak, key);
}else {
render(response, CodeMsg.ACCESS_LIMIT_REACHED);
return false;
}
}
return true;
}
private void render(HttpServletResponse response, CodeMsg cm)throws Exception {
response.setContentType("application/json;charset=UTF-8");
OutputStream out = response.getOutputStream();
String str = JSON.toJSONString(Result.error(cm));
out.write(str.getBytes("UTF-8"));
out.flush();
out.close();
}
private MiaoshaUser getUser(HttpServletRequest request, HttpServletResponse response) {
String paramToken = request.getParameter(MiaoshaUserService.COOKI_NAME_TOKEN);
String cookieToken = getCookieValue(request, MiaoshaUserService.COOKI_NAME_TOKEN);
if(StringUtils.isEmpty(cookieToken) && StringUtils.isEmpty(paramToken)) {
return null;
}
String token = StringUtils.isEmpty(paramToken)?cookieToken:paramToken;
return userService.getByToken(response, token);
}
private String getCookieValue(HttpServletRequest request, String cookiName) {
Cookie[] cookies = request.getCookies();
if(cookies == null || cookies.length <= 0){
return null;
}
for(Cookie cookie : cookies) {
if(cookie.getName().equals(cookiName)) {
return cookie.getValue();
}
}
return null;
}
}
Interceptor configured to intercept injection adapter
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.imooc.miaosha.access.AccessInterceptor;
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter{
@Autowired
UserArgumentResolver userArgumentResolver;
@Autowired
AccessInterceptor accessInterceptor;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(userArgumentResolver);
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(accessInterceptor);
}
}