java - Spring 3.2 - 切换到 JavaConfig 后无法解析 View 名称

标签 java spring spring-mvc controller dispatcher

我刚刚使用 Spring MVC 3.2.3 和 Spring Security 3.2.1 将所有 xml 配置文件转换为 JavaConfig。我遇到了一些问题,其中成员用 @ElementCollection(fetch=FetchType.EAGER) 注释的实体仍然没有被提取(我的 XML 配置没有这个问题),我必须添加 @Fetch(FetchMode) .JOIN)注释。但是,我在从 Controller 检索数据时仍然遇到问题。

我的许多请求都由后端完全处理,但是当它们从我的 Controller 方法返回时,我收到错误“HTTP 状态 500 - 无法解析名称为 ' 的 servlet 中名称为 'xxx' 的 View 调度员”。问题是,我只有 3 个 View :登录、索引和管理。索引页是一个单页站点,它对 Controller 进行大量 AJAX 调用,其中大多数使用 @RequestBody 将 JSON 请求解码到 DTO,所有这些都直接使用 @ResponseBody 写入响应,并使用 Jackson 转换为 JSON。这在过去一直有效—— Controller 方法实际上应该只是 REST 端点,但现在,调度程序 servlet 希望将 View 与我的几乎所有请求(但不是全部)关联起来。我不确定如何告诉 View 解析器或调度程序 servlet 仅将索引、管理和登录视为 View ,而将其他所有内容视为简单的 REST 请求。任何帮助,将不胜感激!这是我的配置:

根配置:

@Configuration
@ComponentScan(value = "x.configuration", excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, value = RootConfig.class))
public class RootConfig {}

安全初始化器:

public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {}

Web 应用程序初始化器:

public class WebAppInitializer extends
        AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{RootConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{
            "/rest/*",
            "/index.html",
            "/login.html",
            "/admin.html",
            "/index/*",
            "/login/*",
            "/admin/*"
        };
    }

    @Override
    protected Filter[] getServletFilters() {
        OpenEntityManagerInViewFilter openEntityManagerInViewFilter = new OpenEntityManagerInViewFilter();
        openEntityManagerInViewFilter.setBeanName("openEntityManagerInViewFilter");       
        openEntityManagerInViewFilter.setPersistenceUnitName("HSQL");
        return new javax.servlet.Filter[]{openEntityManagerInViewFilter};
    }
}

Spring MVC 配置:

@Configuration
@EnableWebMvc
@EnableTransactionManagement
{@ComponentScan.Filter(type= FilterType.ANNOTATION, value=Controller.class)})
@ComponentScan(basePackages = "x.clients")
public class SpringMvcConfig extends WebMvcConfigurerAdapter {

    @Bean
    public InternalResourceViewResolver setupViewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/jsp/");
        viewResolver.setSuffix(".jsp");
        viewResolver.setViewNames(new String[] {"login", "index", "admin"});
        return viewResolver;
    }

    @Bean
    public DefaultAnnotationHandlerMapping getDefaultAnnotationHandlerMapping() {
        DefaultAnnotationHandlerMapping handlerMapping = new DefaultAnnotationHandlerMapping();
        handlerMapping.setAlwaysUseFullPath(true);
        handlerMapping.setDetectHandlersInAncestorContexts(true);
        return handlerMapping;
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(getMappingJacksonHttpMessageConverter());
        super.configureMessageConverters(converters);
    }


    @Bean 
    public JacksonAnnotationIntrospector getJacksonAnnotationIntrospector(){
        return new JacksonAnnotationIntrospector();
    }

    @Bean
    public ObjectMapper getObjectMapper(){
        ObjectMapper mapper = new ObjectMapper();

        mapper.setAnnotationIntrospector(getJacksonAnnotationIntrospector());
        mapper.registerModule(new Hibernate4Module());
        return mapper;
    }

    @Bean MappingJackson2HttpMessageConverter getMappingJacksonHttpMessageConverter(){
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        messageConverter.setObjectMapper(getObjectMapper());

        return messageConverter;
    }

    @Bean
    public DefaultConversionService getDefaultConversionService(){
        return new DefaultConversionService();
    }
}

Spring 安全配置:

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomUserDetailsService userDetailsService;
    @Autowired
    private CustomAuthenticationProvider customAuthenticationProvider;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        AuthenticationProvider rememberMeAuthenticationProvider = getRememberMeAuthenticationProvider();
        TokenBasedRememberMeServices tokenBasedRememberMeServices = getTokenBasedRememberMeServices();

        List<AuthenticationProvider> authenticationProviders = new ArrayList<AuthenticationProvider>(2);
        authenticationProviders.add(rememberMeAuthenticationProvider);
        authenticationProviders.add(customAuthenticationProvider);
        AuthenticationManager authenticationManager = getAuthenticationManager(authenticationProviders);

        http
                .csrf().disable()
                .headers().disable()
                .addFilter(new RememberMeAuthenticationFilter(authenticationManager, tokenBasedRememberMeServices))
                .rememberMe().rememberMeServices(tokenBasedRememberMeServices)
                .and()
                .authorizeRequests()
                .antMatchers("/js/**", "/css/**", "/img/**", "/login", "/processLogin").permitAll()
                .antMatchers("/index.jsp", "/index.html", "/index").hasRole("USER")
                .antMatchers("/admin", "/admin.html", "/admin.jsp").hasRole("ADMIN")
                .and()
                .formLogin().loginProcessingUrl("/processLogin").loginPage("/login").failureUrl("/login").permitAll()
                .and()
                .logout().permitAll();
    }



    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/js/**", "/css/**", "/img/**");
    }

    @Bean
    public AuthenticationManager getAuthenticationManager(List<AuthenticationProvider> authenticationProviders) {
        return new ProviderManager(authenticationProviders);
    }

    @Bean
    public TokenBasedRememberMeServices getTokenBasedRememberMeServices() {
        return new TokenBasedRememberMeServices("testKey", userDetailsService);
    }

    @Bean
    public AuthenticationProvider getRememberMeAuthenticationProvider() {
        return new org.springframework.security.authentication.RememberMeAuthenticationProvider("testKey");
    }

    protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }
}

我的所有 Controller 方法都是通过 URL 模式/rest//访问的。

以下 Controller 仅返回枚举项的列表并且工作正常:

@Controller
@RequestMapping("/swterms")
public class SwTermsController {
    @RequestMapping(value = "/getSensorTypes", method = RequestMethod.GET)
    @ResponseBody
    public List<String> getSensorTypes() {
        List<String> sensorTypes = new ArrayList<String>();
        for (SensorTypes sensorType : SensorTypes.values()){
            sensorTypes.add(sensorType.getURI());
        }
        return sensorTypes;
    }
}

该 Controller 返回 map 图层列表。我可以在 Debug模式下单步执行,一切都构建得很好,但它会产生 500 错误:

@Controller
@RequestMapping("/map")
public class MapLayerController {

    @Autowired
    @Resource(name="mapLayers") private List<OpenLayersMapLayer> mapLayers;

    @RequestMapping(value = "/getLayerData", method = RequestMethod.GET)
    @ResponseBody
    public Map getMapLayers() {
        Map model = new HashMap();
        model.put("layers", this.mapLayers);
        return model;
    }   
}

以下是日志的相关部分:

 00:12:21,034 (http-bio-8084-exec-77) DEBUG [org.springframework.security.web.FilterChainProxy] - /rest/map/getLayerData at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
    00:12:21,034 (http-bio-8084-exec-77) DEBUG [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Checking match of request : '/rest/map/getlayerdata'; against '/logout'
    00:12:21,035 (http-bio-8084-exec-77) DEBUG [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Checking match of request : '/rest/map/getlayerdata'; against '/js/**'
    00:12:21,035 (http-bio-8084-exec-77) DEBUG [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Checking match of request : '/rest/map/getlayerdata'; against '/css/**'
    00:12:21,035 (http-bio-8084-exec-77) DEBUG [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Checking match of request : '/rest/map/getlayerdata'; against '/img/**'
    00:12:21,035 (http-bio-8084-exec-77) DEBUG [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Checking match of request : '/rest/map/getlayerdata'; against '/login'
    00:12:21,035 (http-bio-8084-exec-77) DEBUG [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Checking match of request : '/rest/map/getlayerdata'; against '/processlogin'
    00:12:21,035 (http-bio-8084-exec-77) DEBUG [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Checking match of request : '/rest/map/getlayerdata'; against '/index.jsp'
    00:12:21,035 (http-bio-8084-exec-77) DEBUG [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Checking match of request : '/rest/map/getlayerdata'; against '/index.html'
    00:12:21,035 (http-bio-8084-exec-77) DEBUG [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Checking match of request : '/rest/map/getlayerdata'; against '/index'
    00:12:21,035 (http-bio-8084-exec-77) DEBUG [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Checking match of request : '/rest/map/getlayerdata'; against '/admin'
    00:12:21,035 (http-bio-8084-exec-77) DEBUG [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Checking match of request : '/rest/map/getlayerdata'; against '/admin.html'
    00:12:21,035 (http-bio-8084-exec-77) DEBUG [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Checking match of request : '/rest/map/getlayerdata'; against '/admin.jsp'
    00:12:21,035 (http-bio-8084-exec-77) DEBUG [org.springframework.security.web.util.matcher.AntPathRequestMatcher] - Checking match of request : '/rest/map/getlayerdata'; against '/js/saic/jswe/admin/**'
    00:12:21,035 (http-bio-8084-exec-77) DEBUG [org.springframework.security.web.access.intercept.FilterSecurityInterceptor] - Public object - authentication not attempted
    00:12:21,035 (http-bio-8084-exec-77) DEBUG [org.springframework.security.web.FilterChainProxy] - /rest/map/getLayerData reached end of additional filter chain; proceeding with original chain
    00:12:21,041 (http-bio-8084-exec-77) DEBUG [org.springframework.web.servlet.DispatcherServlet] - DispatcherServlet with name 'dispatcher' processing GET request for [/swtc/rest/map/getLayerData]
    00:12:21,041 (http-bio-8084-exec-77) DEBUG [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] - Looking up handler method for path /map/getLayerData
    00:12:21,042 (http-bio-8084-exec-77) DEBUG [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping] - Returning handler method [public org.springframework.ui.ModelMap x.clients.controllers.MapLayerController.getMapLayers(org.springframework.ui.ModelMap)]
    00:12:21,042 (http-bio-8084-exec-77) DEBUG [org.springframework.beans.factory.support.DefaultListableBeanFactory] - Returning cached instance of singleton bean 'mapLayerController'
    00:12:21,042 (http-bio-8084-exec-77) DEBUG [org.springframework.web.servlet.DispatcherServlet] - Last-Modified value for [/swtc/rest/map/getLayerData] is: -1
    00:12:44,844 (http-bio-8084-exec-77) DEBUG [org.springframework.web.servlet.DispatcherServlet] - Could not complete request
    javax.servlet.ServletException: Could not resolve view with name 'map/getLayerData' in servlet with name 'dispatcher'
        at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1190)
        at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:992)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:939)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:180)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
        at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
        at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:146)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:146)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
        at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
        at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:722)
    00:12:44,902 (http-bio-8084-exec-77) DEBUG [org.springframework.security.web.context.SecurityContextPersistenceFilter] - SecurityContextHolder now cleared, as request processing completed

最佳答案

尝试删除此行:

viewResolver.setViewNames(new String[] {"login", "index", "admin"});

这导致 viewResolver 忽略 ["login","index","admin"] 中不存在的所有内容

摘自文档:

setViewNames

public void setViewNames(String[] viewNames) Set the view names (or name patterns) that can be handled by this ViewResolver. View names can contain simple wildcards such that 'my*', '*Report' and 'Repo' will all match the view name 'myReport'.

关于java - Spring 3.2 - 切换到 JavaConfig 后无法解析 View 名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22285234/

相关文章:

java - lucene 一元词和二元词的频率

java - ConstraintViolationException 不能同时适用于 DTO 和 MODEL 类

java - Spring 3 Web 请求拦截器——如何获取 BindingResult?

jquery - spring MVC 3 get请求从ie错误地返回代码304

java - 将 JInternalFrame 在 JDesktopPane 中居中无法正常工作

Java:如何从结果集选择查询中提取计数

java - Vsphere Web 客户端 sdk 无法加载属性文件

java - Spring 中的 Thread.setDefaultUncaughtExceptionHandler

javascript - 如何从前端向 Spring 发出 HTTP POST 请求?

java - 是否有用于 Spring/SpringMVC 的类似 Sprockets 的库/插件?