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