来源:http://blog.csdn.net/u013979547/article/details/53449788
Controller层的作用是处理业务逻辑并返回数据,那怎么返回数据呢?接口的请求通过HttpServletRequest和HttpServletResponse实现前后端的交互,ServletResponse中有一个getWriter()方法获取到一个PrintWriter对象,通过PrintWriter的.print()方法即可将数据通过HttpServletResponse传递给前端。
首先定义一个返回数据的module,
public class ResponseModel { public static final int SUCCESS = 200; public static final int ERROR = 100; private Integer status; private String message; private Object data; private Locale locale; public ResponseModel(){ this.status = SUCCESS; this.locale = Locale.CHINA; } public ResponseModel put(String key, Object value){ if(this.data == null || !(data instanceof Map)){ this.data = new HashMap<String,Object>(); } Map<String, Object> map = (Map<String,Object>)this.data; map.put(key,value); return this; } public Object getData(){ return data; } public ResponseModel setData(Object data){ this.data = data; return this; } public ResponseModel setErrorMsg(ErrorMsg errorMsg){ this.setStatus(errorMsg.getCode()); this.setMessage(errorMsg.getMessage()); return this; } public ResponseModel setStatus(int status){ this.status = status; if(ERROR == status){ this.setMessage("系统错误"); } return this; } public ResponseModel setMessage(String message){ this.message = message; return this; } public int getStatus(){ return status; } public String getMessage(){ return message; } }
再定义一个holder的Bean,返回module作为一个线程级变量放到Bean中,
@Component public class ResponseHolder { private static ThreadLocal<Object> model = new ThreadLocal<>(); public void clean(){ model.remove(); } public ResponseModel getModel(){ Object o = model.get(); if(o == null){ this.setModel(new ResponseModel()); o = this.getObject(); } if(o != null && o instanceof ResponseModel){ return (ResponseModel) o; }else { return null; } } public Object getObject(){ return model.get(); } public void setModel(Object o){ model.set(o); } public ResponseModel put(String key, Object value){ ResponseModel responseModel = this.getModel(); Object data = responseModel.getData(); if(data == null || !(data instanceof Map)){ data = new HashMap<String,Object>(); responseModel.setData(data); } Map<String,Object> map = (Map<String,Object>) data; map.put(key,value); return responseModel; } public ResponseModel setData(Object data){ ResponseModel responseModel = this.getModel(); responseModel.setData(data); return responseModel; } public ResponseModel setErrorMsg(ErrorMsg errorMsg){ ResponseModel responseModel = this.getModel(); responseModel.setStatus(errorMsg.getCode()); responseModel.setMessage(errorMsg.getMessage()); return responseModel; } }
其中的ErrorMsg是一个错误枚举,
public enum ErrorMsg { TEST(1,"test"), SUCCESS(200,"交易完成"), LOGIN_FAIL(101,"登录失败"), LOGOUT_SUCCESS(104,"登出成功"), USER_NOT_FOUND(102,"未注册用户"), USER_DISABLED(103,"无效用户"), NO_LOGIN(105,"未登录"), VERIFY_CODE_ERROR(106,"验证码错误"), SYSTEM_ERROR(100,"系统错误"); private int code; private String message; public int getCode(){ return code; } public String getMessage(){ return message; } ErrorMsg(int code, String message){ this.code = code; this.message = message; } }
接下来定义拦截器,在每个controller完成后从holder中取出数据通过HttpServletResponse传递给前端,
@Component public class ResponseInterceptor implements HandlerInterceptor { @Autowired private ResponseHolder responseHolder; private Logger logger = LogManager.getLogger(ResponseInterceptor.class); @Override public boolean preHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception{ return true; } @Override public void postHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3, ModelAndView var4) throws Exception{ //do noting } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception exception) throws Exception{ if(responseHolder == null){ logger.error("system error", exception); responseHolder.setErrorMsg(ErrorMsg.SYSTEM_ERROR); } String json = JSON.toJSONString(responseHolder.getModel()); this.returnJson(response,json); responseHolder.clean(); } private void returnJson(HttpServletResponse response, String json) throws Exception{ PrintWriter writer = null; response.setCharacterEncoding("UTF-8"); response.setContentType("text/html; charset=utf-8"); try { writer = response.getWriter(); writer.print(json); } catch (IOException e) { logger.error("response error",e); } finally { if (writer != null) writer.close(); } } }
spring提供了拦截器HandlerInterceptorAdapter对应提供了三个preHandle,postHandle,afterCompletion方法。preHandle在业务处理器处理请求之前被调用,
postHandle在业务处理器处理请求执行完成后,生成视图之前执行,afterCompletion在DispatcherServlet完全处理完请求后被调用,可用于清理资源等 。
拦截器定义完成后,不配置是不起作用的,传统的spring项目通过XML文件配置,spring—boot是为了实现无XML配置,所以可以通过如下方式添加,
@Configuration public class WebAppConfig extends org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter { @Autowired private ResponseInterceptor responseInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(responseInterceptor).addPathPatterns("/**").excludePathPatterns("/identifyCode/generate"); } }
这里可是整个拦截器的核心,通过实现addInterceptors接口,我们可以添加自己想加的拦截器,也能配置特殊不需要拦截的接口。代码虽简单,但值得细细揣摩,也有许多可优化的地方!