在实际项目中,我们经常会在接口中获取如:HttpServletRequest, HttpServletResponse,我们会发现,我们不要做任何处理,就能获取到对象,这就是固定类型解析器的魅力 除了上面2个,参数比如是SessionStatus, ServletResponse, OutputStream, Writer, WebRequest, MultipartRequest, HttpSession, Principal, InputStream等源生的API对象也可以获取
一、ServletRequestMethodArgumentResolver
@Override
public boolean supportsParameter(MethodParameter parameter) {
Class<?> paramType = parameter.getParameterType();
return (WebRequest.class.isAssignableFrom(paramType) ||
ServletRequest.class.isAssignableFrom(paramType) ||
MultipartRequest.class.isAssignableFrom(paramType) ||
HttpSession.class.isAssignableFrom(paramType) ||
(pushBuilder != null && pushBuilder.isAssignableFrom(paramType)) ||
Principal.class.isAssignableFrom(paramType) ||
InputStream.class.isAssignableFrom(paramType) ||
Reader.class.isAssignableFrom(paramType) ||
HttpMethod.class == paramType ||
Locale.class == paramType ||
TimeZone.class == paramType ||
ZoneId.class == paramType);
}
@Override
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
Class<?> paramType = parameter.getParameterType();
// WebRequest / NativeWebRequest / ServletWebRequest
if (WebRequest.class.isAssignableFrom(paramType)) {
if (!paramType.isInstance(webRequest)) {
throw new IllegalStateException(
"Current request is not of type [" + paramType.getName() + "]: " + webRequest);
}
return webRequest;
}
// ServletRequest / HttpServletRequest / MultipartRequest / MultipartHttpServletRequest
if (ServletRequest.class.isAssignableFrom(paramType) || MultipartRequest.class.isAssignableFrom(paramType)) {
return resolveNativeRequest(webRequest, paramType);
}
// HttpServletRequest required for all further argument types
return resolveArgument(paramType, resolveNativeRequest(webRequest, HttpServletRequest.class));
}
处理器处理情况说明
- 如果形参类型是
WebRequest,ServletRequest,MultipartRequest,HttpSession,pushBuilder,Principal,InputStream,Reader,HttpMethod,Locale,TimeZone,ZoneId
就会使用此处理器,看到这你应该明白,以后你需要使用这些参数的话,直接在方法上申明即可,不需要自己再去get了
二、ServletResponseMethodArgumentResolver
// @since 3.1
public class ServletResponseMethodArgumentResolver implements HandlerMethodArgumentResolver {
// 它相对来说很比较简单
@Override
public boolean supportsParameter(MethodParameter parameter) {
Class<?> paramType = parameter.getParameterType();
return (ServletResponse.class.isAssignableFrom(paramType) || // webRequest.getNativeResponse(requiredType)
OutputStream.class.isAssignableFrom(paramType) || //response.getOutputStream()
Writer.class.isAssignableFrom(paramType)); //response.getWriter()
}
@Override
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
// 这个判断放在这。。。
if (mavContainer != null) {
mavContainer.setRequestHandled(true);
}
...
}
}
处理器处理情况说明
- 如果形参类型是
ServletResponse,OutputStream,Writer
就会使用此处理器
三、SessionStatusMethodArgumentResolver
public class SessionStatusMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return SessionStatus.class == parameter.getParameterType();
}
@Override
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
Assert.state(mavContainer != null, "ModelAndViewContainer is required for session status exposure");
return mavContainer.getSessionStatus();
}
}
处理器处理情况说明
- 如果形参类型是
SessionStatus
就会使用此处理器
四、UriComponentsBuilderMethodArgumentResolver
public class UriComponentsBuilderMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
Class<?> type = parameter.getParameterType();
return (UriComponentsBuilder.class == type || ServletUriComponentsBuilder.class == type);
}
@Override
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
Assert.state(request != null, "No HttpServletRequest");
return ServletUriComponentsBuilder.fromServletMapping(request);
}
}
处理器处理情况说明
- 如果形参类型是
UriComponentsBuilder,ServletUriComponentsBuilder
就会使用此处理器
通过UriComponentsBuilder来得到URL的各个部分,以及构建URL都是非常的方便的。
五、RedirectAttributesMethodArgumentResolver
public class RedirectAttributesMethodArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return RedirectAttributes.class.isAssignableFrom(parameter.getParameterType());
}
@Override
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
Assert.state(mavContainer != null, "RedirectAttributes argument only supported on regular handler methods");
ModelMap redirectAttributes;
if (binderFactory != null) {
DataBinder dataBinder = binderFactory.createBinder(webRequest, null, DataBinder.DEFAULT_OBJECT_NAME);
redirectAttributes = new RedirectAttributesModelMap(dataBinder);
}
else {
redirectAttributes = new RedirectAttributesModelMap();
}
mavContainer.setRedirectModel(redirectAttributes);
return redirectAttributes;
}
}
处理器处理情况说明
- 如果形参类型是
RedirectAttributes
就会使用此处理器
RedirectAttributes是Spring mvc 3.1版本之后出来的一个功能,专门用于重定向之后还能带参数跳转的
如果涉及到重定向:多个视图见传值,使用它还是比较方便的。
六、ModelMethodProcessor
public class ModelMethodProcessor implements HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return Model.class.isAssignableFrom(parameter.getParameterType());
}
@Override
@Nullable
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
Assert.state(mavContainer != null, "ModelAndViewContainer is required for model exposure");
return mavContainer.getModel();
处理器处理情况说明
- 如果形参类型是
Model
就会使用此处理器
七、ModelAttributeMethodProcessor
public class ModelAttributeMethodProcessor implements HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler {
private final boolean annotationNotRequired;
@Override
public boolean supportsParameter(MethodParameter parameter) {
return (parameter.hasParameterAnnotation(ModelAttribute.class) ||
(this.annotationNotRequired && !BeanUtils.isSimpleProperty(parameter.getParameterType())));
}
@Override
@Nullable
public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
Assert.state(mavContainer != null, "ModelAttributeMethodProcessor requires ModelAndViewContainer");
Assert.state(binderFactory != null, "ModelAttributeMethodProcessor requires WebDataBinderFactory");
String name = ModelFactory.getNameForParameter(parameter);
ModelAttribute ann = parameter.getParameterAnnotation(ModelAttribute.class);
if (ann != null) {
mavContainer.setBinding(name, ann.binding());
}
Object attribute = null;
BindingResult bindingResult = null;
if (mavContainer.containsAttribute(name)) {
attribute = mavContainer.getModel().get(name);
}
else {
// Create attribute instance
try {
attribute = createAttribute(name, parameter, binderFactory, webRequest);
}
catch (BindException ex) {
if (isBindExceptionRequired(parameter)) {
// No BindingResult parameter -> fail with BindException
throw ex;
}
// Otherwise, expose null/empty value and associated BindingResult
if (parameter.getParameterType() == Optional.class) {
attribute = Optional.empty();
}
bindingResult = ex.getBindingResult();
}
}
if (bindingResult == null) {
// Bean property binding and validation;
// skipped in case of binding failure on construction.
WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);
if (binder.getTarget() != null) {
if (!mavContainer.isBindingDisabled(name)) {
bindRequestParameters(binder, webRequest);
}
validateIfApplicable(binder, parameter);
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
throw new BindException(binder.getBindingResult());
}
}
// Value type adaptation, also covering java.util.Optional
if (!parameter.getParameterType().isInstance(attribute)) {
attribute = binder.convertIfNecessary(binder.getTarget(), parameter.getParameterType(), parameter);
}
bindingResult = binder.getBindingResult();
}
// Add resolved attribute and BindingResult at the end of the model
Map<String, Object> bindingResultModel = bindingResult.getModel();
mavContainer.removeAttributes(bindingResultModel);
mavContainer.addAllAttributes(bindingResultModel);
return attribute;
}
处理器处理情况说明
- 如果形参类型使用
@ModelAttribute
或者不是普通类型(通过!BeanUtils.isSimpleProperty
来判断)的参数就会使用此处理器