SpringBoot修改请求参数和返回结果

SpringBoot修改请求参数和返回结果

注:本文基本上照抄自:https://www.codenong.com/cs107098749/,记录一下方便自己之后再找而已。

1.修改请求参数

1.1.自定义HttpServletRequest的包装类

Spring 中的 request.getInputStream()和 request.getReader()只能被读取一次,而@RequestBody注解底层也是通过流来请求数据,所以需要把拦截器中的数据流保存下来,让 controller 层可以读取的数据

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;

/**
 * @author tianxc
 * @title: RequestWrapper
 * @projectName mycim-module
 * @description:
 * @date 2022/4/14 11:25
 */
public class RequestWrapper extends HttpServletRequestWrapper {
    private String body;

    public RequestWrapper(HttpServletRequest request) {
        super(request);
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        InputStream inputStream = null;
        try {
            inputStream = request.getInputStream();
            if (inputStream != null) {
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                char[] charBuffer = new char[128];
                int bytesRead = -1;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            } else {
                stringBuilder.append("");
            }
        } catch (IOException ex) {

        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        body = stringBuilder.toString();
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
        ServletInputStream servletInputStream = new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {
            }

            @Override
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }
        };
        return servletInputStream;

    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }

    public String getBody() {
        return this.body;
    }

    // 赋值给body字段
    public void setBody(String body) {
        this.body = body;
    }

1.2.自定义过滤器,将HttpServletRequest替换成自定义的包装类

image-20220414132035897

1.3.自定义拦截器

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mycim.framework.logging.Logger;
import com.mycim.framework.logging.LoggerFactory;
import com.mycim.webapp.wrapper.RequestWrapper;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author tianxc
 * @title: LoginInterceptor
 * @projectName mycim-module
 * @description:
 * @date 2022/4/14 10:47
 */
@Component
public class RequestParamInterceptor implements HandlerInterceptor {
    private final Logger logger = LoggerFactory.getLogger(LoginInterceptor.class);
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println(handler);
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod)handler;
        pushRequest2Body(request, handlerMethod);

        return true;
    }

    private void pushRequest2Body(HttpServletRequest request, HandlerMethod handlerMethod) {
        try{
            MethodParameter[] methodParameters = handlerMethod.getMethodParameters();
            if(ArrayUtils.isEmpty(methodParameters)) {
                return;
            }
            if(request instanceof RequestWrapper){
                RequestWrapper requestWrapper = (RequestWrapper)request;
                String body = requestWrapper.getBody();
                JSONObject param = JSONObject.parseObject(body).getJSONObject("body");
                requestWrapper.setBody(JSON.toJSONString(param));
            }
        }catch (Exception e){
            logger.warn("fill userInfo to request body Error ", e);
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }
}

2.修改返回参数

2.1.自定义返回值拦截器

因为SpringBoot默认的ResponseBody的处理程序就是HandlerMethodReturnValueHandler,所以我们自己写的HandlerMethodReturnValueHandler通常无法生效,

非要使用HandlerMethodReturnValueHandler,那么只能替换掉默认的,

如果只是想对Controller的所有返回值进行封装,产生上面的效果,使用ResponseBodyAdvice会更加简单一些

import com.mycim.webapp.Response;
import com.mycim.webapp.ResponseMsgBuilder;
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.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * @author tianxc
 * @title: InterceptResponse
 * @projectName mycim-module
 * @description:
 * @date 2022/4/14 11:14
 */
@ControllerAdvice
public class InterceptResponse 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) {
        if (body instanceof Response) {
            return body;
        }
        return ResponseMsgBuilder.buildSuccessResponse(body);
    }
}

