package org.springframework.web.method.support; import org.springframework.core.MethodParameter; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; public interface HandlerMethodArgumentResolver { //用于断定是否须要处理该参数分解,返回true为须要,并会去调用下面的方法resolveArgument。 boolean supportsParameter(MethodParameter parameter); //真正用于处理参数分解的方法,返回的Object就是controller方法上的形参对象。 Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception; }
springmvc自带的一些实现:java
ServletRequestMethodArgumentResolver
和ServletResponseMethodArgumentResolver
处理了自动绑定HttpServletRequest和HttpServletResponseRequestParamMapMethodArgumentResolver
处理了@RequestParam
RequestHeaderMapMethodArgumentResolver
处理了@RequestHeader
PathVariableMapMethodArgumentResolver
处理了@PathVariable
ModelAttributeMethodProcessor
处理了@ModelAttribute
RequestResponseBodyMethodProcessor(实际处理类AutoWrapperRequestResponseBodyMethodProcessor)
处理了@RequestBody 。同时也继承: org.springframework.web.method.support.HandlerMethodReturnValueHandler 用来处理 @ResponseBody
public interface HandlerMethodReturnValueHandler { //检验是否支持本处理器处理,返回true会执行handleReturnValue boolean supportsReturnType(MethodParameter returnType); //处理返回值的方法,returnValue便是controller方法中的返回值 void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception;
常见如:AutoWrapperRequestResponseBodyMethodProcessor处理了@RequestBody web
Servlet.service -> DispatcherServlet.doDispatch -> AbstractHandlerMethodAdapter.handle -> RequestMappingHandlerAdapter.handleInternal -> ServletInvocableHandlerMethod.invokeAndHandle:spring
因此: 使用自定义实现后,须要去除controller方法上的@ResponseBody
注解(或类上的@RestController 注解换为 @Controller),否则由于自定义的优先级比较低,仍是会走默认的处理器!api
标识请求是否已经在该方法内完成处理mvc
在RequestMappingHandlerAdapter.invokeHandlerMethod执行过程当中,在处理完输出对象后, 会调用getModelAndView子过程经过“mavContainer.isRequestHandled()”来断定返回一个ModelAndeView对象。
app
正确的逻辑应该返回null;若返回了ModelAndView对象,但内部属性View为空也无法解析。
ide
DispatcherServlet.doDispatch -> DispatcherServlet.processDispatchResult -> DispatcherServlet.render -> InternalResourceView(AbstractView).render 解析过程输出异常 :spring-boot
2019-12-12 17:42:00.613 [http-nio-8023-exec-9] WARN org.springframework.web.servlet.PageNotFound -- No mapping found for HTTP request with URI [/api/api/query] in DispatcherServlet with name 'dispatcherServlet'
postMan响应结果:
post
参数及返回结果处理spa
import javax.servlet.http.HttpServletResponse; import org.springframework.core.MethodParameter; 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.HandlerMethodReturnValueHandler; import org.springframework.web.method.support.ModelAndViewContainer; import com.utrusts.adapter.dto.guarantee.Person; public class SessionArgumentsReturnValRelover implements HandlerMethodArgumentResolver, HandlerMethodReturnValueHandler { @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.hasParameterAnnotation(Session.class) && parameter.getParameterType().equals(String.class); } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { return "test"; } @Override public boolean supportsReturnType(MethodParameter returnType) { return returnType.getParameterType() == Person.class; } @Override public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { mavContainer.setRequestHandled(true); // 设置请求已经被处理的标识 HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class); response.setContentType("text/plain;charset=utf-8"); Person person = (Person) returnValue; response.getWriter().write("通过HandlerMethodReturnValueHandler输出的person:" + person); } }
spring-boot方式注册自定义分解器
@Configuration public class MyConfigurer extends WebMvcConfigurationSupport { SessionArgumentsReturnValRelover relover = new SessionArgumentsReturnValRelover(); @Override protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { argumentResolvers.add(relover); } @Override protected void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) { returnValueHandlers.add(relover); } }
使用时要注意的是: 使用自定义实现后,须要去除controller方法上的@ResponseBody
注解(或类上的@RestController 注解换为 @Controller),否则由于自定义的优先级比较低,仍是会走默认的处理器。
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.utrusts.adapter.aop.Session; import com.utrusts.adapter.dto.common.query.QueryApplyResultReq; import com.utrusts.adapter.dto.guarantee.Person; import lombok.extern.slf4j.Slf4j; //@RestController @Controller @RequestMapping("/api") public class QueryController { @PostMapping("/query") public Person query(@RequestBody QueryApplyResultReq queryReq, @Session String user) { Person person = new Person(); person.setName(user); return person ; } }
postMan响应结果: