@restcontroller返回的是html不是json为啥_Spring Boot API 统一返回格式封装

今天给大家带来的是Spring Boot API 统一返回格式封装,我们在做项目的时候API 接口返回是需要统一格式的,只有这样前端的同学才可对接口返回的数据做统一处理,也可以使前后端分离 拉勾IT课小编为大家分解
模式的开发中,只关注于业务,而无需考虑对每一个返回结果做处理,中心思想是,所有结果封装为json,错误信息通过异常抛出,统一捕捉处理后返回前端,举例:如果插入一条用户信息,而
这个用户已经在系统中存在,则返回插入失败,我们用枚举定义一个返回信息,通过异常抛出。

35ddfcd4057550f4b6f3133572e99eb9.png

源码地址https://gitee.com/zgc005/resut

废话少说 上代码

先讲项目结构

├── LICENSE

├── demo.iml

├── pom.xml

├── re

└── src

├── main

│ ├── java

│ │ └── com

│ │ └── result

│ │ └── demo

│ │ ├── DemoApplication.java

│ │ ├── common

│ │ │ └── config

│ │ ├── global

│ │ │ ├── advice

│ │ │ │ ├── ExceptionResultAdvice.java ———— 异常捕捉。处理。

│ │ │ │ └── ResponseResultAdvice.java ———— 接口返回统一封装

│ │ │ ├── annotation

│ │ │ │ └── ResponseResult.java ———— 自定义标签 用来验证接口是否需要包装返回 并且验证接口是否存在

│ │ │ ├── config

│ │ │ │ └── GlobalConfig.java ———— 全局配置,读取*.yml 配置文件信息

│ │ │ ├── enums

│ │ │ │ └── ResultCode.java ———— api异常枚举

│ │ │ ├── exception

│ │ │ │ └── BizException.java

│ │ │ ├── filterLists

│ │ │ │ ├── FilterConfig.java ———— Filter 配置

│ │ │ │ └── SignAuthFilter.java ———— 接口请求验签等操作

│ │ │ ├── interceptor

│ │ │ │ ├── ResponseResultInterceptor.java 用来处理返回数据是否需要封装

│ │ │ │ └── WebConfigurer.java

│ │ │ ├── result

│ │ │ │ ├── EnumInterface.java

│ │ │ │ └── Result.java

│ │ │ └── sign

│ │ │ ├── BodyReaderHttpServletRequestWrapper.java ————对请求流处理

│ │ │ ├── HttpUtils.java

│ │ │ └── SignUtil.java

│ │ ├── modules

│ │ │ ├── goods

│ │ │ │ ├── controller

│ │ │ │ │ └── GoodsController.java

│ │ │ │ ├── dao

│ │ │ │ │ └── GoodsDao.java

│ │ │ │ ├── entity

│ │ │ │ │ ├── Goods.java

│ │ │ │ │ ├── GoodsBrandBean.java

│ │ │ │ │ ├── GoodsImage.java

│ │ │ │ │ ├── ProductEntity.java

│ │ │ │ │ └── TestName.java

│ │ │ │ └── service

│ │ │ │ ├── GoodsService.java

│ │ │ │ └── impl

│ │ │ │ └── GoodsServiceImpl.java

│ │ │ ├── order

│ │ │ │ ├── controller

│ │ │ │ ├── dao

│ │ │ │ ├── entity

│ │ │ │ └── service

│ │ │ ├── user

│ │ │ │ ├── controller

│ │ │ │ ├── dao

│ │ │ │ ├── entity

│ │ │ │ └── service

│ │ │ └── util

│ │ │ └── JsonTOpagaData.java

│ │ ├── scheduled

│ │ │ ├── ScheduledMachine.java

│ │ │ └── ScheduledProduct.java

│ │ └── test

│ │ ├── Demo.java

│ │ └── Test.java

│ └── resources

│ ├── application-dev.yml

│ ├── application-pro.yml

│ ├── application-test.yml

│ ├── application.yml

│ └── mapper

│ ├── goods

│ │ └── GoodsDao.xml

│ ├── machine

│ │ └── MachineDao.xml

│ ├── order

│ └── user

└── test

└── java

└── com

└── result

└── demo

└── DemoApplicationTests.java

以下是几个核心的类

  • ExceptionResultAdvice :所有的异常都会通个这个类进行捕捉,处理,如果有新增加的Exception 只需要新增方法即可,如新增一个XXXException的方法

@ExceptionHandler(value = XXXException.class)

public Result XXXexceptionHandler(XXXException xxxexception){

log.info("系统异常处理:{}",xxxexception);

return Result.error();

}

  • ResponseResultAdvice: 重写返回数据,这个类主要是对返回结果进行封装,而不需要在每一个Controller 里的方法进行封装,简化代码,做到只关注业务。

这里有一个坑:ResponseBodyAdvice 返回类型如果是String 的话会报错,原因大家可以自行查看,所以这个地方要对String 类型的数据进行处理

@Override

public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {

log.info("进入返回提重写格式 处理中。。。。。。");

Result result = new Result();

// 包含Result 说明是异常

if (body instanceof Result) {

return body;

}

if (body instanceof String) {

String str = JSON.toJSONString(Result.success(body));

return str;

}

return Result.success(body);

}

  • ResponseResult: 这个是自定义的标签,主要是用来判断Controller 类的返回数据是否需要封装用法如下
bb7f4852c71c782ac3cb65d94dabbf3c.png

@Slf4j

@RestController

@RequestMapping(value = "/api")

@ResponseResult

public class Test {

}

在ResponseResultInterceptor 类里会对这个标签进行判断处理。

public class ResponseResultInterceptor implements HandlerInterceptor {

public static final String RESPONSE_RESULT_ANN = "RESPONSE-RESULT-ANN";

/**

* 此代码核心思想,就是获取此请求,是否需要返回值包装,设置一个属性标记。

*

*/

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

990ab76ca12f5b596f8be7371a5a2a96.gif

// 方法校验

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;

} else {

return initResponse(response, ResultCode.API_NOT_EXIST);

}

}

private boolean initResponse(HttpServletResponse response,ResultCode resultCode) throws IOException {

response.setCharacterEncoding("utf-8");

response.setContentType("application/json; charset=utf-8");

PrintWriter writer = response.getWriter();

JSONObject jsonObject = new JSONObject();

jsonObject.put("code", resultCode.getCode());

jsonObject.put("message", resultCode.getMessage());

jsonObject.put("data", null);

writer.write(jsonObject.toString());

return false;

}

小结:下载源码测试,如果有问题,大家可以留言,或者私信。对于面向对象编程的逻辑思维要始终贯穿于整个项目,对象的封装也是必然,一个类是对象,多个类组成的模块也是对象,甚至在庞大的系统中,每一个子系统都是一个对象,这也就是OOP的核心 ,一切皆对象,所以没有对象的同学要抓紧时间找个对象,只有这样你才会知道如何面向对象

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值