当前位置: 首页 > article >正文

后台管理系统的通用权限解决方案(十)如何自定义SpringMVC的参数解析器

文章目录

  • 1 参数解析器介绍
  • 2 参数解析器案例
    • 2.1 案例需求
    • 2.2 案例实战

1 参数解析器介绍

我们在开发中,可能会写以下Controller代码:

@RestController
@RequestMapping("/user")
public class UserController {

    @PostMapping("/save")
    // 此处request对象就是通过Springmvc提供的参数解析器帮我们注入的
    public String saveUser(HttpServletRequest request) {
        return "success";
    }
}

在上面的saveUser方法中,我们直接声明了一个类型为HttpServletRequest的参数,这个参数对象可以直接使用,那是因为这个参数对象就是通过Springmvc提供的ServletRequestMethodArgumentResolver参数解析器帮我们注入的。

同样,如果我们需要使用HttpServletResponse对象,也可以直接在方法上加入这个参数,此时Springmvc会通过ServletResponseMethodArgumentResolver这个参数解析器帮我们注入。

在项目开发中我们也可以根据需要自定义参数解析器,需要实现HandlerMethodArgumentResolver接口:

可以看到,此接口包含两个接口方法:supportsParameterresolveArgumentsupportsParameter方法返回true时,才会调用resolveArgument方法。

2 参数解析器案例

2.1 案例需求

在实际项目中,绝大部分操作都是基于“当前登录用户”进行的,业务逻辑中一般也需要获取“当前登录用户”的信息。

常用的做法是,在过滤器中解析token得到当前登录用户的信息,并将需要的信息放入request域,那在Controller方法中就可以通过HttpServletRequest对象获取到当前登录用户信息。

而通过参数解析器的做法,是和HttpServletRequest对象已有直接声明,让Springmvc帮我们自动注入,而无需再放入request域。

2.2 案例实战

  • 1)创建maven工程resolver-demo,并配置其pom.xml文件如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/>
    </parent>
    <groupId>com.hsgx</groupId>
    <artifactId>resolver-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>
  • 2)创建实体类LoginUser
package com.itweid.resolver.pojo;

import java.time.LocalDateTime;

@Data
@AllArgsConstructor
public class LoginUser {

    private Integer id;
    private String username;
    private LocalDateTime loginTime;
}
  • 3)创建UserController
package com.itweid.resolver.controller;

import com.itweid.resolver.pojo.LoginUser;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "/user")
public class UserController {

    // 获取当前登录用户信息
    @GetMapping("/getLoginUser")
    public String getLoginUser(LoginUser loginUser) {
        return loginUser.toString();
    }
}
  • 4)创建启动类
package com.itweid.resolver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ResolverApp {

    public static void main(String[] args) {
        SpringApplication.run(ResolverApp.class, args);
    }
}
  • 5)启动项目,访问http://127.0.0.1:8080/user/getLoginUser

由结果可知,虽然访问成功了,但返回的信息全为空,说明在Controller方法中,直接使用LoginUser对象暂时是无法注入的。

而为了能够自动注入LoginUser对象,我们可以通过Spring提供的参数解析器来实现。

  • 6)创建LoginUser注解,只有标注了该注解的参数才会自动注入
package com.itweid.resolver.annotation;

import java.lang.annotation.*;

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LoginUser {
}
  • 7)创建参数解析器类,实现HandlerMethodArgumentResolver接口
package com.itweid.resolver.resolver;

import com.itweid.resolver.pojo.LoginUser;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import java.time.LocalDateTime;

public class LoginUserMethodArgumentResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        // 如果Controller方法的参数类型为LoginUser,
        // 同时还加入了@LoginUser注解,则返回true
        if (parameter.getParameterType().equals(LoginUser.class) &&
                parameter.hasParameterAnnotation(com.itweid.resolver.annotation.LoginUser.class)) {
            return true;
        }
        return false;
    }

    // 当supportsParameter方法返回true时执行此方法
    @Override
    public Object resolveArgument(MethodParameter parameter,
                                  ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest,
                                  WebDataBinderFactory binderFactory) throws Exception {
        System.out.println("参数解析器执行了...");
        // 此处直接模拟了一个LoginUser对象,实际项目中可能需要从请求头中获取登录用户的令牌然后进行解析,
        // 最终封装成LoginUser对象返回即可,这样在Controller的方法形参就可以直接引用到LoginUser对象了
        LoginUser loginUser = new LoginUser(1,"admin", LocalDateTime.now());
        return loginUser;
    }
}
  • 8)创建配置类,用于注册自定义的参数解析器
package com.itweid.resolver.config;

import com.itweid.resolver.resolver.LoginUserMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
public class ArgumentResolverConfiguration implements WebMvcConfigurer {

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new LoginUserMethodArgumentResolver());
    }
}
  • 9)修改UserController类的getLoginUser()方法,在LoginUser参数前加入@LoginUser注解
// 获取当前登录用户信息
@GetMapping("/getLoginUser")
public String getLoginUser(@com.itweid.resolver.annotation.LoginUser LoginUser loginUser) {
    return loginUser.toString();
}
  • 10)重启项目,访问http://127.0.0.1:8080/user/getLoginUser

有结果可知,返回的LoginUser对象的属性已经有值了,这是因为在我们访问Controller的方法时,Spring框架会调用我们自定义的参数解析器的supportsParameter方法来判断是否执行resolveArgument方法。

如果Controller方法的参数类型为LoginUser并且加入了@LoginUser注解,则执行resolveArgument方法,此方法的返回结果将赋值给Controller方法中声明的LoginUser参数,即完成了参数绑定。

本节完,更多内容查阅:后台管理系统的通用权限解决方案

延伸阅读:后台管理系统的通用权限解决方案(九)后台管理系统的通用权限解决方案(九)SpringBoot整合jjwt实现登录认证鉴权


http://www.kler.cn/a/380628.html

相关文章:

  • 青少年编程能力等级测评CPA Python编程(一级)
  • docker 可用镜像服务地址(2024.10.31亲测可用)
  • 【Nginx】编译安装(Centos)
  • Lucene分析器的详细使用(5)
  • Java 实现接口幂等的九种方法:确保系统稳定性与数据一致性
  • 再探“构造函数”(2)友元and内部类
  • springboot+shiro 权限管理
  • 【前端基础】盒子模型
  • 华为HarmonyOS打造开放、合规的广告生态 - 开屏广告
  • 【双指针】【数之和】 LeetCode 633.平方数之和
  • CSS中的背景色和前景色
  • 软件测试面试题个人总结
  • 齐次线性微分方程的解的性质与结构
  • 《YOLO 目标检测》—— YOLO v4 详细介绍
  • el-talble selection行 初始默认勾选
  • TypeScript中的类型注解、Interface接口、泛型
  • 2025郑州国际台球及配套设施展会,台球盛宴,产业新篇
  • 制造业大模型应用案例赏析
  • 【论文速读】| PathSeeker:使用基于强化学习的越狱攻击方法探索大语言模型的安全漏洞
  • 高效作业跟踪:SpringBoot作业管理系统
  • leetcode203. Remove Linked List Elements
  • 【AI】【提高认知】深度学习与反向传播:理解AI的基础
  • mutable用法
  • FastAPI 目录结构推荐
  • 了解神经网络中的激活函数
  • 【VSCode / Source Insight 4】设置关键字高亮的插件 | Highlight Word