记一次学习SpringBoot RequestBodyAdvice ResponseBodyAdvice RestControllerAdvice

今天老板给我了一套代码,然后我就拿过去研究,代码的风格是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进行保护),下来晾代码:

@RestControllerpublic 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 = "[email protected]#~";

    @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 = "[email protected]#~";
        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

原文地址:https://www.cnblogs.com/ChoviWu/p/8987895.html

时间: 2024-08-02 11:54:33

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

学习springboot框架

今天学习了下现在比较流行的搭建框架Spring Boot ,感觉SpringBoot的优势在于对各种组件的支持,通过一些简短的配置可以实现以前需要很多操作才能完成的插件植入.让程序员把更多的时间放在对业务逻辑的思考上,节约时间成本,这是本人第一次写博客,有什么不好的地方希望多多指正,下面言归正传开始SpringBoot的学习: SpringBoot的具体介绍可以参看其他网上介绍,这里就不多说了,就这几天的学习,个人理解,简而言之: (1)它是Spring的升级版,Spring容器能做到的事情,它

一起学习SpringBoot(一) SpringBoot 开始准备

一起学习SpringBoot(一) SpringBoot 开始准备 Spring Boot 简介 简化Spring应用开发的一个框架,整个Spring技术栈的一个大整合,J2EE开发的一站式解决方案 maven设置 <profile> <id>jdk-1.8</id> <activation> <activeByDefault>true</activeByDefault> <jdk>1.8</jdk> <

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

SpringBoot使用Thymeleaf模块访问不了静态页面 最近学习SpringBoot的过程中使用了Thymeleaf模块引擎,页面发送请求后老是无法显示静态页面,所有的步骤都是参考资料来执行,自我检查好久都没有找到问题的答案,哎呦,我这暴脾气就上来了,一个小页面就想难倒我?那我还怎么找到ONE PIECE? 下面就给大家分享一下我悲惨的心路历程: 要使用Thymeleaf模块引擎,我们首先在pom文件中引入相关依赖如下: 这边我们不需要指定版本,因为SpringBoot默认会使用spri

从-1起步学习SpringBoot

最近项目要上SpringBoot,作为一个不太合格的.neter,又要开始用SpringBoot,感觉好方. 但是又有什么办法呢,既然决定不了大方向还是学习一下吧,免得丢了饭碗. 先说一下个人的背景吧 Winform/WPF大概做了2年,感觉趋势不对,转身加入到了Web开发的大队伍中来, .net mvc4,mvc5,,net core1.0,2.0陆续学习并应用,Android开发也有过一段时间接触 接下来准备把学习过程整理出来,作为自己一个笔记,同时也希望对和我一样的初学者有一个引导. 暂时

学习 - SpringBoot hello

1. 下载一个 Intellij IDEA 2. 创建一个新项目,Maven工程 2.1 pom.xml 引入 它可以提供dependency management,也就是说依赖管理,引入以后在申明其它dependency的时候就不需要version了. <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifac

理解学习Springboot(一)

Springboot有何优势呢,网上一大推,这里就不写了. 一.配置maven 1.在maven官网下载maven,http://maven.apache.org/download.cgi 2.将下载好的maven压缩包存储并解压 3.配置maven本地仓库地址与远程镜像仓库地址 可以选择性的将maven配置为计算机全局变量path. 二.IDEA配置maven 源码与文档可以选择性勾选.应用就ok了. 三.创建简单springboot项目 可以选择性勾选thyme leaf(前端模板,可以很好

理解学习Springboot(二)

一.关闭banner 如果不想看到任何的banner,可以将其关闭. 当然也可以自己自定义banner,http://patorjk.com/software/taag/#p=display&h=3&v=3&f=4Max&t=itcast%20Spring%20Boot,有点鸡肋. 二.全局配置文件 阅读Springboot文档,全局的配置文件可以是application.properties或application.yml,在resources目录下或者类路径下的/con

学习springboot(一)

什么是springboot? springboot是一款快速开发的框架,能够快速整合第三方框架,全部采用注解的方式,内置tomcat容器,springboot的web组件默认集成的是springMVC框架. 优点: 1.省去了各种繁琐的配置,开箱即用. 2.可以打jar包直接使用java -jar方式启动,不需要将项目打war包放在tomcat容器中来启动. 关键注解 @RestController @SpringBootApplication 原文地址:https://www.cnblogs.

小编带您学习springboot

一般而言,写个Javaweb应用搭建环境都可能要几十分钟,下载个tomcat服务器,再加上各种xml配置等等,很烦躁,而且每个web应用的配置还差不多,都是什么web.xml,application.xml等等(注解版就是各种配置类@Configuration),既然每个web应用很多配置都一样,那为什么还要每次都动手写或者copy一份呢?假如有什么框架能够帮我们把常用的东西都配置好,有默认值,然后我们只需要关注一些逻辑的编写,那不就大大简化了编程效率吗? 所以就有了springboot,这里s