使用json作为controller入参

使用json作为controller入参

需求

公司的项目中controller是使用json字符串作为入参,这样做对于开发来说十分方便,参数的内容前后端是解耦的,当然使用map也可以起到同样的效果,但是json总归用起来顺手一些。因为公司是自己定义了一套注解而没有使用spring,对于个人来说工程量太大,因此决定直接在spring基础上进行改造。

思路

其实这里实现起来并不复杂,可以使用aop的知识,在请求进入controller的方法之前对请求进行拦截,提取其中的json参数部分,然后填充到自己设置的入参中即可。

实现

首先在springboot项目中引入aop依赖,引入这个依赖之后默认就会开启aop

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>fastjson</artifactId>
	<version>1.2.76</version>
</dependency>

然后在controller中定义自己压迫的json入参,这里以登录操作为例(login方法中的json参数就是我们前端传进来的入参,由于登录操作设计生成并返回token,所以这个接了个response参数,可以忽略,重点在于如何填充json参数):

package com.sunlong.jz.controller;

import com.alibaba.fastjson.JSONObject;
import com.sunlong.jz.common.JzResponse;
import com.sunlong.jz.service.IJzLoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;

/**
 *  
 *
 * @author SL 
 * @description: 登录
 * @date 2021/11/11 15:46 
 **/
@RestController
@RequestMapping("/login")
public class JZLoginController {

    @Autowired
    private IJzLoginService loginService;

    /**
     * 登录验证 login
     *
     * @return LoginInfo 用户信息类(包含用户的ID,账号和密码和生成token字符串信息)
     */
    @PostMapping
    public JzResponse login(String json, HttpServletResponse response) {
        JSONObject jsonObject = JSONObject.parseObject(json);
        return loginService.login(jsonObject,response);
    }


}

此时如果直接运行,json的值只会是null,因为spring无法识别这个参数,此时就要使用aop自己去实现注入,我们先准备好前端入参:

{
    "username": "admin",
    "password": "123456"
}//注意设置请求头Content-Type:application/json

然后到了重点,编写切面类:

package com.sunlong.jz.config;

import com.alibaba.fastjson.JSONObject;
import com.sunlong.jz.common.JzResponse;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * @author SL
 * @desc 创建AOP 用于实现自定义controller参数填充
 * @Slf4j 必须结合lombok一起使用,否则无效
 */
@Slf4j
@Aspect
@Component
public class CommonAop {    // 用于记录每个controller执行的耗时时间,毫秒级    private ThreadLocal<Long> timeLocal = new ThreadLocal<>();

    /**
     * 定义切入点,切入点为com.example.aop下的所有函数
     */
    @Pointcut("execution(public * com.sunlong.jz.controller.*.*(..))")
    public void point() {
    }

    /**
     * @param joinPoint
     * @throws Throwable
     * @desc 前置通知:在连接点之前执行的通知
     */
    @Around("point()")
    public Object doBefore(ProceedingJoinPoint joinPoint) throws Throwable {
        // 接收到请求,记录请求内容       
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 记录下请求内容       
        try {
            BufferedReader streamReader = new BufferedReader(new InputStreamReader(request.getInputStream(), "UTF-8"));
            StringBuilder responseStrBuilder = new StringBuilder();
            int input;
            boolean flag = false;
            while ((input = streamReader.read()) != -1) {
                char c = (char) input;
                if (c == '{'){
                    flag = true;
                }
                if (flag) {
                    responseStrBuilder.append(c);
                }
                if (c == '}'){
                    flag = false;
                }
            }
            JSONObject jsonObject = JSONObject.parseObject(responseStrBuilder.toString());
            Object[] args = joinPoint.getArgs();
            for (int i = 0; i < args.length; i++) {
                if (args[i] == null && jsonObject != null) {
                    args[i] = jsonObject.toJSONString();
                    break;
                }
            }
            //执行
            return joinPoint.proceed(args);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return JzResponse.error("执行出错!");
    }
}

这里要把切入点设定为controller下的所有接口方法,然后使用@Before注解标明是在controller方法运行前执行doBefore方法,至于方法的内容就比较直接了,直接获取request变量中的内容,然后提取json变量的部分,赋值给json参数就可以了。

注意我这里因为很明确json变量肯定是null所以才直接判断是null的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值