找不到带有spring boot的html页面

Posted

技术标签:

【中文标题】找不到带有spring boot的html页面【英文标题】:cannot find html pages with spring boot 【发布时间】:2016-06-15 11:26:29 【问题描述】:

我在前端使用弹簧靴和角度。有时我想直接从服务重定向。我们只使用 .html、.css 和脚本文件(没有 .jsp)。

这是return "static/pages/savepassword.html"; 我尝试重定向到保存密码的方式

那么第一个问题在这种情况下如何正确重定向?

接下来,Spring 找不到我的 html 文件。我有这个结构

我读到 spring 应该自动在“静态”中找到所有静态文件,但它没有。所以我尝试配置我的 ViewControllerRegistry 和 RessourceControllerRegistry

@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) 
        super.addResourceHandlers(registry);
        registry.addResourceHandler("/static/**").addResourceLocations("/static/");
//      registry.addResourceHandler("/stylesheets/**").addResourceLocations("/stylesheets/");
//      registry.addResourceHandler("/scripts/**").addResourceLocations("/scripts/");
//      registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
    

    @Override
    public void addViewControllers(ViewControllerRegistry registry) 
        super.addViewControllers(registry);
        registry.addViewController("/savePassword").setViewName("static/pages/savePassword.html");
        registry.addViewController("/login").setViewName("static/pages/login.html");
        registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
    

当我直接调用“static/pages/login.html”时,它可以工作。当我想调用“/login”时,它会显示 404。 第二个问题:我需要配置什么,哪些不需要?

UPDATE-1:Spring 安全性

http
            .authorizeRequests().antMatchers("/login", "/logout", "/user/**").permitAll()
            .anyRequest().authenticated()
        .and()
            .exceptionHandling()
            .accessDeniedHandler(new CustomAccessDeniedHandler())
            .authenticationEntryPoint(new CustomAuthenticationEntryPoint())
        .and()
            .requiresChannel()
            .anyRequest().requiresSecure()
        .and()
            .csrf()
            .disable()
            //.csrfTokenRepository(csrfTokenRepository())
            .addFilterBefore(new MDCFilter(), ExceptionTranslationFilter.class)
            // .addFilterBefore(new CorsFilter(),// ChannelProcessingFilter.class)
            //.addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class)
            .formLogin()
            .successHandler(new CustomSuccessAuthenticationHandler())
            .failureHandler(new CustomFailureHandler())
            .loginPage("/login").permitAll();

UPDATE-2 我更新了结构,但从 /login 重定向到自定义登录仍然存在问题。

UPDATE-3 我看了 Bob Shields 的第二条评论:https://spring.io/blog/2013/12/19/serving-static-web-content-with-spring-boot 我做了以下事情:

@Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) 
        super.addResourceHandlers(registry);
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
    

    @Override
    public void addViewControllers(ViewControllerRegistry registry) 
        super.addViewControllers(registry);
        registry.addViewController("/savepassword").setViewName("savepassword.html");
        registry.addViewController("/login").setViewName("login.html");
        registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
    

我设置 .html 因为否则 /login 会导致递归问题。有了这个配置,我可以输入 /login 和 /templates/login.html 将被调用(savepassword.html 相同)。

现在,我想知道如何在 html 中包含我的 css/js

<link rel="stylesheet" type="text/css" href="..resources/stylesheets/bootstrap.min.css" />
    <script src="..resources/scripts/angular.min.js"></script>
    <script src="..resources/scripts/login.js"></script>

这不起作用...但我不能直接使用 /scripts/login.js 调用我的脚本。

【问题讨论】:

你可以试试 /login.html 吗? 不,因为默认的 Spring Security 页面出现了。通常,我们的自定义 login.html (static/pages/login.html) 应该会显示出来。我更新了我的答案,所以你可以看到 spring 安全配置。我认为ViewControllerRegistry 将登录解析为 static/pages/login,html 并会使用此登录页面 我可能需要将静态文件夹放在 src/main/ressource 中而不是放在 webapp 中吗? 您可以尝试将一页直接放在 webapp 文件夹下并使用 /login.html 引用它吗? 我停用了spring security,但是直接将html文件放在“资源”中时无法访问。 【参考方案1】:

在我看来,最好将您的 *.HTML 文件与所有静态 CSS 字体等放在资源文件夹中,如下图所示。在 webapp 中,您只能拥有一个 WEB-INF 文件夹。

我正在使用这种结构,我可以毫无问题地找到任何类 css 或 htmls,并且我没有在 java 的末尾使用扩展名(“static/pages/login.html”就像你的那样)。如果我想访问 html,如果它在文件夹用户中,我会像“user/someHtml”一样。

我知道这个答案并不完全是您正在寻找的答案,但它可能会以某种方式帮助您。

编辑:现在是:

   @Override
   public void addViewControllers(ViewControllerRegistry registry) 
       super.addViewControllers(registry);
       registry.addViewController("/savePassword").setViewName("static/pages/savePassword.html");
       registry.addViewController("/login").setViewName("static/pages/login.html");
       registry.setOrder(Ordered.HIGHEST_PRECEDENCE);

假设你有一个控制器:

@Controller
@RequestMapping("/myController")
public class MyController
...


@RequestMapping(value = "/login")
public String login(Model model) 
     // Your code ....

    return "login"; //<- this is your login.html if it is directly in resource/templates folder

    @RequestMapping(value = "/savePassword")
public String savePassword(Model model) 
     // Your code ....

    return "savePassword"; //<- this is your savePassword.html if it is directly in resource/templates folder
 
.....

