赞
踩
在SpringMVC的使用中,后端与前端的交互一般是使用Json格式进行数据传输,SpringMVC的@ResponseBody注解可以很好的帮助我们进行转换,但是后端返回数据给前端往往都有约定固定的格式,这时候我们在后端返回的时候都要组拼成固定的格式,每次重复的操作非常麻烦。
SpringMVC处理@ResponseBody注解声明的Controller是使用默认的.RequestResponseBodyMethodProcessor类来实现,RequestResponseBodyMethodProcessor类实现了HandlerMethodReturnValueHandler接口并实现了接口中的supportsReturnType()和handleReturnValue()方法。
/* * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.web.method.support; import org.springframework.core.MethodParameter; import org.springframework.lang.Nullable; import org.springframework.web.context.request.NativeWebRequest; /** * Strategy interface to handle the value returned from the invocation of a * handler method . * * @author Arjen Poutsma * @since 3.1 * @see HandlerMethodArgumentResolver */ public interface HandlerMethodReturnValueHandler { /** * Whether the given {@linkplain MethodParameter method return type} is * supported by this handler. * @param returnType the method return type to check * @return {@code true} if this handler supports the supplied return type; * {@code false} otherwise */ boolean supportsReturnType(MethodParameter returnType); /** * Handle the given return value by adding attributes to the model and * setting a view or setting the * {@link ModelAndViewContainer#setRequestHandled} flag to {@code true} * to indicate the response has been handled directly. * @param returnValue the value returned from the handler method * @param returnType the type of the return value. This type must have * previously been passed to {@link #supportsReturnType} which must * have returned {@code true}. * @param mavContainer the ModelAndViewContainer for the current request * @param webRequest the current request * @throws Exception if the return value handling results in an error */ void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception; }
知道@ResponseBody是由RequestResponseBodyMethodProcessor进行处理的,这时候我们可以自己定义一个处理返回数据的Handler来实现我们的定制化Json格式数据返回,但是如果直接把我们定制的Handler加入到SpringMVC的ReturnValueHandlers中,因为我们定制的Handler在RequestResponseBodyMethodProcessor之后,所以我们定制的Handler还是不会生效,这时候我们可以想办法把RequestResponseBodyMethodProcessor替换成我们定制的Handler。
package com.autumn.template; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.experimental.Accessors; /** * JSON信息交互对象模板 * @Author Autumn、 * @Date 2019/4/8 23:46 * @Description */ @Setter @Getter @AllArgsConstructor @NoArgsConstructor @Accessors(chain = true) public class Result implements BaseBean { ......(这里只展示一些必要字段) /** 响应码 */ private Integer code; /** 响应信息 */ private String message; /** 数据 */ private Object data; /** 请求地址 */ private String url; ...... }
package com.autumn.component.handler; import com.autumn.template.Result; import org.springframework.core.MethodParameter; import org.springframework.lang.Nullable; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.method.support.ModelAndViewContainer; /** * 统一处理ResponseBody数据格式 * @Author: Autumn、 * @Date: 2019/4/24 23:59 * @Description: **/ public class ResultWarpReturnValueHandler implements HandlerMethodReturnValueHandler { private final HandlerMethodReturnValueHandler delegate; /** 委托 */ public ResultWarpReturnValueHandler(HandlerMethodReturnValueHandler delegate) { this.delegate = delegate; } /** * 判断返回类型是否需要转成字符串返回 * @param returnType 方法返回类型 * @return 需要转换返回true,否则返回false */ @Override public boolean supportsReturnType(MethodParameter returnType) { return delegate.supportsReturnType(returnType); } /** * 返回值转换 */ @Override public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { // 委托SpringMVC默认的RequestResponseBodyMethodProcessor进行序列化 delegate.handleReturnValue(returnValue instanceof Result ? returnValue : Result.succeed(returnValue), returnType, mavContainer, webRequest); } }
package com.autumn.config; import com.autumn.component.handler.ResultWarpReturnValueHandler; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Configuration; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor; import java.util.ArrayList; import java.util.List; import lombok.extern.slf4j.Slf4j; /** * 替换默认的RequestResponseBodyMethodProcessor * @Author Autumn、 * @Date 2019/4/8 23:46 * @Description */ @Slf4j @Configuration @EnableCaching public class ApplicationContext implements WebMvcConfigurer, InitializingBean { @Autowired(required = false) private RequestMappingHandlerAdapter adapter; @Override public void afterPropertiesSet() throws Exception { // 获取SpringMvc的ReturnValueHandlers List<HandlerMethodReturnValueHandler> returnValueHandlers = adapter.getReturnValueHandlers(); // 新建一个List来保存替换后的Handler的List List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>(returnValueHandlers); // 循环遍历找出RequestResponseBodyMethodProcessor for (HandlerMethodReturnValueHandler handler : handlers) { if (handler instanceof RequestResponseBodyMethodProcessor) { // 创建定制的Json格式处理Handler ResultWarpReturnValueHandler decorator = new ResultWarpReturnValueHandler(handler); // 使用定制的Json格式处理Handler替换原有的RequestResponseBodyMethodProcessor int index = handlers.indexOf(handler); handlers.set(index, decorator); break; } } // 重新设置SpringMVC的ReturnValueHandlers adapter.setReturnValueHandlers(handlers); } }
至此完成了定制@ResponseBody注解返回的Json格式,在Controller中返回任何的字符串都可以定制成为我们想要的Json格式。此外SpringMVC还提供了非常多的Handler接口来进行Controller的增强,可以使用此思路对参数等进行定制化。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。