springMvc杂记(2)--统一返回消息格式并且进行base64编码
在SpringMVC的开发过程中,返回给前端的消息一般都是固定格式的,这样也方便调用者解析,在springMVC中实现这一点,也是非常方便,
实例代码路径--https://github.com/wangjiuong/springstudy/tree/master/SpringMvcRequestBody
1、定义一个注解类
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ResponseJsonBody { }
2、定义类实现HandlerMethodReturnValueHandler。
package com.nuaa.handler; import com.alibaba.fastjson.JSON; import com.nuaa.annotation.ResponseJsonBody; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.ServletServerHttpResponse; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.method.support.ModelAndViewContainer; import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.List; /** * Created by wangjiuyong on 2017/7/5. */ public class ReponseJsonBodyMethodReturnValueHandler implements HandlerMethodReturnValueHandler { private List<HttpMessageConverter<?>> messageConverters = new ArrayList<>(); public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) { this.messageConverters.addAll(messageConverters); } @Override public boolean supportsReturnType(MethodParameter returnType) { return returnType.getMethodAnnotation(ResponseJsonBody.class)!=null; } @Override public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception { HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class); JsonResult result = buildJsonResult(returnValue); if(null!=messageConverters && !messageConverters.isEmpty()){ ServletServerHttpResponse outputMessage = new ServletServerHttpResponse(response); for( HttpMessageConverter messageConverter:messageConverters){ messageConverter.write(result, MediaType.APPLICATION_JSON,outputMessage); } }else { response.getWriter().write(result.toString()); } response.flushBuffer(); } public JsonResult buildJsonResult(Object returnValue){ JsonResult jsonResult=new JsonResult(); if (returnValue != null) { jsonResult.setData(JSON.toJSON(returnValue)); jsonResult.setErrorCode(ResultEnum.success.getCode()); jsonResult.setMsg(ResultEnum.success.getMsg()); jsonResult.setSuccess(true); } else{ jsonResult.setErrorCode(ResultEnum.unknown.getCode()); jsonResult.setMsg(ResultEnum.unknown.getMsg()); jsonResult.setSuccess(false); } return jsonResult; } }
supportsReturnType用来判断该类是用于解析那个注解。
handleReturnValue方法用来封装返回的消息格式,
在类中增加了messageConverters,可以再封装好的消息上,做进一步的处理,譬如base64编码等处理,避免消息的明文传输。
其他的辅助类如下:
JsonResult定义了返回的消息体格式:
package com.nuaa.handler; import com.alibaba.fastjson.JSON; /** * Created by wangjiuyong on 2017/7/5. */ public class JsonResult { private boolean success; private String msg; private String errorCode; private Object data; public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public String getErrorCode() { return errorCode; } public void setErrorCode(String errorCode) { this.errorCode = errorCode; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } @Override public String toString(){ return JSON.toJSONString(this); } }
ResultEnum定义了一些返回码和消息的对应值:
package com.nuaa.handler; import org.apache.commons.lang3.StringUtils; /** * Created by wangjiuyong on 2017/7/5. */ public enum ResultEnum { success("10000", "success"), sqlerror("60001", "sql error"), internalerror("70001", "internal error"), unknown("90001", "unkown error"); private final String code; private final String msg; ResultEnum(String code, String msg) { this.code = code; this.msg = msg; } public static ResultEnum getCityCodeById(String statusCode) { if (StringUtils.isEmpty(statusCode)) { return unknown; } for (ResultEnum resule : ResultEnum.values()) { if (resule.getCode().equals(statusCode)) { return resule; } } return unknown; } public String getCode() { return code; } public String getMsg() { return msg; } }
Base64JsonHttpMessageConverter用于对JsonResult的值进行base64编码后返回
package com.nuaa.handler; import org.apache.commons.codec.binary.Base64; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; import org.springframework.util.FileCopyUtils; import java.io.IOException; import java.util.List; /** * Created by wangjiuyong on 2017/7/5. */ public class Base64JsonHttpMessageConverter implements HttpMessageConverter { @Override public boolean canRead(Class clazz, MediaType mediaType) { return false; } @Override public boolean canWrite(Class clazz, MediaType mediaType) { return false; } @Override public List<MediaType> getSupportedMediaTypes() { return null; } @Override public Object read(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { return null; } @Override public void write(Object object, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { byte[] bytes = object.toString().getBytes(); FileCopyUtils.copy(Base64.encodeBase64(bytes), outputMessage.getBody()); } }
最后在spring配置文件中将类装配进去就OK了
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!-- 注解的映射器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" /> <!-- 注解的适配器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> <value>application/json;charset=UTF-8</value> </list> </property> </bean> </list> </property> <property name="returnValueHandlers"> <list> <bean class="com.nuaa.handler.ReponseJsonBodyMethodReturnValueHandler"> <property name="messageConverters"> <list> <bean class="com.nuaa.handler.Base64JsonHttpMessageConverter"/> </list> </property> </bean> </list> </property> </bean> </beans>
在Controller中将注解配置下,就可以实现,统一格式的消息返回并且进行base64编码。
@RequestMapping(value="/helloworld", method = RequestMethod.POST,produces="application/json") @ResponseJsonBody @ResponseBody public Student helloWorld(@RequestBody Student student){ student.setName(student.getName()+(new Date())); return student; }