Java封装返回数据类型
介绍
在做Java请求返回json数据的时候,我们常做的就是封装数据类型,每个方法的返回类型都是自己定义封装的数据类型,我如果在方法上直接定义void类型,是否就不能返回json数据了呢,我做了下面的测试。
自定义封装类
package org.jeemp.common;
import org.jeemp.enums.IErrorCode;
import org.jeemp.enums.ResultCode;
/**
* 通用返回对象
*/
public class CommonResult<T> {
private long code;
private String message;
private T data;
protected CommonResult() {
}
protected CommonResult(long code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
/**
* 成功返回结果
*
* @param data 获取的数据
*/
public static CommonResult success(T data) {
return new CommonResult(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMessage(), data);
}
/**
* 成功返回结果
*
* @param data 获取的数据
* @param message 提示信息
*/
public static CommonResult success(T data, String message) {
return new CommonResult(ResultCode.SUCCESS.getCode(), message, data);
}
/**
* 失败返回结果
* @param errorCode 错误码
*/
public static CommonResult failed(IErrorCode errorCode) {
return new CommonResult(errorCode.getCode(), errorCode.getMessage(), null);
}
/**
* 失败返回结果
* @param message 提示信息
*/
public static CommonResult failed(String message) {
return new CommonResult(ResultCode.FAILED.getCode(), message, null);
}
/**
* 失败返回结果
*/
public static CommonResult failed() {
return failed(ResultCode.FAILED);
}
/**
* 参数验证失败返回结果
*/
public static CommonResult validateFailed() {
return failed(ResultCode.VALIDATE_FAILED);
}
/**
* 参数验证失败返回结果
* @param message 提示信息
*/
public static CommonResult validateFailed(String message) {
return new CommonResult(ResultCode.VALIDATE_FAILED.getCode(), message, null);
}
/**
* 未登录返回结果
*/
public static CommonResult unauthorized(T data) {
return new CommonResult(ResultCode.UNAUTHORIZED.getCode(), ResultCode.UNAUTHORIZED.getMessage(), data);
}
/**
* 未授权返回结果
*/
public static CommonResult forbidden(T data) {
return new CommonResult(ResultCode.FORBIDDEN.getCode(), ResultCode.FORBIDDEN.getMessage(), data);
}
public long getCode() {
return code;
}
public void setCode(long code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
方法中直接调用:
@GetMapping("/testJson")
public CommonResult testJson() {
Map map = initUrlService.obtainMapUrls();
return CommonResult.success(map);
}
方法返回类型直接声明void
@GetMapping("/obtainUserInfo")
public void obtainUserInfo() {
Map map = new HashMap<>();
map.put("name","jack");
map.put("age",16);
setRespAttr("dataMaps",map);
}
最主要的就是setRespAttr("dataMaps",map);,怎么将代码中的数据对象传出去?
这边想到的是做一个拦截器,将数据对象转json后传出去:
/**
* @author JackRen
* @date 2021-12-08 16:19
* @description:
*/
@Component
public class JeempInterceptor implements HandlerInterceptor {
@Autowired
private InitUrlService initUrlService;
/**
* controller方法结束之后调用如果有controller方法有异常则不会调用
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
parseControllerModel(request,response);
}
private void parseControllerModel(HttpServletRequest req, HttpServletResponse resp) throws Exception {
String className=obtainClassName(req,resp);
try {
BaseController baseController = (BaseController) ApplicationUtil.getBean(className);
if (baseController==null) {
return;
}
writeJson(req,resp,baseController.getRespMap());
}catch (Exception e){
// TODO:打印日志,后续加入
}
}
private String obtainClassName(HttpServletRequest req, HttpServletResponse resp) throws Exception {
final String contextPath = req.getContextPath();
final String requestURI = req.getRequestURI();
String path = requestURI.substring(contextPath.length());
path = URLDecoder.decode(path, "UTF-8");
//根据获取的请求url获取className
Map map = initUrlService.obtainMapUrls();
if (map==null) {
return "";
}
return StrUtil.removePreAndLowerFirst(String.valueOf(map.get(path)), Constant.PREFIX_URL);
}
private void writeJson(HttpServletRequest req, HttpServletResponse resp, Map model) throws Exception {
writeRespHeaders(req, resp);
resp.setHeader("Content-Type", "text/plain; charset=UTF-8");
Writer out = resp.getWriter();
out.write(toJson(model));
}
private void writeRespHeaders(HttpServletRequest req, HttpServletResponse resp) {
// http://blog.55minutes.com/2011/10/how-to-defeat-the-browser-back-button-cache/
resp.setHeader("Cache-Control", "no-cache, max-age=0, must-revalidate, no-store");
resp.setHeader("Pragma", "no-cache"); // HTTP 1.0 backward compatibility
resp.setDateHeader("Expires", 0); // Causes the proxy cache to see the page as "stale"
}
public String toJson(Object obj) {
if (obj == null) {
return null;
}
return JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect);
}
}
总结
void声明说了那么多,其实就是将返回的数据对象通过HttpServletResponse返回,如果想要做到通用,最简单的办法就是自己定义一些规则,比如在定义bean的时候自己定义名称,方法的请求url必须以bean的名称开头,在拦截的时候可以根据这样的规则找到bean,进而可以拿到这个类上要传递的数据。
我这边没有定义规则,我想的是根据url反向查找类名,接口名,注解值,然后根据拿到的类名再去查找bean,但是会有一些问题,比如不同的开发人员在定义bean的时候,有的不去定义,系统默认处理,但是有的同事却自己定义,这样的话根据类型就找不到这个bean,所以会出现问题。
最好的解决办法就是自己定义规则,所有的请求按照自己的规则来,然后自己按照规则进行处理,这样就可以在方法返回类型中直接定义void。
评论