我们的Controller的方法,是可以自由指定 Request和Response和Model的
是如何做到的呢?
答案在WebMvcConfigurer
这节通过WebMvcConfigurer将我们自定义的bean如同Model一样可以传递给controller的方法,
在Servlet时代我们可以使用过滤器来进行实现的,现在我们看看springmvc的封装处理方案
WebMvcConfigurer
这个接口里面定义了好多的方法
void configurePathMatch(PathMatchConfigurer configurer);
void addInterceptors(InterceptorRegistry registry);
void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers);
void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers);
等等
这里能解决疑问的就是 addArgumentResolvers 方法了
WebMvcConfigurerAdapter
这个就是 WebMvcConfigurer的一个默认适配器
我们如果想要和Model那样把我们自定义的对象加入到controller的方法中
我们就要实现一个WebMvcConfigurer,这里我们只要继承WebMvcConfigurerAdapter即可
我们实现addArgumentResolvers 方法,将想要传给controller的方法的对象包装成一个
HandlerMethodArgumentResolver加入进去就可以了
HandlerMethodArgumentResolver
这个接口将想要传入的对象进行包装。
这是一个接口,里面定义了两个方法
boolean supportsParameter(MethodParameter parameter);
Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception;
第一个方法
supportsParameter
resolveArgument方法
通过传入的参数webRequest 可以获取到request和response说道这里意图很明显了吧
到这里我们准备的原理就够了。下面继续我们上节的话题
将User像Model一样传入到Controller的方法参数中
首先呢我们需要继承一个WebMvcConfigurerAdapter 的类,
这个类的作用就是将我们的User对象给加入到框架的方法参数列表中
其次,我们需要实现一个HandlerMethodArgumentResolver
可以将我们的对象包装成HandlerMethodArgumentResolver
UserArgumentResolver
这个类将完成如何获取到User对象然后将它包装成一个HandlerMethodArgumentResolver
主要就是上面我们介绍的两个方法:
我们利用 MethodParameter 得到参数的类型,如果是 User.class ,那么就被识别
resolveArgument 方法中将使用 NativeWebRequest 获取到 request和response
然后 从request中获取到token,然后从redis中获取到用户的信息,返回这个user即可
WebConfig
引入上面实现的
UserArgumentResolver
然后将它加入到List<HandlerMethodArgumentResolver> 中
UserArgumentResolver.java
package miaosha.config;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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 miaosha.dao.domain.User;
import miaosha.service.UserService;
import miaosha.util.ConstValue;
import org.apache.commons.lang3.StringUtils;
/**
* user作为方法参数传入的处理对象
* @author kaifeng1
*
*/
@Component
public class UserArgumentResolver implements HandlerMethodArgumentResolver{
@Autowired
private UserService userService ;
/**
* 识别出需要传入的对象
*/
public boolean supportsParameter(MethodParameter parameter) {
Class<?> claz = parameter.getParameterType();
//将user这个对象加入到controller的方法参数中
if(claz == User.class) {
return true ;
}
return false;
}
/**
* 将制定的对象传入到controller方法中
*/
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
Cookie cook = this.getCookie(request, ConstValue.COOKI_NAME_TOKEN);
if(cook == null) {
return null ;
}
String paramToken = request.getParameter(ConstValue.COOKI_NAME_TOKEN);
if(StringUtils.isEmpty(cook.getValue()) && StringUtils.isEmpty(paramToken)) {
return null;
}
String token = StringUtils.isEmpty(paramToken)?cook.getValue():paramToken;
return userService.getByToken(response, token);
}
public Cookie getCookie(HttpServletRequest request , String name) {
Cookie[] cooks = request.getCookies() ;
Cookie cook = null ;
for(Cookie c : cooks) {
if(name.equals(c.getName())) {
cook = c ;
break ;
}
}
return cook ;
}
}
WebConfig.java
package miaosha.config;
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.WebMvcConfigurerAdapter;
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter{
@Autowired
UserArgumentResolver userArgumentResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(userArgumentResolver);
}
}
Controller的方法写法简化
User可以像Model一样传入给方法了
/**
* 我们做了这个UserArgumentResolver之后的简洁处理
* @param model
* @param user
* @return
*/
@RequestMapping("/toList")
public String toList(Model model , User user) {
if(user == null) {
return "login";
}
model.addAttribute("user", user);
return "goods_list";
}