请求结果返回封装

请求结果返回封装

以下是对返回结果的封装,这样可以让开发者明确的知道代码的业务性
1.对返回结果的设计

public class Result {
    private Integer code;
    private String message;
    private Object data;
}

2.code和message的关系,
code是状态码,message是返回的消息
code,和message是一一对应的关系,为了规范和便于维护,我们采用枚举,此处为了猜测,所以并没有枚举更多code和message.以后有更多的code和message,可以直接在这里进行维护

public enum ResultCode {
    /*成功状态码*/
    SUCCESS(1, "成功"),
    /*参数错误*/
    PARAM_IS_INVALID(1001, "参数无效"),
    PARAM_IS_BLANK(1002, "参数类型错误");
    /*用户错误*/

    private Integer code;
    private String message;

    ResultCode(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    public Integer code() {
        return this.code;
    }

    public String message() {
        return this.message;
    }

}

3.result和ResultCode的关系

public class Result {
    private Integer code;
    private String message;
    private Object data;

    public Result() {
    }

    public Result(ResultCode resultCode, Object data) {
        this.code = resultCode.code();
        this.message = resultCode.message();
        this.data = data;
    }
    
    private void setResultCode(ResultCode resultCode) {
        this.code = resultCode.code();
        this.message = resultCode.message();
    }
    //此处省略get和set
    }

4.为了不在controller层对返回结果进行封装,此时我们在result类下提供静态方法

   //返回成功
    public static Result successs(){
        Result result = new Result();
        result.setResultCode(ResultCode.SUCCESS);
        return result;
    }

    public static Result successs(Object data){
        Result result = new Result();
        result.setResultCode(ResultCode.SUCCESS);
        result.setData(data);
        return result;
    }

    //返回失败
    public static Result failure(ResultCode resultCode){
        Result result = new Result();
        result.setResultCode(resultCode);
        return result;
    }

    public static Result failure(ResultCode resultCode,Object data){
        Result result = new Result();
        result.setResultCode(resultCode);
        result.setData(data);
        return result;
    }

5.编写自定义注解,确定该类或该方法将被我们进行封装

@Retention(RUNTIME)
@Target({TYPE,METHOD})
@Documented
public @interface ResponseResult {
}

6.拦截器的实现

@Component
public class ResponseResultInterceptor extends HandlerInterceptorAdapter {
    public static final String RESPONSE_RESULT_ANN ="RESPONSE_RESULT_ANN";
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
       if (handler instanceof HandlerMethod){
           final HandlerMethod handlerMethod = (HandlerMethod) handler;
           final Class<?> clazz = handlerMethod.getBeanType();
           final Method method = handlerMethod.getMethod();
            //判断是否在类对象上加了注解
           if (clazz.isAnnotationPresent(ResponseResult.class)){
                request.setAttribute(RESPONSE_RESULT_ANN,clazz.getAnnotation(ResponseResult.class));
           }else if (method.isAnnotationPresent(ResponseResult.class)){//方法体是否有注解
               request.setAttribute(RESPONSE_RESULT_ANN,method.getAnnotation(ResponseResult.class));
           }
       }
        return true;
    }
}

7.真正操作返回结果的

@ControllerAdvice
public class ResponseResultHandler implements ResponseBodyAdvice<Object> {
    //标记名称
    public static final String RESPONSE_RESULT_ANN ="RESPONSE_RESULT_ANN";
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        //是否请求,包含了 包装注解,没有就直接返回,不需要重写返回体
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = sra.getRequest();
        //判断请求是否有包装标记
        ResponseResult responseResultAnn = (ResponseResult) request.getAttribute(RESPONSE_RESULT_ANN);
        return responseResultAnn==null?false:true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        return Result.successs(body);
    }
}

8.controller此时只需要注重逻辑,对返回结果格式化不需要controller进行考虑

@RestController
@RequestMapping("/api")
public class IndexController {

    @Autowired
    private GoodsService goodsService;
    @Autowired
    private SellerService sellerService;

    @GetMapping("/seller")
    @ResponseResult
    public Seller seller() {
        Seller seller = sellerService.query();
        return seller;
    }
    }

此时只要我们的被请求类或者方法由我们的自定义注解,那我们就可以只注重我们的业务了
最终请求后得到的数据会是

{
code: 1,
message: "成功",
data: {
id: 1,
name: "雨荷塘",
avatar: "http://static.galileo.xiaojukeji.com/static/tms/seller_avatar_256px.jpg",
score: 0,
description: "蜂鸟专送",
deliveryTime: "38",
bulletin: "粥品香坊其烹饪粥料的秘方源于中国千年古法,在融和现代制作工艺,由世界烹饪大师屈浩先生领衔研发。坚守纯天然、0添加的良心品质深得消费者青睐,发展至今成为粥类的引领品牌。是2008年奥运会和2013年园博会指定餐饮服务商。",
supports: [
{
id: 0,
type: "0",
description: "蜂鸟专送"
},
{
id: 0,
type: "1",
description: "蜂鸟专送"
},
{
id: 0,
type: "2",
description: "蜂鸟专送"
},
{
id: 0,
type: "3",
description: "蜂鸟专送"
},
{
id: 0,
type: "4",
description: "蜂鸟专送"
}
]
}
}

code,massage,以及data都会自动被封装好


版权声明:本文为TowerTan原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。