【问题标题】:SpringBoot 404 on ModelAndViewModelAndView 上的 Spring Boot 404
【发布时间】:2017-11-09 22:43:53
【问题描述】:

我有一个这样的控制器:

@RestController
public class SecureController {

    private static final Logger logger = LoggerFactory.getLogger(SecureController.class);

    @RequestMapping(value={"/secure"},
                    method=RequestMethod.GET)
    public ResponseEntity<?> getSecure() {
        String str = "Security Area? -- GET";

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (!(authentication instanceof AnonymousAuthenticationToken)) {
            String currentUserName = authentication.getName();
            str = str + " -- " + currentUserName + "\n\n";
        }

        return new ResponseEntity<>(str, HttpStatus.OK);
    }

    @RequestMapping(value={"/secure"},
                    method=RequestMethod.POST)
    public ResponseEntity<?> postSecure() {
        String str = "Security Area? -- POST";

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (!(authentication instanceof AnonymousAuthenticationToken)) {
            String currentUserName = authentication.getName();
            str = str + " -- " + currentUserName + "\n\n";
        }

        return new ResponseEntity<>(str, HttpStatus.OK);
    }

    @RequestMapping(value={"/secure/sub"},
                    method=RequestMethod.GET)
    public ResponseEntity<?> getSecureSub() {
        String str = "Security area subpage -- GET";

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (!(authentication instanceof AnonymousAuthenticationToken)) {
            String currentUserName = authentication.getName();
            str = str + " -- " + currentUserName + "\n\n";
        }

        return new ResponseEntity<>(str, HttpStatus.OK);
    }

    @RequestMapping(value={"/secure/list"}, method=RequestMethod.GET)
    public ModelAndView getSecureList() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("listpage.html");
        return modelAndView;
    }

    @RequestMapping(value={"/login"}, method=RequestMethod.GET)
    public ModelAndView getLogin(@RequestParam(value="logout", required=false) String logout,
                                 @RequestParam(value="error", required=false) String error) {

        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("loginpage.html");
        return modelAndView;
    }
}

有一个像这样的网络安全:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .csrf().disable()
        .authorizeRequests()
        .antMatchers("/secure/**").fullyAuthenticated()
        .antMatchers("/login").fullyAuthenticated()
        .antMatchers(HttpMethod.GET, "/login").permitAll()
        .and()
        .formLogin().loginPage("/login").failureUrl("/login?error").defaultSuccessUrl("/secure/list", true).permitAll()
        .and()
        .logout();
}

这似乎有效。

我正在测试一些安全性的东西......无论如何,当进入登录页面时,loginpage.html 呈现得很好。它发布到 /login 并且一切正常。

直到您尝试访问 /secure/list。然后是404s。该路由存在,并且 listpage.html 与 loginpage.html 存在于同一目录中,我知道它会找到它,因为如果我将名称更改为 list.html 它会给我一个关于循环路由的异常。

无论如何,/secure/sub 路由工作正常。因此,基于此看来,ModelAndView 没有问题,子路由也没有问题,但由于某种原因,当一起使用时,出现了问题。

为什么给我一个 404?

一些日志:

