2015-03-04 9 views
12

Próbuję użyć Bootstrap CSS z moją aplikacją internetową Spring + Security + Thymeleaf. CSS jest pobierany przez mój niestandardowy ekran logowania i wszystko jest w porządku - wszystkie style są stosowane. Jednakże, kiedy przechodzę z ekranu logowania do następnego ekranu z jakiegoś powodu moja strona HTML nie zbiera pliku CSS i style nie są stosowane. Czy ktoś może pomóc?Spring Thymeleaf Bootstrap CSS

Poniżej znajdują się odpowiednie pliki:

plik Logowanie html (która pracuje bez zarzutu):

<!DOCTYPE html> 
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> 
    <head> 
    <meta charset="utf-8"></meta> 
    <meta http-equiv="X-UA-Compatible" content="IE=edge"></meta> 
    <meta name="viewport" content="width=device-width, initial-scale=1"></meta> 
    <meta name="description" content=""></meta> 
    <meta name="author" content=""></meta> 

    <title>motodoc hub Sign in</title> 

    <!-- Bootstrap core CSS --> 
    <link href="resources/css/bootstrap-3.3.2-dist/bootstrap.min.css" rel="stylesheet" /> 

    <!-- Custom styles for this template --> 
    <link href="resources/css/signin.css" rel="stylesheet" /> 

    <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> 
    <!--[if lt IE 9]> 
     <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> 
     <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> 
    <![endif]--> 
    </head> 

    <body> 

    <div class="container"> 

     <p th:if="${loginError}">Wrong username or password</p> 
     <form th:action="@{/login}" method="post" class="form-signin"> 
     <h2 class="form-signin-heading">Please sign in</h2> 
     <label for="username" class="sr-only">Username</label> 
     <input type="text" id="username" name="username" class="form-control" placeholder="Username" /> 
     <label for="password" class="sr-only">Password</label> 
     <input type="password" id="password" name="password" class="form-control" placeholder="Password" /> 
     <!-- <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button> --> 
     <input type="submit" value="Log in" class="btn btn-lg btn-primary btn-block" /> 
     </form> 

    </div> <!-- /container --> 


    <!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> 
    <script src="resources/js/ie10-viewport-bug-workaround.js"></script> 
    </body> 
</html> 

Logowanie kontroler (znowu - wszystko działa poprawnie z tym):

package com.motodoc.hub.controller; 

import org.springframework.stereotype.Controller; 
import org.springframework.ui.Model; 
import org.springframework.web.bind.annotation.RequestMapping; 

@Controller 
public class LoginController { 

    // Login form 
    @RequestMapping("/login") 
    public String login() { 
     System.out.println("in here ...."); 
     return "login"; 
    } 

    // Login form with error 
    @RequestMapping("/login-error") 
    public String loginError(Model model) { 
     model.addAttribute("loginError", true); 
     return "login"; 
    } 
} 

Strona główna plik html (jest to plik, w którym z jakiegoś powodu CSS nie jest "zbierany"):

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> 
<head> 

    <meta charset="utf-8"></meta> 
    <meta http-equiv="X-UA-Compatible" content="IE=edge"></meta> 
    <meta name="viewport" content="width=device-width, initial-scale=1"></meta> 
    <meta name="description" content=""></meta> 
    <meta name="author" content=""></meta> 

    <!-- Bootstrap core CSSS --> 
    <link href="resources/css/bootstrap-3.3.2-dist/bootstrap.min.css" rel="stylesheet" /> 

    <title>Home</title> 
</head> 
<body> 
    <div th:include="templates/navbar :: navigationBar"></div> 
    <br></br> 
    <h1>Login success!</h1><br></br> 

    <div> 
    <table class="table table-striped"> 
    <caption th:text="#{user.table.caption}">Site Users</caption> 
    <thead> 
     <tr> 
      <th scope="col" th:text="#{user.id.label}">Id</th> 
      <th scope="col" th:text="#{user.firstname.label}">First Name</th> 
      <th scope="col" th:text="#{user.lastname.label}">Last Name</th> 
      <th scope="col" th:text="#{user.username.label}">Username</th> 
     </tr> 
    </thead> 
    <tbody> 
     <tr th:each="user : ${currentResults.content}"> 
      <td th:text="${user.id}">1</td> 
      <td th:text="${user.firstName}">George</td> 
      <td th:text="${user.lastName}">Washington</td> 
      <td th:text="${user.username}">gwash</td> 
     </tr> 
    </tbody> 
</table> 
</div> 



    <!-- Bootstrap core JavaScript 
    ================================================== --> 
    <!-- Placed at the end of the document so the pages load faster --> 
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script> 
    <script src="resources/js/bootstrap-3.3.2-dist/bootstrap.min.js"></script> 

</body> 
</html> 

główna klasa kontrolera:

@Controller 
public class HomeController { 

    @Autowired 
    private ISecurityUserService securityUserService; 

    @RequestMapping("/home") 
    public String redirect() {  
     return "redirect:/home/page/1"; 
    } 

