Spring拦截器实现controller层json数据返回

来源:互联网 发布:godaddy 域名续费优惠 编辑:程序博客网 时间:2024/05/21 22:43

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中,
@Componentpublic 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传递给前端,
@Componentpublic 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配置,所以可以通过如下方式添加,

@Configurationpublic 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接口,我们可以添加自己想加的拦截器,也能配置特殊不需要拦截的接口。代码虽简单,但值得细细揣摩,也有许多可优化的地方!

 
1 0