2017-11-09 17:52:49.865 DEBUG 9020 --- [nio-8088-exec-4] o.s.w.s.v.ContentNegotiatingViewResolver : Requested media types are [text/html, application/xhtml+xml, image/webp, application/xml;q=0.9, */*;q=0.8] based on Accept header types and producible media types [*/*])
2017-11-09 17:52:49.865 DEBUG 9020 --- [nio-8088-exec-4] o.s.w.servlet.view.BeanNameViewResolver  : No matching bean found for view name 'listpage.html'
2017-11-09 17:52:49.866 DEBUG 9020 --- [nio-8088-exec-4] o.s.w.servlet.view.BeanNameViewResolver  : No matching bean found for view name 'listpage.html.html'
2017-11-09 17:52:49.867 DEBUG 9020 --- [nio-8088-exec-4] o.s.w.s.v.ContentNegotiatingViewResolver : Returning [org.springframework.web.servlet.view.JstlView: name 'listpage.html'; URL [listpage.html]] based on requested media type 'text/html'
2017-11-09 17:52:49.868 DEBUG 9020 --- [nio-8088-exec-4] o.s.web.servlet.DispatcherServlet        : Rendering view [org.springframework.web.servlet.view.JstlView: name 'listpage.html'; URL [listpage.html]] in DispatcherServlet with name 'dispatcherServlet'
2017-11-09 17:52:49.868 DEBUG 9020 --- [nio-8088-exec-4] o.s.web.servlet.view.JstlView            : Forwarding to resource [listpage.html] in InternalResourceView 'listpage.html'
2017-11-09 17:52:49.869 DEBUG 9020 --- [nio-8088-exec-4] o.s.web.servlet.DispatcherServlet        : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/secure/listpage.html]
2017-11-09 17:52:49.870 DEBUG 9020 --- [nio-8088-exec-4] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /secure/listpage.html
2017-11-09 17:52:49.875 DEBUG 9020 --- [nio-8088-exec-4] s.w.s.m.m.a.RequestMappingHandlerMapping : Did not find handler method for [/secure/listpage.html]
2017-11-09 17:52:49.875 DEBUG 9020 --- [nio-8088-exec-4] o.s.w.s.handler.SimpleUrlHandlerMapping  : Matching patterns for request [/secure/listpage.html] are [/**]
2017-11-09 17:52:49.875 DEBUG 9020 --- [nio-8088-exec-4] o.s.w.s.handler.SimpleUrlHandlerMapping  : URI Template variables for request [/secure/listpage.html] are {}
2017-11-09 17:52:49.875 DEBUG 9020 --- [nio-8088-exec-4] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapping [/secure/listpage.html] to HandlerExecutionChain with handler [ResourceHttpRequestHandler [locations=[ServletContext resource [/], class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@7383eae2]]] and 1 interceptor
2017-11-09 17:52:49.876 DEBUG 9020 --- [nio-8088-exec-4] o.s.web.servlet.DispatcherServlet        : Last-Modified value for[/secure/listpage.html] is: -1
2017-11-09 17:52:49.878 DEBUG 9020 --- [nio-8088-exec-4] o.s.web.servlet.DispatcherServlet        : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
2017-11-09 17:52:49.878 DEBUG 9020 --- [nio-8088-exec-4] o.s.web.servlet.DispatcherServlet        : Successfully completed request


ls src/main/resources/static/
listpage.html  loginpage.html

【问题讨论】:

  • 能分享一下应用的目录结构吗?
  • 对我来说,您似乎需要将 listpage.html 放在不同的目录中。

标签: java spring spring-mvc spring-boot spring-security


【解决方案1】:

您将控制器定义为@RestController,这会在访问secure/list 页面时导致错误。我的建议是使用 @Controller 注释而不是 @RestController 创建另一个控制器。

@Controller
public class SecureListController {
    @RequestMapping(value={"/secure/list"}, method=RequestMethod.GET)
    public ModelAndView getSecureList() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("listpage.html");
        return modelAndView;
    }    
}

【讨论】:

  • 如果是这样,那么为什么 /login 路径可以与 ModelAndView 一起使用?
  • 哦,这似乎是因为 Spring 在 secure 目录上查找您的 listpage.html,但您的 listpage.html 位于 src/resources/static。然后尝试将您的listpage.html 移动到src/resources/static/secure
  • ...这个东西正在寻找与 uri 相关的资源,而不仅仅是“在类路径中”
  • 是的,我对 Spring 有一点经验,但是看到您的错误消息 Looking up handler method for path /secure/listpage.htmlDid not find handler method for [/secure/listpage.html] 是否意味着您需要将 listpage.html 放在 secure 目录下?
【解决方案2】:

对我来说,添加百里香依赖解决了它。

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

方法

@GetMapping("item")
public ModelAndView getItems() {
    return new ModelAndView("item");
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-24
    • 2018-05-26
    • 2021-11-04
    • 2018-09-25
    • 2017-12-05
    相关资源
    最近更新 更多