现在您的 addViewController 显示如下所示:

   @Override
      public void addViewControllers(ViewControllerRegistry registry) 
          super.addViewControllers(registry);
          registry.addViewController("/savePassword").setViewName("forward:/myController/savePassword");
       registry.addViewController("/login").setViewName("forward:/myController/login");
       registry.setOrder(Ordered.HIGHEST_PRECEDENCE);

您在 addViewController 中看到您正在尝试访问 CONTROLLER 而不是 HTML,您将通过从方法 addViewControllers 访问的 CONTROLLER 访问您的 HTML。

更新:

如果您将 CSS 放入静态文件夹中的资源中,例如:

您可以像这样简单地访问它们:

<link rel="stylesheet" th:href="@/css/bootstrap-datetimepicker.min.css" />

希望这会有所帮助!

【讨论】:

首先,谢谢 ;) 是的,我现在像这样改变了我的结构(所以 +1),但是仍然有两个问题:如何重定向和设置 ViewController。 好吧,我想你扩展了 WebMvcConfigurerAdapter。所以对于前。这是当您尝试在浏览器中访问您的应用程序时的方式,例如localhost:8080,您将被重定向到“user/showSomething”@Override public void addViewControllers(ViewControllerRegistry registry)registry.addViewController("/").setViewName("forward :/user/showSomething" ); registry.setOrder(Ordered.HIGHEST_PRECEDENCE); super.addViewControllers(注册表); PS:你可能缺少像我前任那样的“前锋”。希望这会有所帮助。 它只是不起作用...无法访问任何 html...即使没有 Spring Security 并且没有 ViewControllerRegistry/ResourceHandlerRegistry 谢谢,我对你的做法有点不同。我现在通过包含 css 和 js 遇到问题...(请参阅更新 3) 你试过 Jhipster 吗?看看它,它可能就是你所需要的。【参考方案2】:

好的,现在我完全明白了。我尽量做到具体。

我的最终结构

1.静态资源

Spring 有一些默认配置,您可以在其中放置静态资源而无需对其进行配置。您需要在 src/main/resources

中创建这些文件夹 /META-INF/resources/ resources(是的,src/main/resources 中的附加资源文件夹 静态 公开

看看here in Spring Doku. 例如,查看 Bob Shields 的第二条评论:

在创建了一堆“findme.txt”文件后,每个文件里面都有不同的“source-relative”路径字符串,我发现可以用“http://host/findme.txt”获取以下位置是:

src/main/resources/public/findme.txt

src/main/resources/static/findme.txt

src/main/resources/resources/findme.txt -(是的,资源^2!)

src/main/resources/findme.txt - 未找到!!

我将文件夹“scripts”和“stylesheets”放在静态文件夹中。当我想在 html 中包含这些文件夹中的文件时,源代码看起来像 src="scripts/file.js",因为发现 static 中的文件和文件夹直接植根于 host/scripts/file.js

我不需要 ResourceHandlerRegistry!

2。视图控制器

我想将我的 login.html 根到 /login,将 savepassword.html 根到 /savepassword 并将我的 index.html 根到 /。这是我所做的:

registry.addViewController("/savepassword").setViewName("savepassword.html");
registry.addViewController("/login").setViewName("login.html");
registry.addViewController("/").setViewName("loggedin/index.html");

我设置 *.html 是因为我有一个问题,即 spring 不知道 /login 和 login(.html) 之间的区别。 如您所见,我将 index.html 放在名为“loggedin”的不同文件夹中。这个文件夹就在我的公共文件夹中(由 Spring 找到,参见 1.)。我为什么要这样做?看看3。

3.春季安全

.authorizeRequests().antMatchers("/stylesheets/**", "/scripts/**","/login", "/user/**").permitAll()
...omitted further configuration...
.loginPage("/login").permitAll();

首先,我希望用户始终必须先登录才能访问任何其他网站。所以登录页面的所有资源都必须可用。

这段代码使样式表和脚本中的每个文件都可以访问。记住样式表和脚本文件夹是静态的。由于自定义登录页面,我必须设置“/ login”。 老实说,我认为.loginPage("/login").permitAll(); 会授予访问权限,但事实并非如此。没有它,Spring 会尝试访问“/login”,但不能导致没有权限,然后自动重定向到 login => ERR_TOO_MANDY_REDIRECTS。 “/user/**”只是我的一些服务,每个用户都可以使用。

如您所见,我不授予对“loggedin”文件夹的访问权限,因此每个访问者只有在登录时才能在“loggedin”中输入文件;)

4.重定向

我刚刚用@RequestController 标记了我的整个控制器,它实现了@ResponseBody。当我返回一个类似 return "redirect:/savepassword"; 的字符串时,Spring 会将其设置为 ResponseBody 并将其解释为 String/Json(?)。

我必须将控制器标记为@Controller 并将@ResponseBody 设置为每个必须返回json 或某事的服务。我应该重定向的服务只用@RequestMapping 和method=RequestMethod.GET 标记。最后,我返回一个类似return "redirect:/savepassword"; 的字符串,这将使Spring 重定向到/savepassword,实际上是放在src/main/resources/public/savepassword.html 中。

最后,它可以工作了,很难找到 spring 是如何为文件提供服务的。我希望它可以帮助别人:)

【讨论】:

以上是关于找不到带有spring boot的html页面的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个 Spring Boot 应用程序找不到主页?

在带有 MongoDB 的 Spring Boot M7 中找不到 ReflectKotlinClass

带有 Spring Data 的 Spring Boot 应用程序找不到 com.mysema.query.types EntityPath

带有 MySQL 的 Spring Boot R2DBC - 异常:找不到表

Spring Boot JSP 404:找不到页面

带有 JOOQ 的 Spring Boot 收到一条消息“需要一个找不到的 'org.jooq.DSLContext' 类型的 bean”