spring web架构图
从图中可以看出,
如果要对输出的内容进行重构,不需要视图的话,在handlerMethodReturnValueHandler里进行操作,可以重构这个对象,以达到自定义输出的结果。
需要视图的话,在viewResolver 进行处理,
servletInvocableHandlerMethod 对请求参数进行封装。
如果参数封装有问题,就去 servletInvocableHandlerMethod 打断点寻找。
问题1.想让输出 为json,xml,protobuf 怎么处理?
根据上图 当然是在HandlerMethodReturnValueHandler 中查找,
第一种,理所当然找到RequestResponseBodyMethodProcessor 它里面有一个messageConvert 所以增加一个 对应处理json,xml,protobuf的类即可。
第二种,可以自定义注解,自定义一个HandlerMethodReturnValueHandler 的实现类,来处理对应的注解,直接进行参数转换,或是用messageConvert进行转换即可。当然第一种有现成的方法,没必要用第二种
问题2.@RequestParam 注解什么意思
这个注解,默认是true,必须需要这个参数,如果你不传递,就报错给你看, 可以把参数改为false。
问题3,怎么确定一个输出使用什么MediaType
答:第一根据请求参数里的.accept(mediaTypes) 和 produces 里的mediatype 来求并集。.contentType(ProtobufHttpMessageConverter.PROTOBUF) 请求参数类型是这个,需要用对应的mediaType来解析参数。
一、filter 详解
1.HiddenHttpMethodFilter 将 post请求,转化为,请求参数里指定的方法
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { HttpServletRequest requestToUse = request; if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) { String paramValue = request.getParameter(this.methodParam); if (StringUtils.hasLength(paramValue)) { requestToUse = new HttpMethodRequestWrapper(request, paramValue); } } filterChain.doFilter(requestToUse, response); }
界面用法 th:method将post 转换为delete方法。
<td><form class="form-inline" th:action="@{'/' + ${message.id}}" th:method="delete" method="delete"> <input type="submit" value="Delete1"/></form></td>
后台处理类。
@RequestMapping(value = "{id}", method = RequestMethod.DELETE) public String delete(@PathVariable("id") Message message, RedirectAttributes redirect) { messageRepository.delete(message); redirect.addFlashAttribute("globalMessage", "Message removed successfully"); return "redirect:/"; }
2.HttpPutFormContentFilter 如果请求是PUT或pach,将form里的参数提取到request的parameter里面。
protected void doFilterInternal(final HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { if (("PUT".equals(request.getMethod()) || "PATCH".equals(request.getMethod())) && isFormContentType(request)) { HttpInputMessage inputMessage = new ServletServerHttpRequest(request) { @Override public InputStream getBody() throws IOException { return request.getInputStream(); } }; MultiValueMap<String, String> formParameters = formConverter.read(null, inputMessage); HttpServletRequest wrapper = new HttpPutFormContentRequestWrapper(request, formParameters); filterChain.doFilter(wrapper, response); } else { filterChain.doFilter(request, response); } }
会把form里的参数放入到request的parameters里面
<form action="/springmvc/testRest/3" method="post"> <input type="hidden" name="_method" value="put"/> <input type="submit"value="Test Rest PUT"/> </form>
现在一般的spring web应用里都会添加这两个过滤器。 OrderedHiddenHttpMethodFilter ,OrderedHttpPutFormContentFilter