英文:
Why th:text doesn't want to display in the main.html template while it displays in other pages?
问题
下面是你提供的代码部分的翻译:
main.html (/templates/layouts/main)
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<!-- Required meta tags -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
<script src="https://kit.fontawesome.com/2dafcd6f62.js" crossorigin="anonymous"></script>
<!-- Bootstrap CSS // Let's connect the CSS to the grid system -->
<link rel="stylesheet" type="text/css" href="css/bootstrap-4.3.1-dist/css/bootstrap.min.css">
<!-- CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" type="text/css" href="css/style.css" th:href="@{css/style.css}">
<link rel="stylesheet" type="text/css" href="css/bootstrap-4.3.1-dist/css/bootstrap-grid.min.css"
th:href="@{css/bootstrap-4.3.1-dist/css/bootstrap-grid.min.css}">
<link rel="stylesheet" type="text/css" href="css/bootstrap-4.3.1-dist/css/bootstrap.min.css"
th:href="@{css/bootstrap-4.3.1-dist/css/bootstrap.min.css}">
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"
integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<title layout:title-pattern="$LAYOUT_TITLE - $CONTENT_TITLE">Using Spring Security Thymeleaf</title>
</head>
<body>
<div class="jumbotron text-center container-color">
<h1 class="home-title font-text-style">Text</h1>
<p>Text, text, text...</p>
</div>
<div layout:fragment="content">
the login content should get here
</div>
<footer class="text-center footer bg-dark">
<div class="font-style">
<div>
Today is <span th:text="${#dates.format(dateTime, 'yyyy-MM-dd')}">Today is</span></div>
<br>Your IP address is <span class="yourIp" th:text="${yourip}">IP as: 127.0.0.1</span>
</div>
</footer>
</body>
</html>
login.html (/templates/auth/login)
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
lang="en" layout:decorate="~{layouts/main}">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" type="text/css" href="css/bootstrap-4.3.1-dist/css/bootstrap-grid.min.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap-4.3.1-dist/css/bootstrap.min.css">
<!--We are choosing these two to let the browser to load faster-->
<link rel="stylesheet" type="text/css" href="css/logincss.css">
<!--this is the last one so that we can override previous boostrap styles if we want-->
<head>
<body class="signin-body">
<div class="container signin-container" layout:fragment="content">
<div class="row">
<div class="col"></div>
<div class="col-sm-12 col-md-8">
<div class="card signin-card">
<div class="card-block">
<!-- <img src="images/logindetails.png" width="50%" height="50%" class="img-fluid signin-img"> -->
<form name="login" th:action="@{/login}" method="post" class="signin-form">
<div class="form-group">
<h2 class="form-signin-heading">Please sign in</h2>
<div th:if="${param.error}" class="alert alert-danger">Wrong username and
password</div>
<div th:if="${param.logout}" class="alert alert-success">You successfully
logged out</div>
<label for="username" class="sr-only">Username</label>
<input type="text" id="username" name="username" class="form-control"
placeholder="Username" required="true">
<label for="password" class="sr-only">Password</label>
<div class="form-group">
<input type="password" id="password" name="password" class="form-control"
placeholder="Password" required="true">
</div>
</div>
<button class="btn btn-lg btn-primary btn-block signin-btn" type="submit">Login</button>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck1">
<a class="new-account" href="/registration">Create New Account</a>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="col"></div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="css/bootstrap-4.3.1-dist/js/bootstrap.min.js"></script>
</body>
</html>
ApiController.java 的一部分
@Controller
public class ApiController {
private final Logger log = LoggerFactory.getLogger(this.getClass());
private EmailService emailService;
private UserService userService;
private FormUserService formUserService;
@Autowired
public void setForm
<details>
<summary>英文:</summary>
I'm practicing Spring Security+Thymeleaf and I have a template with header and footer, **main.html** and a **login page** where the login content is. I successfully made the login content "wrapped" into the template but the only thing that doesn't want to work is the `th:text="${#dates.format(dateTime, 'yyyy-MM-dd')}"` and the `th:text="${yourip}`" in the footer of the main.html template. These are working in the other pages after I set them in the controller class. I made sure in the Config class that /templates/layouts/main is ignored (`.antMatchers(staticResources).permitAll()`) but it still doesn't want to work. I don't know how should I define the template page in the controller class since the template is just a template unlike the login page.
**UPDATE:** I just tried to put the footer with the indicated th:text context variables in the login view and doesn't work either, but it works when I put them in the registration view for example.
**main.html** (/templates/layouts/main)
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<!-- Required meta tags -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
<script src="https://kit.fontawesome.com/2dafcd6f62.js" crossorigin="anonymous"></script>
<!-- Bootstrap CSS // Let's connect the CSS to the grid system -->
<link rel="stylesheet" type="text/css" href="css/bootstrap-4.3.1-dist/css/bootstrap.min.css">
<!--CSS-->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" type="text/css" href="css/style.css" th:href="@{css/style.css}">
<link rel="stylesheet" type="text/css" href="css/bootstrap-4.3.1-dist/css/bootstrap-grid.min.css" th:href="@{css/bootstrap-4.3.1-dist/css/bootstrap-grid.min.css}">
<link rel="stylesheet" type="text/css" href="css/bootstrap-4.3.1-dist/css/bootstrap.min.css" th:href="@{css/bootstrap-4.3.1-dist/css/bootstrap.min.css}">
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<title layout:title-pattern="$LAYOUT_TITLE - $CONTENT_TITLE">Using Spring Security Thymeleaf</title>
</head>
<body>
<div class="jumbotron text-center container-color">
<h1 class="home-title font-text-style">Text</h1>
<p>Text, text, text...</p>
</div>
<div layout:fragment="content">
the login content should get here
</div>
<footer class="text-center footer bg-dark">
<div class="font-style">
<div>
Today is <span th:text="${#dates.format(dateTime, 'yyyy-MM-dd')}">Today is</span></div>
<br>Your IP address is <span class="yourIp" th:text="${yourip}">IP as: 127.0.0.1</span>
</div>
</footer>
</body>
</html>
**login.html** (/templates/auth/login)
<!doctype html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
lang="en" layout:decorate="~{layouts/main}">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" type="text/css" href="css/bootstrap-4.3.1-dist/css/bootstrap-grid.min.css">
<link rel="stylesheet" type="text/css" href="css/bootstrap-4.3.1-dist/css/bootstrap.min.css">
<!--We are choosing these two to let the browser to load faster-->
<link rel="stylesheet" type="text/css" href="css/logincss.css">
<!--this is the last one so that we can override previous boostrap styles if we want-->
<head>
<body class="signin-body">
<div class="container signin-container" layout:fragment="content">
<div class="row">
<div class="col"></div>
<div class="col-sm-12 col-md-8">
<div class="card signin-card">
<div class="card-block">
<!-- <img src="images/logindetails.png" width="50%" height="50%" class="img-fluid signin-img"> -->
<form name="login" th:action="@{/login}" method="post" class="signin-form">
<div class="form-group">
<h2 class="form-signin-heading">Please sign in</h2>
<div th:if="${param.error}" class="alert alert-danger">Wrong username and password</div>
<div th:if="${param.logout}" class="alert alert-success">You successfully logged out</div>
<label for="username" class="sr-only">Username</label>
<input type="text" id="username" name="username" class="form-control" placeholder="Username" required="true">
<label for="password" class="sr-only">Password</label>
<div class="form-group">
<input type="password" id="password" name="password" class="form-control" placeholder="Password" required="true">
</div>
</div>
<button class="btn btn-lg btn-primary btn-block signin-btn" type="submit">Login</button>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customCheck1">
<!-- <label class="custom-control-label" for="customCheck1">Remember me <a href="#"> Need help?</a></label> -->
<a class= "new-account" href="/registration">Create New Account</a>
</div>
</form>
</div>
</div>
</div>
<div class="col"></div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="css/bootstrap-4.3.1-dist/js/bootstrap.min.js"></script>
</body>
</html>
**snippet of the ApiController.java**
@Controller
public class ApiController {
private final Logger log = LoggerFactory.getLogger(this.getClass());
private EmailService emailService;
private UserService userService;
private FormUserService formUserService;
@Autowired
public void setFormUserService(FormUserService formUserService) {
this.formUserService = formUserService;
}
@Autowired
public void setEmailService(EmailService emailService) {
this.emailService = emailService;
}
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
@RequestMapping("/")
public String home(Model model) {
model.addAttribute("serverTime", new Date());
model.addAttribute("itskills", "IT skills");
model.addAttribute("references", "References");
model.addAttribute("qualifications", "Qualifications");
model.addAttribute("myproject", "My Project");
model.addAttribute("it", "IT");
model.addAttribute("vaadin", "VAADIN");
model.addAttribute("java", "JAVA");
model.addAttribute("exam", "EXAM");
model.addAttribute("yourip", userService.userIpAddress());
return "index";
}
@PostMapping("/login")
public String login(Model model) {
model.addAttribute("dateTime", new Date());
model.addAttribute("yourIp", userService.userIpAddress());
return "auth/login";
}
}
**snippet of the config class**
@EnableGlobalMethodSecurity(securedEnabled=true)
@EnableWebSecurity
@Configuration
public class SecurityConf extends WebSecurityConfigurerAdapter {
String[] staticResources = {
"/css/**",
"/layouts/main"
};
@Bean
public UserDetailsService userDetailsService() {
return super.userDetailsService();
}
private UserDetailsService userService;
@Autowired
public void setUserService(UserDetailsService userService) {
this.userService = userService;
}
@Autowired
public void configureAuth(AuthenticationManagerBuilder auth) {
try {
auth
.inMemoryAuthentication()
.withUser("user")
.password("user")
.roles("USER");
} catch (Exception e) {
System.out.println(" " + e.getMessage());
}
}
@Override
public void configure(WebSecurity web) {
web
.ignoring()
.antMatchers(staticResources);
}
@Override
public void configure(HttpSecurity httpSec) {
try {
httpSec.authorizeRequests()
.antMatchers(staticResources).permitAll()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/registration").permitAll()
.antMatchers("/reg").permitAll()
.antMatchers("/log").permitAll()
.antMatchers("/main").permitAll()
.antMatchers("/addUser").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login").permitAll()
.and().rememberMe().tokenValiditySeconds(60*60*7).key("message")
.and()
.logout()
.logoutSuccessUrl("/login?logout")
.permitAll();
} catch (Exception ex) {
System.out.println(" " + ex.getMessage());
}
}
</details>
# 答案1
**得分**: 0
只有在我将`WebConf`类中的`HIGHEST_PRECEDENCE`更改为`LOWEST_PRECEDENCE`时,它才对我起作用:
```java
@Configuration
public class WebConf implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("auth/login");
registry.setOrder(Ordered.LOWEST_PRECEDENCE);
}
}
显然,这并不是最佳实践,是否有其他更好的解决方案?
英文:
It only works for me when I change HIGHEST_PRECEDENCE for LOWEST_PRECEDENCE in the WebConf class:
@Configuration
public class WebConf implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("auth/login");
registry.setOrder(Ordered.LOWEST_PRECEDENCE);
}
}
This is obviously not the best practice, is there any other better solution?
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论