springboot-No9: 将session信息如同Model一样可以传给Controller之HandlerMethodArgumentResolver妙用

我们的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

这个方法呢就像一个 识别器一样,如果这个resolver指定的 条件可以被识别
也就是如果 MethodParameter 的信息符合一定的规则就可以被识别
然后就可以调用 resolveArgument 来进行处理了.
典型的处理方式就是 使用
parameter.getParameterType()
得到的参数类型和我们想要传入的参数类型匹配,一致的话就进行

resolveArgument方法

通过传入的参数webRequest 可以获取到request和response说道这里意图很明显了吧

也就是说如果你想从 request中获取参数放到每一个业务的指定的多个方法中
我们可以在controller的方法上每次都从request中获取参数进行处理
这样就很麻烦,每个方法都要写
这个时候我们在controller调用之前的时候,
就将这个 request的东西拿到然后设置成HandlerMethodArgumentResolver
这样动态的传入到我们的方法中去
后面如果想要某个对象,只要像 ModelView一样直接写在方法参数中即可使用

最终返回的结果就是我们要加入到controller方法中的参数对象.

到这里我们准备的原理就够了。下面继续我们上节的话题



将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";
		
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值