1.功能背景
我们在项目中有些经常会重复使用的参数,如用户信息相关USER_ID。此时并不希望每次都让前端传输重复的参数给我们,一方面减少重复代码的工作量,另一方面可以有效的保护用户隐私信息,这个时候可以在后台将其处理放入过滤器中,实现获得相关的参数的值。
2.示例代码
①包结构
代码语言:javascript复制├─.idea
│ ├─codeStyles
│ ├─dictionaries
│ ├─inspectionProfiles
│ └─libraries
├─.mvn
│ └─wrapper
├─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │ └─example
│ │ │ └─demo
│ │ │ ├─config
│ │ │ ├─context
│ │ │ ├─controller
│ │ │ ├─entity
│ │ │ └─service
│ │ └─resources
│ └─test
│ └─java
│ └─com
│ └─example
│ └─demo
└─target
├─classes
│ └─com
│ └─example
│ └─demo
│ ├─config
│ ├─context
│ ├─controller
│ ├─entity
│ └─service
├─generated-sources
│ └─annotations
├─generated-test-sources
│ └─test-annotations
└─test-classes
└─com
└─example
└─demo
②POM依赖
代码语言:javascript复制<?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 https://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.3.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- ################## Lombok ################## -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version><!--$NO-MVN-MAN-VER$ -->
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
③相关类
User:
代码语言:javascript复制/**
* 用户信息
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
private String name;
private int age;
public User(Long id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
/**
* 创建时间
*/
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT 8")
private Date createTime;
}
UserService:
代码语言:javascript复制/**
* 此处可以改为数据层
* 为方便展示 暂时只做简单模拟
*/
@Service("userService")
public class UserService {
public User getUserById(Long id) {
if (id.equals(1L)) {
return new User(1L, "张三", 18);
}
return null;
}
}
TestController:
代码语言:javascript复制@Slf4j
@RestController
@RequestMapping
public class TestController {
@RequestMapping("/")
public String test(Long user_id, String user_name, Integer user_age) {
String params = "user_id->" user_id " user_name->" user_name " user_age->" user_age;
return params;
}
}
BaseApplicationContext:
代码语言:javascript复制/**
* 通过上下文获取相关类
*/
@Configuration
public class BaseApplicationContext implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
applicationContext = context;
}
/**
* 获取applicationContext对象
*
* @return applicationContext对象
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 根据bean的id来查找对象
*
* @param id beanId
* @return 根据id查找到的对象
*/
public static <T> T getBeanById(String id) {
return (T) applicationContext.getBean(id);
}
/**
* 根据bean的id来查找对象
*
* @param id beanId
* @param clazz 类型
* @return 根据id查找到的对象
*/
public static <T> T getBeanById(String id, Class<T> clazz) {
return applicationContext.getBean(id, clazz);
}
/**
* 根据bean的class来查找对象
*
* @param c class
* @return bean的class查找到的对象
*/
public static <T> T getBeanByClass(Class<T> c) {
return (T) applicationContext.getBean(c);
}
/**
* 根据bean的class来查找所有的对象(包括子类)
*
* @param c
* @return
*/
public static Map getBeansByClass(Class c) {
return applicationContext.getBeansOfType(c);
}
public static String getMessage(String key) {
return applicationContext.getMessage(key, null, Locale.getDefault());
}
}
RequestWrapper:
代码语言:javascript复制/**
* HttpServletRequest的包装类
*/
public class RequestWrapper extends HttpServletRequestWrapper {
private Map<String, String[]> userInfoMap = new HashMap<String, String[]>();
/**
* 特殊的参数名称列表
*/
private static final Set<String> SPECIAL_NAME = new HashSet<String>();
/**
* 当前操作的用户
*/
public static final String user_id = "user_id".toLowerCase();
public static final String user_name = "user_name".toLowerCase();
public static final String user_age = "user_age".toLowerCase();
static {
SPECIAL_NAME.add(user_id.toLowerCase());
SPECIAL_NAME.add(user_name.toLowerCase());
SPECIAL_NAME.add(user_age.toLowerCase());
}
private final HttpServletResponse response;
public RequestWrapper(HttpServletRequest request, HttpServletResponse response) {
super(request);
this.response = response;
UserService userService = BaseApplicationContext.getBeanById("userService", UserService.class);
User user = userService.getUserById(1L);
userInfoMap.put(user_id, this.toArray(user.getId().toString()));
userInfoMap.put(user_name, this.toArray(user.getName()));
userInfoMap.put(user_age, this.toArray(String.valueOf(user.getAge())));
}
@Override
public String getParameter(String name) {
String[] values = this.getParameterValues(name);
if (values == null) {
return null;
} else {
return values[0];
}
}
@Override
public String[] getParameterValues(String name) {// NOPMD
String lowerCaseName = StringUtils.lowerCase(name);
if (SPECIAL_NAME.contains(lowerCaseName)) {
return userInfoMap.get(lowerCaseName);
} else {
return super.getParameterValues(name);
}
}
private String[] toArray(String content) {
if (content == null) {
return null;
} else {
return new String[]{content};
}
}
}
UserInfoRequestWrapperFilter:
代码语言:javascript复制/**
* 请求的相关Filter
*/
@Slf4j
public class UserInfoRequestWrapperFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
RequestWrapper httpRequestWraper = new RequestWrapper(request, response);
chain.doFilter(httpRequestWraper, res);
}
@Override
public void destroy() {
log.info(" UserInfoRequestWrapperFilter destory ");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info(" init UserInfoRequestWrapperFilter ");
}
}
FilterConfiguration:
代码语言:javascript复制/**
* 把Filter注册到SpringBoot中
*/
@Configuration
public class FilterConfiguration {
@Bean
public FilterRegistrationBean<UserInfoRequestWrapperFilter> grantFilterFilter(){
FilterRegistrationBean<UserInfoRequestWrapperFilter> filterRegistrationBean = new FilterRegistrationBean<>();
UserInfoRequestWrapperFilter userInfoRequestWrapperFilter = new UserInfoRequestWrapperFilter();
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico");
filterRegistrationBean.setFilter(userInfoRequestWrapperFilter);
filterRegistrationBean.setOrder(2);
filterRegistrationBean.setEnabled(true);
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.setName("userInfoRequestWrapperFilter");
return filterRegistrationBean;
}
}
④测试结果
代码语言:javascript复制user_id->1 user_name->张三 user_age->18