Spring boot的web mvc项目中,经常会使用自定义拦截器进行权限的验证,安全验证等步骤。自定义拦截器往往会引用外部properties配置。比如:为了防范CSRF攻击,需要拦截每一个请求,并判断request header中Referer属性是不是来自合法的服务器地址。而服务器地址url为了方便管理和维护,在*.properties文件中配置。
本文基于Spring boot构建web项目,定义拦截器时,发现无法引用properties中的配置。
初始代码如下:
ApplicationConfig类–用于加载properties文件
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource(value = "file:E:/***/system.properties")//properties文件路径
public class ApplicationConfig {
}
WebConfig类–定义srpring mvc运行时的配置
import com.*.LoginInterceptor;//自定义拦截器类
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages="com.*.controller,com.*.startup,com.*.config")
@Import(ApplicationConfig.class)
public class WebConfig extends WebMvcConfigurerAdapter {
/**
* 用户登录拦截器配置
* @param registry
*/
@Override
public void addInterceptors(final InterceptorRegistry registry) {
//实例化自定义拦截器,并指定需要拦截和不进行拦截的url请求
registry.addInterceptor(new LoginInterceptor).addPathPatterns("/**")
.excludePathPatterns("/***/***", "/**/*"");
super.addInterceptors(registry);
}
}
自定义拦截器LoginInterceptor类,继承HandlerInterceptorAdapter类
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Import(ApplicationConfig.class)
public class LoginInterceptor extends HandlerInterceptorAdapter {
@Value{"$server.host"}
private String host;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
...do something
if (...) {
...
return false;
}
return true;
}
}
发现LoginInteceptor类host的值为null,并没有加载外部properties配置。
究其原因在于WebConfig类中初始化拦截器时使用new LoginInterceptor()的方式实例化自定拦截器对象,并没有将该对象交给Spring容器。故不能通过Spring容器提供的@Import和@Value方式对该对象的属性赋值。
更改WebConfig类和LogingInterceptor拦截器类如下:
通过@Bean的方式实例化自定义拦截器,并通过有参构造方法对属性赋值。
修改WebConfig类代码为:
@Configuration
@EnableWebMvc
@ComponentScan(basePackages="...")
@Import(ApplicationConfig.class)//在这里引入外部配置文件
public class WebConfig extends WebMvcConfigurerAdapter {
@Value("${server.host:localhost:8080/asd...}")//定义默认值
private String host;
//实例化LoginInterceptor对象,并将其交给Spring容器
@Bean
public LoginInterceptor getLoginInterceptor(){
return new LoginInterceptor(host);//有参构造方法进行属性赋值
}
/**
* 用户登录拦截器配置
* @param registry
*/
@Override
public void addInterceptors(final InterceptorRegistry registry) {
//初始化拦截器类并制定拦截和不拦截的url地址 registry.addInterceptor(getLoginInterceptor()).addPathPatterns("...").excludePathPatterns("...");
super.addInterceptors(registry);
}
}
LoginInterceptor类加入有参构造方法:
public LoginInterceptor(String serverHost) {
this.serverHost=serverHost;
}
private String serverHost;
参考(reference):
https://stackoverflow.com/questions/23349180/java-config-for-spring-interceptor-where-interceptor-is-using-autowired-spring-b