Spring控制器:如何在@RequestMapping中使用属性${..}?

Spring controller: How to use property ${..} in @RequestMapping?

我已经找到了有答案的问题,但它们对我没有帮助。

我有一个 web servlet 项目,我在其中使用 Spring 控制器 (4.2.5) 和 Spring 安全 (4.0.2)。我不使用 Spring Boot.

我的项目运行良好。

但现在我的任务是:
使 @RequestMapping(value={"auth/**"} 可配置(将 "auth/**" 替换为 ${dm.filterPattern}

问题:在 @RequestMapping ${dm.filterPattern} 中未解决,尽管 @PropertySource 已处理。

这是 dmConfig.properties 中的条目 dm.filterPattern:

dm.filterPattern=/auth/*

这是一些基本代码,带有所有 Spring 注释。

控制器:

方法 init() 的输出显示 @PropertySource 已正确处理。 env.getProperty("...") returns 正确的值。

@Controller
@PropertySource("classpath:/dmConfig.properties")
@RequestMapping(value ={ "${dm.filterPattern}"})
public class DmProxyController implements ApplicationContextAware
{
    private Environment env;

    @Autowired
    public DmProxyController(Environment env)
    {
        this.env = env;
    }

    @RequestMapping(path={"${dm.filterPattern}"} ,method = RequestMethod.POST)
    protected void doPost(HttpServletRequest customerRequest, HttpServletResponse response)
            throws ServletException, IOException, DmException
    {
           // code for POST request
    }

    @RequestMapping(path={"${dm.filterPattern}"} ,method = RequestMethod.GET)
    protected void doGet(HttpServletRequest customerRequest, HttpServletResponse response)
            throws ServletException, IOException, DmException
    {
           // code for GET request
    }

    @PostConstruct
    public void init() throws ServletException
    {
        RequestMappingHandlerMapping requestMapping=
                (RequestMappingHandlerMapping) appContext.getBean("requestMappingHandlerMapping");

        Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMapping.getHandlerMethods();
        logger.debug("RequestMapping via dm.filterPattern: {}",
                env.getProperty("dm.filterPattern"));
                logger.debug("Handler Methods: {}", handlerMethods.size());

        for (RequestMappingInfo mapInfo : handlerMethods.keySet())
        {
            logger.debug(" Mappinginfo: {} --> {}", mapInfo, handlerMethods.get(mapInfo));
        }
    }
}

Class 带有 bean 定义

@Configuration
@PropertySource("classpath:/dmConfig.properties")
@ComponentScan(basePackages = "com.dm.filter, com.dm.controller")
@EnableTransactionManagement(mode = AdviceMode.PROXY, proxyTargetClass = false)
@Import({DmSecurityConfigurer.class, DmWebConfigurer.class})
public class DmRoot
{

}

DispatcherServletInitializer

public class DmDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
{
    @Override
    protected Class<?>[] getRootConfigClasses()
    { return new Class[]{DmRoot.class};  }

    @Override
    protected Class<?>[] getServletConfigClasses()
    { return null; }

    @Override
    protected String[] getServletMappings()
    { return new String[]{"/"}; }

    @Override
    protected String getServletName()
    {  return "dmDispatcherServlet";  }

    @Override
    protected void customizeRegistration(ServletRegistration.Dynamic registration)
    {
        super.customizeRegistration(registration);
        registration.setLoadOnStartup(1);
    }
}

WebConfigurer

public class DmWebConfigurer extends WebMvcConfigurerAdapter
{
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry)
    {
        super.addResourceHandlers(registry);
        registry.addResourceHandler("/index.html").addResourceLocations("/");
        registry.setOrder(Integer.MAX_VALUE-5);
    }
}

SecurityWebApplicationInitializer

public class DmSecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer
{
    public DmSecurityWebApplicationInitializer()
    {
        // some logging
    }

    @Override
    protected void beforeSpringSecurityFilterChain(ServletContext servletContext)
    {     // adding own filters   }

    @Override
    protected void afterSpringSecurityFilterChain(ServletContext servletContext)
    {     // adding own filters   }
}

安全配置器

@EnableWebMvc
@EnableWebSecurity
@PropertySource("classpath:dmConfig.properties")
public class DmSecurityConfigurer extends WebSecurityConfigurerAdapter
{

    private static Logger logger = LogManager.getLogger(DmSecurityConfigurer.class.getName());

    @Autowired
    private Environment env;

    @Autowired
    private UserDetailsService dmUserDetailsService;

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception
    {
        String urlPattern = env.getProperty("dm.springSecurityPattern");
        String realmName = env.getProperty("dm.springSecurityRealm");

        httpSecurity.httpBasic().realmName(realmName)
                .and().userDetailsService(dmUserDetailsService)
                .authorizeRequests()
                .antMatchers(urlPattern).authenticated()
                .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .csrf().disable();
    }

}

有可能 PropertySourcesPlaceholderConfigurer 在 spring 上下文中比您的控制器更晚被初始化,因此值未被解析。尝试在根配置文件之一中为 PropertySourcesPlaceholderConfigurer 添加显式 bean 定义,如下所示;

@PropertySource("classpath:/dmConfig.properties")
public class DmWebConfigurer extends WebMvcConfigurerAdapter
{
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry)
    {
        super.addResourceHandlers(registry);
        registry.addResourceHandler("/index.html").addResourceLocations("/");
        registry.setOrder(Integer.MAX_VALUE-5);
    }

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

您可以在 init() 方法中正确看到值的原因是因为它是在所有 bean 初始化之后调用的,包括 PropertySourcesPlaceholderConfigurer.