关于SpringMVC的处理器拦截器:
SpringMVC的拦截器(面向切面编程)底层使用的是AOP动态代理:
拦截器 :是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。
Struts2的是File过滤器:
过滤器:是在javaweb中,你传入的request、response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者 struts的action前统一设置字符集,或者去除掉一些非法字符.。
关于拦截器和过滤器区别LINK:
LINK: https://blog.csdn.net/evilcry2012/article/details/79737161
使用注解和代码完成SpringMVC的自定义参数处理器:
将自定义的拦截器加入到处理器的队列
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.WebMvcConfigurerAdapter;
import java.util.List;
/**
* SpringMVC配置处理器
*/
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Autowired
UserArgumentResolver userArgumentResolver;
/**
* 将UserArgumentResolver将入到处理器队列中来
* @param argumentResolvers
*/
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(userArgumentResolver);
}
}
自定义参数处理器:
supportsParameter方法对所有Controller层接口方法判断此解析器是否支持此类型,然后再调用resolveArgument进行具体的参数处理
import com.demo.miaosha.domain.MiaoshaUser;
import com.demo.miaosha.service.MiaoshaUserService;
import com.demo.miaosha.utils.CooKieUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
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 org.thymeleaf.util.StringUtils;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 这个自定义的参数处理器,对请求的cookie进行处理,cookie中key为token的值
* 做为redis缓存中用户信息的key进行查询,查询到的用户信息MiaoshaUser对象返回
*/
@Component
public class UserArgumentResolver implements HandlerMethodArgumentResolver {
@Autowired
MiaoshaUserService miaoshaUserService;
/**
* 所有方法中的参数都需要调用此方法判断此解析器是否支持此参数
* @param parameter 请求参数
* @return 支持返回true,不支持返回false
*/
@Override
public boolean supportsParameter(MethodParameter parameter) {
Class<?> parameterType = parameter.getParameterType();
return parameterType == MiaoshaUser.class;
}
/**
* 在supportsParameter(parameter)方法判断完,方法中的参数解析器是否支持后,
* 所有请求此路径的方法,调用此方法对请求参数进行处理
*
* 将方法参数解析为来自给定请求的参数值。 ,
* ModelAndViewContainer 提供对*请求的模型的访问。 ,
* WebDataBinderFactory 提供了一种在需要进行数据绑定和*类型转换时创建 WebDataBinder实例的方法。
*
* @param parameter 请求参数(这里的请求参数都是已经调用过上面的supportsParameter判断过解析器是否支持)
* @param mavContainer 当前请求的ModelAndViewContainer
* @param webRequest 当前的请求
* @param binderFactory 用于创建 WebDataBinder 实例的工厂
* @return 用户信息
* @throws Exception
*/
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
//获取请求和响应对象
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
HttpServletResponse response = webRequest.getNativeRequest(HttpServletResponse.class);
//由于手机端和电脑端的差异,这段代码除了return哪里是调用查询redis缓存中的用户信息,其他的都是获取到cookie的值以及对他的判断
//从请求参数中获取cookie的值
String paramToken = request.getParameter(CooKieUtil.COOKIE_NAME_TOKEN);
//正常从请求中获取Cookie[]来获取cookie对象,调用getValue()方法获取值
String cookieToken = getCookieValue(request, CooKieUtil.COOKIE_NAME_TOKEN);
//判断是否为空
if (StringUtils.isEmpty(cookieToken) && StringUtils.isEmpty(paramToken)){
return null;
}
String token = StringUtils.isEmpty(paramToken)?cookieToken:paramToken;
//获取用户信息
return miaoshaUserService.queryUserLogin(response,token);
}
/**
* 获取指定cookie的值
* 正常从请求中获取Cookie[]来获取cookie对象,调用getValue()方法获取值
* @param request 请求
* @param cookieNameToken 需要获取的cookie的key
* @return cookie的value
*/
private String getCookieValue(HttpServletRequest request, String cookieNameToken) {
Cookie[] cookies = request.getCookies();
for (Cookie cookie:cookies){
if (cookie.getName().equals(cookieNameToken)){
return cookie.getValue();
}
}
return null;
}
}
Controller层代码:
/**
* 登录
* @param vo 前端返回过来用户账号和密码
* @return 登录成功的信息or失败信息
*/
@RequestMapping(path="/do_login",method=RequestMethod.POST)
@ResponseBody
public Result do_login(MiaoshaUser user, HttpServletResponse response, @Valid LoginVo vo){
System.out.println(user);
//判断用户是否已登录,在自定义的参数处理器中进行了处理
if (user != null){
return Result.Failure(ResultEnum.USER_YET_LOGIN);
}
log.info(vo.toString());
boolean loginResult = miaoshaUserService.login(response,vo);
return Result.SUCCESS(ResultEnum.SUCCESS,loginResult);
}
自定义参数处理器完成分页LINK: