Spring MVC - Spring有时使用RequestMappingHandlerMapping,有时使用SimpleUrlHandlerMapping

时间:2015-02-19 16:12:23

标签: java spring spring-mvc spring-java-config

过去两天我一直试图解决这个问题,到目前为止没有找到答案。关于这一点,我对很多谷歌进行了研究;)

所以问题是我正在尝试使用Hibernate开发Spring MVC应用程序并将其部署在Tomcat 8本地服务器上。问题是在10次运行中我有大约6次404 Not Found页面和4次我的应用程序我工作正常并显示我想要的。我进行了一些挖掘,并在Debug日志中发现,当请求映射失败时,Spring使用SimpleUrlHandlerMapping(我没有配置),当app工作正常时,Spring使用RequestMappingHandlerMapping(我配置了)。

然后是一点代码;)

WebConfig.java

package pkw.config;

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = {"pkw"})
@Import({AppConfig.class, SecurityConfig.class})
public class WebConfig extends WebMvcConfigurerAdapter{


    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("classpath:bootstrap/");
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping(){
        return new RequestMappingHandlerMapping();
    }

    @Bean
    public UrlBasedViewResolver viewResolver() {
        UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();
        viewResolver.setViewClass(TilesView.class);
        return viewResolver;
    }

    @Bean
    public TilesConfigurer tilesConfigurer(){
        TilesConfigurer result = new TilesConfigurer();
        result.setDefinitions("/WEB-INF/layouts/layout.xml");
        return result;
    }

}

SpringMvcInitilizer.java

package pkw.config.core;

public class SpringMvcInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {

        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(WebConfig.class);

        servletContext.addListener(new ContextLoaderListener(ctx));
        servletContext.addListener(new RequestContextListener());

        ctx.setServletContext(servletContext);

        Dynamic servlet = servletContext.addServlet("Enter", new DispatcherServlet(ctx));
        servlet.addMapping("/");
        servlet.setLoadOnStartup(1);

    }

}

EnterController.java

package pkw.controllers;

@Controller
public class EnterController {

    private static final Logger logger = LogManager.getLogger(EnterController.class);

    @Autowired
    IUserDAO userDAO;

    @Autowired
    IUserRoleDAO userRoleDAO;

    @Autowired
    DatabaseFinder finder;

    @Autowired
    PasswordEncoder passwordEncoder;

    @RequestMapping(value = {"/", "/main"}, method = {RequestMethod.GET, RequestMethod.HEAD})
    public String enterMain(Model model) {

        return "main";
    }


    @RequestMapping(value = "/login", method = {RequestMethod.GET, RequestMethod.HEAD})
    private String login(@RequestParam(value = "error", required = false) String error, @RequestParam(value = "logout",
            required = false) String logout, @RequestParam(value = "denied", required = false) String denied, @RequestParam(value = "success", required = false) String success,
                         Model model) {

        if (error != null) {
            model.addAttribute("error", "1");
        }

        if (logout != null) {
            model.addAttribute("logout", "1");
        }

        if (denied != null) {
            model.addAttribute("denied", "1");
        }

        if (success != null) {
            Authentication auth = SecurityContextHolder.getContext().getAuthentication();

            userBean.setLoggedUser(userDAO.findByPesel(auth.getName()));
            model.addAttribute("success", "1");
        }


        return "main";

    }
}

从错误运行调试日志

16:31:44.433 [http-apr-8080-exec-8] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/'; against '/resources/**'
16:31:44.434 [http-apr-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy - / at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
16:31:44.434 [http-apr-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy - / at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
16:31:44.434 [http-apr-8080-exec-8] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No HttpSession currently exists
16:31:44.434 [http-apr-8080-exec-8] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: null. A new one will be created.
16:31:44.434 [http-apr-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy - / at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
16:31:44.434 [http-apr-8080-exec-8] DEBUG o.s.s.w.h.writers.HstsHeaderWriter - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@3b904681
16:31:44.434 [http-apr-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy - / at position 4 of 12 in additional filter chain; firing Filter: 'CsrfFilter'
16:31:44.434 [http-apr-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy - / at position 5 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
16:31:44.434 [http-apr-8080-exec-8] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'HEAD /' doesn't match 'POST /logout
16:31:44.434 [http-apr-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy - / at position 6 of 12 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
16:31:44.434 [http-apr-8080-exec-8] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'HEAD /' doesn't match 'POST /login
16:31:44.434 [http-apr-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy - / at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
16:31:44.434 [http-apr-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy - / at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
16:31:44.434 [http-apr-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy - / at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
16:31:44.434 [http-apr-8080-exec-8] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055e4a6: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
16:31:44.435 [http-apr-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy - / at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
16:31:44.435 [http-apr-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy - / at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
16:31:44.435 [http-apr-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy - / at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
16:31:44.435 [http-apr-8080-exec-8] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/'; against '/admin/*'
16:31:44.435 [http-apr-8080-exec-8] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Public object - authentication not attempted
16:31:44.435 [http-apr-8080-exec-8] DEBUG o.s.security.web.FilterChainProxy - / reached end of additional filter chain; proceeding with original chain
16:31:44.435 [http-apr-8080-exec-8] DEBUG o.s.web.servlet.DispatcherServlet - DispatcherServlet with name 'Enter' processing HEAD request for [/]
16:31:44.435 [http-apr-8080-exec-8] DEBUG o.s.w.s.h.SimpleUrlHandlerMapping - Matching patterns for request [/] are [/**]
16:31:44.435 [http-apr-8080-exec-8] DEBUG o.s.w.s.h.SimpleUrlHandlerMapping - URI Template variables for request [/] are {}
16:31:44.435 [http-apr-8080-exec-8] DEBUG o.s.w.s.h.SimpleUrlHandlerMapping - Mapping [/] to HandlerExecutionChain with handler [org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler@1b8fe99] and 1 interceptor
16:31:44.435 [http-apr-8080-exec-8] DEBUG o.s.web.servlet.DispatcherServlet - Last-Modified value for [/] is: -1
16:31:44.436 [http-apr-8080-exec-8] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
16:31:44.436 [http-apr-8080-exec-8] DEBUG o.s.web.servlet.DispatcherServlet - Null ModelAndView returned to DispatcherServlet with name 'Enter': assuming HandlerAdapter completed request handling
16:31:44.436 [http-apr-8080-exec-8] DEBUG o.s.web.servlet.DispatcherServlet - Successfully completed request
16:31:44.436 [http-apr-8080-exec-8] DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally
16:31:44.436 [http-apr-8080-exec-8] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed

从良好运行调试日志

16:35:26.914 [http-apr-8080-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/'; against '/resources/**'
16:35:26.917 [http-apr-8080-exec-2] DEBUG o.s.security.web.FilterChainProxy - / at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
16:35:26.926 [http-apr-8080-exec-2] DEBUG o.s.security.web.FilterChainProxy - / at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
16:35:26.927 [http-apr-8080-exec-2] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No HttpSession currently exists
16:35:26.928 [http-apr-8080-exec-2] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: null. A new one will be created.
16:35:26.932 [http-apr-8080-exec-2] DEBUG o.s.security.web.FilterChainProxy - / at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter'
16:35:26.932 [http-apr-8080-exec-2] DEBUG o.s.s.w.h.writers.HstsHeaderWriter - Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@1e30dd63
16:35:26.932 [http-apr-8080-exec-2] DEBUG o.s.security.web.FilterChainProxy - / at position 4 of 12 in additional filter chain; firing Filter: 'CsrfFilter'
16:35:26.935 [http-apr-8080-exec-2] DEBUG o.s.security.web.FilterChainProxy - / at position 5 of 12 in additional filter chain; firing Filter: 'LogoutFilter'
16:35:26.936 [http-apr-8080-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'HEAD /' doesn't match 'POST /logout
16:35:26.936 [http-apr-8080-exec-2] DEBUG o.s.security.web.FilterChainProxy - / at position 6 of 12 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
16:35:26.936 [http-apr-8080-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'HEAD /' doesn't match 'POST /login
16:35:26.936 [http-apr-8080-exec-2] DEBUG o.s.security.web.FilterChainProxy - / at position 7 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
16:35:26.936 [http-apr-8080-exec-2] DEBUG o.s.security.web.FilterChainProxy - / at position 8 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
16:35:26.938 [http-apr-8080-exec-2] DEBUG o.s.security.web.FilterChainProxy - / at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
16:35:26.940 [http-apr-8080-exec-2] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055e4a6: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
16:35:26.941 [http-apr-8080-exec-2] DEBUG o.s.security.web.FilterChainProxy - / at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
16:35:26.941 [http-apr-8080-exec-2] DEBUG o.s.security.web.FilterChainProxy - / at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
16:35:26.941 [http-apr-8080-exec-2] DEBUG o.s.security.web.FilterChainProxy - / at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
16:35:26.942 [http-apr-8080-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/'; against '/admin/*'
16:35:26.942 [http-apr-8080-exec-2] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Public object - authentication not attempted
16:35:26.943 [http-apr-8080-exec-2] DEBUG o.s.security.web.FilterChainProxy - / reached end of additional filter chain; proceeding with original chain
16:35:26.947 [http-apr-8080-exec-2] DEBUG o.s.web.servlet.DispatcherServlet - DispatcherServlet with name 'Enter' processing HEAD request for [/]
16:35:26.952 [http-apr-8080-exec-2] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Looking up handler method for path /
16:35:26.956 [http-apr-8080-exec-2] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Returning handler method [public java.lang.String pkw.controllers.EnterController.enterMain(org.springframework.ui.Model)]
16:35:26.956 [http-apr-8080-exec-2] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'enterController'
16:35:26.956 [http-apr-8080-exec-2] DEBUG o.s.web.servlet.DispatcherServlet - Last-Modified value for [/] is: -1

and more but not concerning the problem anymore (at least I think so... ^^) 

所以问题是为什么Spring有时会使用一个映射处理程序,有时甚至使用另一个映射处理程序,即使我配置了它想要使用哪一个?

这很奇怪,因为我得到两个不同的结果,一个工作,一个不是完全相同的代码O.o

P.S我检查了所有路径以解决有关错误部署的问题,Intellij在重启时没有正确清理Tomcat等等。我也试过调整Tomcat内存。没有什么能给我解决方案:/

根据iamiddy建议编辑Tiles配置

layout.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
        "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">

<tiles-definitions>
    <definition name="DefaultTemplate" template="/WEB-INF/pages/template/SiteTemplate.jsp">
        <put-attribute name="title" value="Home"/>
        <put-attribute name="header" value="/WEB-INF/pages/header.jsp"/>
        <put-attribute name="navbar" value="/WEB-INF/pages/navbar.jsp"/>
        <put-attribute name="body" value=""/>
        <put-attribute name="footer" value="/WEB-INF/pages/footer.jsp"/>
    </definition>

    <definition name="main" extends="DefaultTemplate">
        <put-attribute name="body" value="/WEB-INF/pages/main.jsp"/>
    </definition>
    <definition name="addUser" extends="DefaultTemplate">
        <put-attribute name="body" value="/WEB-INF/pages/addUser.jsp" />
    </definition>
    <definition name="users" extends="DefaultTemplate">
        <put-attribute name="body" value="/WEB-INF/pages/users.jsp" />
    </definition>
</tiles-definitions>

TilesConfigurer和ViewResolver位于WebConfig.java

2 个答案:

答案 0 :(得分:0)

确保您始终在"/WEB-INF/layouts/layout.xml"

中按照配置返回切片定义而不是jsp页面

如果您已经这样做,请分享磁贴定义和url&amp;的资源文件。瓷砖类。

答案 1 :(得分:0)

尝试显式添加以下requestHandlerMapping bean(如果是

  <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>