    // home 
    @RequestMapping(value="/home/page/{pageNumber}", method = RequestMethod.GET) 
    public String getUsers(
      @PathVariable("pageNumber") Integer pageNumber, 
      ModelMap model) { 

     Page<Person> currentResults = securityUserService.findAll(pageNumber-1); 

     model.addAttribute("currentResults", currentResults); 

     //Pagination variables 
     int startIndex = Math.max(1, pageNumber - 5); 
     int endIndex = Math.min(startIndex + 10, currentResults.getTotalPages()); 

     model.addAttribute("url", "home"); 
     model.addAttribute("startIndex", startIndex); 
     model.addAttribute("endIndex", endIndex); 
     model.addAttribute("currentIndex", pageNumber); 
     //model.addAttribute("users", users); 

     return "home"; 
    } 
} 

Wiosna config bezpieczeństwo:

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

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

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

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
      .authorizeRequests() 
      .antMatchers("/resources/**").permitAll() 
      .anyRequest().authenticated() 
      .and() 
     .formLogin() 
      .loginPage("/login") 
      .permitAll() 
      .defaultSuccessUrl("/home") 
      .failureUrl("/login-error") 
      .and() 
     .logout() 
      .invalidateHttpSession(true) 
      .logoutUrl("/logout") 
      .deleteCookies("JSESSIONID,SPRING_SECURITY_REMEMBER_ME_COOKIE") 
      .logoutSuccessUrl("/") 
      .permitAll(); 
    } 

    @Bean 
    public CustomAuthenticationProviderImpl authenticationProvider() { 
     return new CustomAuthenticationProviderImpl(); 
    } 

    @Bean 
    public BCryptPasswordEncoder encoder() { 
     return new BCryptPasswordEncoder(10); 
    } 
} 

Zastosowanie klasa kontekst config:

@Configuration 
@ComponentScan(basePackages = {"com.motodoc.hub.*"}) 
@EnableWebMvc 
@Import({SpringDataConfig.class, 
    ThymeleafConfig.class, 
    SecurityConfig.class, 
    ServiceBeans.class}) 
@ImportResource("classpath:trace-context.xml") 
@PropertySource("classpath:spring.properties") 
public class ApplicationContext extends WebMvcConfigurerAdapter { 

    // Maps resources path to webapp/resources 
    @Override 
    public void addResourceHandlers(ResourceHandlerRegistry registry) { 
     registry.addResourceHandler("/resources/**").addResourceLocations("/resources/"); 
    } 

    // Only needed if we are using @Value and ${...} when referencing properties 
    @Bean 
    public static PropertySourcesPlaceholderConfigurer properties() { 
     PropertySourcesPlaceholderConfigurer propertySources = new PropertySourcesPlaceholderConfigurer(); 
     Resource[] resources = new ClassPathResource[] { 
       new ClassPathResource("spring.properties") }; 
     propertySources.setLocations(resources); 
     propertySources.setIgnoreUnresolvablePlaceholders(true); 
     return propertySources; 
    } 

    // Provides internationalization of messages 
    @Bean 
    public ResourceBundleMessageSource messageSource() { 
     ResourceBundleMessageSource source = new ResourceBundleMessageSource(); 
     source.setBasename("messages"); 
     return source; 
    } 
} 

Thymeleaf klasa config:

@Configuration 
public class ThymeleafConfig { 

    @Bean 
    public ServletContextTemplateResolver templateResolver() { 
     ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(); 
     resolver.setPrefix("/WEB-INF/views/"); 
     resolver.setSuffix(".html"); 
     resolver.setTemplateMode("HTML5"); 
     resolver.setOrder(1); 
     return resolver; 
    } 

    @Bean 
    public SpringTemplateEngine templateEngine() { 
     SpringTemplateEngine engine = new SpringTemplateEngine(); 
     engine.setTemplateResolver(templateResolver()); 

     //add spring security dialect 
     Set<IDialect> dialects = new HashSet<IDialect>(); 
     dialects.add(springSecurityDialect()); 
     engine.setAdditionalDialects(dialects); 

     return engine; 
    } 

    @Bean 
    public ThymeleafViewResolver thymeleafViewResolver() { 
     ThymeleafViewResolver resolver = new ThymeleafViewResolver(); 
     resolver.setTemplateEngine(templateEngine()); 
     return resolver; 
    } 

    @Bean 
    public SpringSecurityDialect springSecurityDialect() { 
     return new SpringSecurityDialect(); 
    } 
} 
Struktura

webapp Directory Project:

enter image description here

Odpowiedz

12

Zdobione ... Błąd uczeń z mojej strony ...

Poniższy link w moim pliku /home.html nie została do rozwiązywania prawo lokalizacja:

<link href="resources/css/bootstrap-3.3.2-dist/bootstrap.min.css" rel="stylesheet" /> 

zamiast więc użyłem kontekstowej względny adres URL w następujący sposób:

<link th:href="@{/resources/css/bootstrap-3.3.2-dist/bootstrap.min.css}" rel="stylesheet" /> 

I to się udało.