今天老板给我了一套代码,然后我就拿过去研究,代码的风格是SSM + Shiro + nginx + SpringBoot的MVC架构风格,springboot,是当下很火的一个框架,配合springcloud,dubbo可以完成分布式,当然,今天的重点不在这里,

今天看了一下代码的组织结构,大致跟以往的项目架构类似,不过有一些还是有些区别:

区别1:全局异常处理器。以往再写项目的时候,全局异常处理器都是自己定义在代码或者xml里(也就是声明在代码里),定义在

afterCompletion
 HashMap<String, String> msg = new HashMap<String, String>();
if (ex != null) {
msg.put("result", "fail");
if(ex instanceof CrudException){
CrudException exception = (CrudException) ex;
msg.put("messageCode", exception.getCode());
msg.put("messageText", ex.getMessage());
}
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(msg);
response.setContentType("application/json;charset=UTF-8");
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
PrintWriter out = response.getWriter();
out.print(json);
out.flush();
out.close();

这个是传统的全局异常定义的写法,在Spring4.2之后,有了新的写法,看下面:

比如:

当然这个写法是SpringBoot的写法,spring的写法就是定义在xml里面,这里就不多说。下来是新项目用到的,也不算新写法,就是个人第一次见到这个,整理了一下,

这样就,相当于对指定异常的捕捉了,@RestControllerAdvice 意思是把这个类当作bean的一个通知类,通知类可以实现SpringAOP的功能,也可以实现拦截器的功能,验证TOKEN,跨域问题比较常见

这个是区别1;

下来是 区别2:

  对请求的Json串解密,以及对响应的Json加密。这个就牵扯到了加解密问题了(暂不深讨,本例用的是AES加解密,本例未展示出AES工具类,如需要,请自行百度:AESUtil工具类)

  过程就是:

    以响应为先:实现ResponseBodyAdvice 接口并实现其方法,在beforeBodyWrite方法进行对响应的Json串加密修改等操作,这里你可以借鉴拦截器的后置方法,或者说

springAOP的返回通知,在这里我使用了自定义注解校验(如果说 Controller层有该注解则加密数据——对某些重要handler进行保护),下来晾代码:

@RestController
public class IndexController {
@GetMapping(value = "/index/{id}",produces = MediaType.APPLICATION_JSON_UTF8_VALUE) @JsonController(encode = true)
//加解密标识 public Object index(@PathVariable(required = false,value = "id") Integer id, @RequestBody(required = false)String name){
  List list = resourceService.selectAll(); // mqSendMessage.sendMessage(MqEnums.TOPIC,MqEnums.LOGIN.getValue()+id,new BasUser()); // AssertUtil.isNullOrEmpty(null,"sys_error"); return "Hello World"+id +" "+ JsonUtils.toJson(list); }}

一切操作看代码:代码中自定义的注解JsonController就是作为加密的标识,下来是配置关键环节了:ResponseBodyAdvice接口,当然,在配置这个接口之前要先声明ControllerAdvice注解。

package org.choviwu.example.base;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.choviwu.example.common.annatation.JsonController;
import org.choviwu.example.common.util.AESUtil;
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.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; import java.io.IOException;
import java.lang.reflect.Type; /**
* 对请求的Json加解密
*/
@RestControllerAdvice(basePackages = "org.choviwu")
public class ResultResponse implements ResponseBodyAdvice<Object> { private String key = "1fdsv3choviwu@#~"; @Override
public boolean supports(MethodParameter methodParameter, Class aClass) {
return true;
} /**
* 加密Json
* @param o 加密的Json
* @return
*/
@Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
//是否加密Json
if(methodParameter.getMethod().isAnnotationPresent(JsonController.class)){
JsonController jsonController = methodParameter.getMethod().getAnnotation(JsonController.class);
//如果加密
if(jsonController.encode()){
//TODO
ObjectMapper objectMapper = new ObjectMapper();
try {
String result = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(o);
return AESUtil.getInstance().encrypt(result,key);//加密
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
} return o;
}
}

这样就完成了加密响应参数的操作了;

下来是声明请求解密:

直接上代码:

package org.choviwu.example.base;

import org.apache.commons.io.IOUtils;
import org.choviwu.example.common.annatation.MyConvert;
import org.choviwu.example.common.annatation.convert.JsonConvert;
import org.choviwu.example.common.util.AESUtil;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice; import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type; @RestControllerAdvice
public class ApiRequest implements RequestBodyAdvice { @Override
public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
return true;
} @Override
public Object handleEmptyBody(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) { return o;
} @Override
public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {
try {
if(methodParameter.getMethod().isAnnotationPresent(MyConvert.class)){
Object obj = aClass.newInstance();
JsonConvert convert = new JsonConvert();
convert.convert(obj);
return new DHttpInputMessage(httpInputMessage);
}
}catch (Exception e){ }
return httpInputMessage;
} @Override
public Object afterBodyRead(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
return o;
} public static class DHttpInputMessage implements HttpInputMessage{
private HttpHeaders headers; private InputStream body;
private String key = "1fdsv3choviwu@#~";
public DHttpInputMessage(HttpInputMessage inputMessage) throws IOException {
this.headers = inputMessage.getHeaders();
this.body = IOUtils.toInputStream(AESUtil.getInstance().decrypt(IOUtils.toString(inputMessage.getBody()),key));
} @Override
public InputStream getBody() throws IOException {
return body;
} @Override
public HttpHeaders getHeaders() {
return headers;
}
}
}

注:在你请求的Controller里面的方法(Mapping)时候,必须要声明@RequestBody,否则,拦截器不会进入你的RequestBodyAdvice

@RequestBody(required = false)String name
参数填写 name={"abc"}
如果看不懂,请自行学习SpringMVC SpringBoot基础 至此,学习完成!
记今天学习的成果。
2018/05/03

记一次学习SpringBoot RequestBodyAdvice ResponseBodyAdvice RestControllerAdvice的更多相关文章

  1. 从零开始学习springboot之热部署的配置

    各位看官大家好,博主之前因为毕业设计以及毕业旅游耽搁了好长一段时间没有更新博客了,从今天起又会慢慢开始学习啦. 今天主要是来学习springboot热部署的配置. 一. 热部署 我们通常在修改某些文件 ...

  2. SpringBoot学习------SpringBoot使用Thymleaf模块访问不了静态页面

    SpringBoot使用Thymleaf模块访问不了静态页面 最近学习SpringBoot的过程中使用了Thymeleaf模块引擎,页面发送请求后老是无法显示静态页面,所有的步骤都是参考资料来执行,自 ...

  3. springboot 详解RestControllerAdvice(ControllerAdvice)(转)

    springboot 详解RestControllerAdvice(ControllerAdvice)拦截异常并统一处理简介 @Target({ElementType.TYPE}) @Retentio ...

  4. 学习SpringBoot零碎记录——配置应用URL名称

    学习SpringBoot配置应用名称,结果发现坑 到网上找 到 https://blog.csdn.net/qq_40087415/article/details/82497668 server: p ...

  5. 学习SpringBoot,整合全网各种优秀资源,SpringBoot基础,中间件,优质项目,博客资源等,仅供个人学习SpringBoot使用

    学习SpringBoot,整合全网各种优秀资源,SpringBoot基础,中间件,优质项目,博客资源等,仅供个人学习SpringBoot使用 一.SpringBoot系列教程 二.SpringBoot ...

  6. 从零开始学习springboot之springboot搭建

    博主刚开始实习不久,还是小白一枚,被公司的各种新奇技术搞得眼花缭乱了好久,主要是用springboot和dubbo构建起来的项目.看完之后才知道springboot真的是java开发者的福音啊 话不多 ...

  7. 关于学习springboot和springcloud的很不错的教程

    近日,逐步开始学习了springboot和springcloud.本以为很简单,但是随着学习的深入,发现其中有很多地方都需要认真揣摩.凡事都需要循序渐进,有一个好的开端就是成功的一半.于是在浩瀚的网络 ...

  8. 学习 spring-boot (一)

    学习文章来自:http://www.ityouknow.com/spring-boot.html Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初 ...

  9. 最新学习springboot 配置注解

    一.概述      Spring Boot设计目的是用来简化新Spring应用的初始搭建以及开发过程.Spring Boot并不是对Spring功能上的增强,而是提供了一种快速使用Spring的方式. ...

随机推荐

  1. N-grams模型、停顿词(stopwords)和标准化处理 - NLP学习(2)

    在上一节<Tokenization - NLP(1)>的学习中,我们主要学习了如何将一串字符串分割成单独的字符,并且形成一个词汇集(vocabulary),之后我们将形成的词汇集合转换成计 ...

  2. 用IIS防止mdb数据库被下载(转载)

    原网址:http://www.cnblogs.com/kingreatwill/p/4224433.html 第一种方法:要求网站管理人员具体asp编程经验.因为现在的销售虚拟主机的系统,已经为用户建 ...

  3. Understand:高效代码静态分析神器详解(一) | 墨香博客 http://www.codemx.cn/2016/04/30/Understand01/

    Understand:高效代码静态分析神器详解(一) | 墨香博客 http://www.codemx.cn/2016/04/30/Understand01/ ===== 之前用Windows系统,一 ...

  4. node + npm 命令

    npm install npm@latest -g  //更新npm npm -v  //运行查看版本号 地址:https://docs.npmjs.com/getting-started/insta ...

  5. 【Python】python函数每日一讲 - dir()

    最近确实是有些忙,刚过了年,积攒了很多事情需要处理,所以每日一函数只能是每两天更新一篇,在这里和大家致歉. 今天我们来看一个非常重要的函数:dir() 中文说明:不带参数时,返回当前范围内的变量.方法 ...

  6. HDU 1338 Game Prediction

    http://acm.hdu.edu.cn/showproblem.php?pid=1338 Problem Description Suppose there are M people, inclu ...

  7. 基于bootstrap动态分页

    bootstrap本身的分页有分页组件 但是却是静态的,无法满足要求,分页必须根据当前的总页数来展示 使用插件bootstrap-paginator github下载地址 https://github ...

  8. 【历史】- .NET之父 - Anders Hejlsberg

    简介 安德斯·海尔斯伯格(Anders Hejlsberg,1960.12~),丹麦人,Turbo Pascal编译器的主要作者,Delphi和.NET之父! 安德斯·海尔斯伯格曾在丹麦技术大学学习工 ...

  9. Spark+Python+Pycharm在Windows下的配置

    http://blog.csdn.net/ydq1206/article/details/51922148

  10. NET中解决KafKa多线程发送多主题

    NET中解决KafKa多线程发送多主题 一般在KafKa消费程序中消费可以设置多个主题,那在同一程序中需要向KafKa发送不同主题的消息,如异常需要发到异常主题,正常的发送到正常的主题,这时候就需要实 ...