1、Controller代码
以下是Controller方法源码:
@RestController
@RequestMapping("/manage/user")
public class TestController {
private Logger logger = LoggerFactory.getLogger(TestController.class);
/** * 通过会员id获取会员信息及详情 * * @param id 会员id * @return app msg */
@GetMapping("/edit/{id}")
public AppMessage edit(@PathVariable Integer id) {
if (null == id) {
return AppMessage.error(-3, "会员ID不能为空");
}
// 查询会员对象
User user = userService.queryById(id);
if (user == null) {
return AppMessage.error(-3, "根据会员ID未查询到对应会员");
}
return AppMessage.success(user);
}
}
2、拦截处理器
下面已经封装好了一个拦截处理类以供参考:
package com.yclimb.test;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
/** * 拦截Controller方法默认返回参数,统一处理返回值/响应体 */
@ControllerAdvice
public class TestResponseBodyAdvice implements ResponseBodyAdvice {
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
System.out.println("TestResponseBodyAdvice==>beforeBodyWrite:" + o.toString() + ","
+ methodParameter);
return o;
}
@Override
public boolean supports(MethodParameter methodParameter, Class aClass) {
return true;
}
}
方法讲解
个人理解:
ResponseBodyAdvice 接口是在 Controller 执行 return 之后,在 response 返回给客户端之前,执行的对 response 的一些处理,可以实现对 response 数据的一些统一封装或者加密等操作。
该接口一共有两个方法:
(1)supports —— 判断是否要执行beforeBodyWrite方法,true为执行,false不执行 —— 通过supports方法,我们可以选择哪些类或哪些方法要对response进行处理,其余的则不处理。
(2)beforeBodyWrite —— 对 response 处理的具体执行方法。
package com.abc.demo;
import com.github.pagehelper.Page;
import com.abc.pojo.bean.ResponseResult;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ControllerAdvice
public class ControllerAdviceHandler implements ResponseBodyAdvice<Object> {
@ResponseBody
@ExceptionHandler(value = Throwable.class)
public ResponseResult catchAllError(HttpServletRequest request, HttpServletResponse response, Throwable error) {
return ResponseResult.exception(error);
}
@Override
public boolean supports(MethodParameter method, Class<? extends HttpMessageConverter<?>> clazz) {
return method.getContainingClass().getPackage().getName().startsWith("com.abc") &&
(method.getContainingClass().getAnnotation(RestController.class) != null ||
(method.getMethod() != null && method.getMethod().getAnnotation(ResponseBody.class) != null));
}
@Override
public Object beforeBodyWrite(Object result, MethodParameter methodParameter, MediaType mediaType,
Class<? extends HttpMessageConverter<?>> aClass,
ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
return result instanceof ResponseResult ? result :
result instanceof Page ? ResponseResult.page((Page<?>) result) :
ResponseResult.successData(result);
}
}
有一个Controller类,返回参数为OutputObject,我们通过ResponseBodyAdvice,对该类的所有方法返回的OutputObject中的部分数据进行统一加密处理。
// 对响应报文统一处理,对bean内容进行加密
@Component
//声明该类要处理的包路径
@ControllerAdvice("com.cmos.edcreg.web.controller")
public class ResponseAdvice implements ResponseBodyAdvice {
private final Logger logger = LoggerFactory.getLogger(ResponseAdvice.class);
// 对response处理的具体方法
@Override
public Object beforeBodyWrite(Object arg0, MethodParameter arg1,
MediaType arg2, Class arg3, ServerHttpRequest arg4,
ServerHttpResponse arg5) {
OutputObject out = new OutputObject();
try {
//arg0转换为OutputObject类型
ObjectMapper objectMapper=new ObjectMapper();
out = objectMapper.readValue(org.json.JSONObject.valueToString(arg0), OutputObject.class);
//获取加密密钥
String oldEncryptKey = out.getBean().get("oldEncryptKey");
//获取加密字符串
DesSpecial des = new DesSpecial();
String encryptData = des.strEnc(JSON.toJSONString(out.getBean()), oldEncryptKey, null, null);
//封装数据(清除原来数据,放入加密数据)
out.getBean().clear();
out.getBean().put("data", encryptData);
return out;
} catch (Exception e) {
logger.error("返回报文处理出错", e);
out.setReturnCode(ReturnInfoEnums.PROCESS_ERROR.getCode());
out.setReturnMessage(ReturnInfoEnums.PROCESS_ERROR.getMessage());
return out;
}
}
/* 选择哪些类,或哪些方法需要走beforeBodyWrite * 从arg0中可以获取方法名和类名 * arg0.getMethod().getDeclaringClass().getName()为获取方法名 */
@Override
public boolean supports(MethodParameter arg0, Class arg1) {
return "com.cmos.edcreg.web.controller.GdH5AppointmentActiveVideoNewController".equals(arg0.getMethod().getDeclaringClass().getName());
}
}
对controller层返回值进行修改增强处理。比如返回值5,需要封装成:{“code”:“0”,“data”:5,“msg”:“success”} 格式返回前端
1、controller层业务代码
@RestController //此注解包含@ResponseBody注解
@RequestMapping("/mp")
public class ResponseBodyAdviceController {
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public int hello() {
return 5;
}
}
2、实现ResponseBodyAdvice接口的切面类
/** *此注解针对controller层的类做增强功能,即对加了@RestController注解的类进行处理 */
@ControllerAdvice(annotations = RestController.class)
public class RestResultWrapper implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
ServerHttpResponse response) {
//定义一个统一的返回类
RestResult responseResult = new RestResult( "0", body, "success");
//如果handler处理类的返回类型是String(即控制层的返回值类型),为了保证一致性,这里需要将ResponseResult转回去
if(body instanceof String) {
return JSON.toJSONString(responseResult);
}
//封装后的数据返回到前端页面
return JSONObject.toJSON(responseResult);
}
}
3、返回公共类的创建
// 统一返回Rest风格的数据结构
public class RestResult<T> implements Serializable {
private String code = "2000";
// 成功时返回的数据,失败时返回具体的异常信息
private T data;
// 请求失败返回的提示信息,给前端进行页面展示的信息
private String message ;
public RestResult() {
}
@Override
public String toString() {
return "RestResult{" +
"code='" + code + '\'' +
", data=" + data +
", message=" + message +
'}';
}
public RestResult(String code, T data, String message) {
this.code = code;
this.data = data;
this.message = message;
}
}
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/qq_43842093/article/details/121526596
内容来源于网络,如有侵权,请联系作者删除!