原文:https://www.codenong.com/cs107098749/

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
# 基于springBoot编写的RESTFul API 本项目可用于快速搭建基于springBoot的RESTFul API服务,同时集成了swagger作为接口的在线文档与调试工具,数据交互格式建议是JSON格式。 ## 增强理解 [Spring Boot集成swagger2生成接口文档](https://www.jianshu.com/p/a115c9367a59) [自定义RESTful API服务规范](https://www.jianshu.com/p/bdea0385a77e) ## RESTFul API 首先本项目是一个RESTFul API服务的demo,与此同时再集成了一些做API常用的工具。 对于RESTFul API服务各有各的见解,网上大多是自己封装了controller层统一格式返回,通常情况下,不管你怎么请求,它总是响应你的http状态码为200。 而本项目中充分结合了HTTP状态码规范,使用ResponseEntity + HttpStatus的方式完成我们的API。当然,你想做一个完全具有RESTFul风格的API,你需要具有良好的RESTFul风格的资源设计能力。 ## 全局异常处理 采用@RestControllerAdvice + @ExceptionHandler的方式对全局异常进行处理,同时加入了常见的一些自定义异常类。 ## 参数验证器 采用spring提供的@Validated注解结合hibernate的validator进行验证,你只需要在你的验证实体对象中使用验证注解,如@NotNull、@NotBlank等,同时在你的controller方法中加入@Validated注解即可,验证结果信息已经由全局异常处理器帮你做好了。 ## TOKEN验证 当我们的API需要登录后才能访问时,简单做法是登录验证成功后给客户端生成一个token,客户端后续的请求都需要带上这个token参数,服务端对这个token进行验证,验证通过即可访问API。本项目中也集成了token的生成,同时通过拦截器统一验证了token的有效性,这依赖于redis来存储token,但这也是比较流行的做法。 你只需要在controller中需要的地方加入@AccessToken注解即可,同时如果你需要当前登录的用户信息,只需要在方法参数中加入@UserPrincipal注解修饰参数UserPrincipalVO即可。 代码示例: ``` // 在登录业务类中注入用户TOKEN组件 @Autowired private UserTokenComponent userTokenComponent; // 登录 public UserPrincipalVO login(String account, String pwd) { // 登录逻辑验证 ~~~~~ // 验证成功后,可得到用户信息 // 根据用户信息创建token, 可以把用户其它信息填充进UserPrincipalVO中,提供了全参的构造方法 UserPrincipalVO userPrincipalVO = new UserPrincipalVO(account); return userTokenComponent.createToken(userPrincipalVO); } ``` ``` @ApiOperation(value = "需要登录后才能访问的API") @GetMapping("/token") @AccessToken public ResponseEntity<UserPrincipalVO> testToken(@ApiIgnore @UserPrincipal UserPrincipalVO user) { return ResponseEntity.ok(user); } ``` ## 参数签名验证 当我们的API需要作为开放接口时,一般会为接入方分配对应的accessKey和secret,接入方每次请求我们的API时,需要把accessKey和secret与其他参数进行统一的方式签名得到签名串sign,同时把sign作 ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
# SpringBoot整合Mybatis脚手架。 ### 运行环境: - JDK 1.8 or later - Gradle 2.3+ ### 开发者使用说明 1. 进入项目根目录 2. 安装项目依赖,运行`gradle build -t` 3. 启动服务 `gradle bootRun` ### 静态文件服务说明 在/src/main/resources/static目录下自由放置静态文件,放置的文件目录跟url对应。 ####举例 - 放置的文件为main.html,那么访问路径为:http://localhost:3000/main.html - 放置的文件为js/app.js,那么访问路径为: http://localhost:3000/js/app.js ## 管理员登录模块 ``` 管理员登录(管理员也是会员) 管理员分为: 系统管理员: 修改用户名重置密码,删除用户,管理管理员, 普通管理员: 增添会员,查看会员列表,挂失(冻结)。 管理员字段: 账号,密码。姓名,手机号。 ----------------------------------------管理员登录-------------------------------------- 请求参数:adminAccount adminPassword API: /admin/login GET 返回参数:{ "status": { "code": "1", "message": "success" }, "object": null } ``` ## 系统管理员模块 ### 管理员管理 - 增加管理员 ``` 增加管理员 请求参数:adminAccount(账号),adminPassword (密码) adminName(姓名),adminPhone(手机号)。 API: /admin POST 返回参数:{ "status": { "code": "1", "message": "success" }, "object": 人员信息 } ``` - 查询管理员 ``` 查询管理员 请求参数: key(以姓名模糊查询,后期再改) API: /admin GET (如果带参,模糊查询,无参,全部) 返回参数:{ "status": { "code": "1", "message": "success" }, "object": 人员信息 } ``` - 删除管理员 ``` 删除管理员 请求参数:adminAccount(账号) API:/admin DELETE 返回参数:{ "status": { "code": "1", "message": "success" }, "object": null } ``` ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
# Design 基于SpringBoot的毕业设计选题系统 ## 接口设计 ### 1.角色信息 - @RequestMapping("/role") #### 1.1.角色登录 ##### 接口名:verifyRole ##### 请求参数: | 参数名 | 类型 | 说明 | 备注 | |:---- |:---- |:---- |:---- | | roleName | String | 登录名 | | passWord | String | 登录密码 | ##### 返回参数: | 参数名 | 类型 | 说明 | 备注 | |:---- |:---- |:---- |:---- | | isSuccessful | Boolean | 是否成功 | | roleId | Integer | 角色ID | | roleType | Integer | 角色类型。<br>0-领导;<br>1-管理员 | #### 1.2.根据角色ID获取角色信息 ##### 接口名:getRoleById ##### 请求参数: | 参数名 | 类型 | 说明 | 备注 | |:---- |:---- |:---- |:---- | | id | Integer | 角色ID | ##### 返回参数: | 参数名 | 类型 | 说明 | 备注 | |:---- |:---- |:---- |:---- | | isSuccessful | Boolean | 是否成功 | | data | Role | 角色信息 | ### 2.教师信息 #### 2.1.分页获取教师信息 ##### 接口名:listTeachersByCurr ##### 请求参数: | 参数名 | 类型 | 说明 | 备注 | |:---- |:---- |:---- |:---- | | page | Integer | 页码数 | | num | Integer | 每页数量 | ##### 返回参数: | 参数名 | 类型 | 说明 | 备注 | |:---- |:---- |:---- |:---- | | isSuccessful | Boolean | 是否成功 | | total | Integer | 数据总数 | | count | Integer | 当前页数据数 | | list | List | 数据信息 | #### 2.2.根据ID获取教师信息 ##### 接口名:getTeacherById ##### 请求参数: | 参数名 | 类型 | 说明 | 备注 | |:---- |:---- |:---- |:---- | | id | Integer | 教师ID | ##### 返回参数: | 参数名 | 类型 | 说明 | 备注 | |:---- |:---- |:---- |:---- | | isSuccessful | Boolean | 是否成功 | | data | Entity | 教师信息 | #### 2.3.根据教师ID和登录密码修改教师登录密码 ##### 接口名:updatePasswordById ##### 请求参数: | 参数名 | 类型 | 说明 | 备注 | |:---- |:---- |:---- |:---- | | id | Integer | 教师ID | | password | String | 教师登录密码 | | newPassword | String | 新登录密码 | ##### 返回参数: | 参数名 | 类型 | 说明 | 备注 | |:---- |:---- |:---- |:---- | | isSuccessful | Boolean | 是否成功 | | message | String | 消息 | #### 2.4.分页获取所有老师专长信息 ##### 接口名:listExpertisesByCurr ##### 请求参数: | 参数名 | 类型 | 说明 | 备注 | |:---- |:---- |:---- |:---- | | pa ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
### 技术选型: ###### 后端支持: 主体支持: **JDK1.8**、**Springboot1.4.2** 页面支持:**html** ORM支持: **mybatis3.2.8** ORM插件支持: **mapper3.3**、**PageHelp4.1** 分页 权限支持:**shiro1.2.5** 访问接口支持: **swagger2** JSON支持:**fastjson** 连接池支持:**druid** 缓存支持:**ehcache** 、**guava** 参数验证支持:**jsr303** web容器支持:**内嵌tomcat** maven支持:**maven3.3.9** maven仓库支持:**阿里云** 代码精简与日志支持: **lombok** ###### 前端支持: 主体支持:**jQuery** 风格支持:**layui** 图标支持:**font-awesome** 弹窗支持:**layer** websocket支持:**sockjs** 树结构支持:**ztree** ### 支持情况 1. 修改 **config/application-dev.properties** JDBC 链接属性。 2. tomcat 端口在 **config/application-dev.properties** 更改,默认**8082**。 3. 自动创建数据库,关闭请在配置文件找到 JDBC 链接删除 **&createDatabaseIfNotExist=true**。 4. 自动运行SQL脚本,关闭请注释掉 **spring.datasource.schema**。 5. 默认登录 **admin/admin** 6. 打印后台 SQL 语句。 (打开/关闭 注释该方法 com.zyf.framework.config.MybatisAutoConfiguration.pageHelper) 7. 切换配置文件 **application.properties** 设置参数 8. 访问`http://localhost:8082/api`可以查看项目的接口情况。(打开/关闭 com.zyf.other.api.config.SwaggerConfig)。 9. 使用 html,基本使用 ajax 异步请求,页面不刷新。 10. 基于 shiro 改造的 sso 单机实现,登录生成 token 存储在用户 cookies 中,请求解析 cookies,以解析成功作为标识。 11. 交互上使用 layui,使用第三方功能。 12. 热刷新实体 mapper.xml文件 MapperRefresh.java(打开/关闭 config/application-dev.properties -> mapper.mapper-refresh-enable: true/false) 13. 自动注册枚举到 mybatis,查询出来自动转换枚举。 14. 消息转换未配置,如果需要返回 map 自动转换成 UTF-8 json 及需要保证 JDK8 LocalDateTime 类日期的正确性,请打开 com.zyf.admin.support.config.WebConfiguration.configureMessageConverters 注释部分。 15. 采用 mapper3 pageHelper 插件,因此大部分通用 dao 层及 xml 都不比书写。 16. 后台基本使用 resultFull 风格,前端做的事情比较多。 17. 对象池测试 com.zyf.other.pool.test.RunTest#main ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值