我目前正在编写一个项目,其中使用 ThymeLeaf HTML 作为前端,使用 Java 作为后端。我正在尝试使用 ThymeLeaf 将 Java 控制器类之一的变量显示到 HTML 页面上。该变量本质上是用户名,只有在用户登录并重定向回主页后才会显示。我在这里遇到的错误是它无法解析用户名。因此,由于某种原因,该变量显然没有在我的 ThymeLeaf HTML 文件中被读取。根据我从 ThymeLeaf 文档中读到的内容,语法似乎是正确的。有人告诉我它应该有效,但由于某种原因它不起作用。无论如何,我想知道是什么导致了这个问题的发生,因为我不确定为什么它一开始没有被阅读?它一直告诉我它无法解析用户名,尽管我的控制器类中有变量。就我的控制器类而言,代码没有任何错误。代码发布在下面,其中包括 ThymeLeaf HTML 页面,如果用户登录,我将尝试在其中显示用户名。第二部分是用户登录的控制器类。
<div class="d-flex justify-content-between align-items-center mb-3">
<h1>Auto Parts</h1>
<a th:href="@{/login}" class="btn btn-primary btn-sm mb-3">Login</a>
<a th:href="@{/about}" class="btn btn-primary btn-sm mb-3" >About Us</a>
<span th:if="${username}" class="ms-3">Welcome, <span th:text="${username}">User</span>!</span>
</div>
@Controller
public class LoginController {
private static final String HARDCODED_USERNAME = "Carter";
private static final String HARDCODED_PASSWORD = "Password907";
@GetMapping("/login")
public String login() {
return "login";
}
@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password, Model model) {
if (username.equals(HARDCODED_USERNAME) && password.equals(HARDCODED_PASSWORD)) {
model.addAttribute("username", username);
return "redirect:/mainscreen";
} else {
model.addAttribute("loginError", true);
return "login";
}
}
// Mapping for mainscreen page
@RequestMapping("/mainscreen")
public String mainscreen(Model model) {
return "mainscreen"; // returns mainscreen.html
}
}
我尝试只显示变量而不使用 if 语句。这也不起作用,因为它以某种方式无法读取变量。我尝试更改我的模型属性名称,但它也不起作用。我所做的一切都不起作用,我似乎无法弄清楚为什么这对我来说是一个问题,因为它应该可以毫无问题地工作。
首先我想说的是,我即将为您提供的解决方案绝对不是您应该这样做的方式(因为它不安全,并且通常不是实现您自己的安全性的好主意)。您应该做的是添加
spring-security
和 thymeleaf-extras-springsecurity6
依赖项,然后在模板中使用提供的 Authentication
对象,如下所示 here
但是,由于您刚刚学习并作为初学者添加 Spring Security,只会导致您不再有任何工作(不是真的,但看起来是这样:),以下是您如何实现它,仅用于 学习目的。您绝对应该稍后更改您的解决方案以使用 Spring Security。
基本上,您希望能够根据用户的会话记住用户(以防他登录或注销)。首先实现一个会话范围的 bean(仅适用于一个会话,每个会话都有自己的)
@SessionScope
@Component
public class MyPrincipal {
private String username = null;
// getter, setter
}
然后将其自动连接到控制器中并将其添加到模型中:
@Controller
public class LoginController {
@Autowired
private MyPrincipal myPrincipal;
// ...
@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password, Model model) {
if (username.equals(HARDCODED_USERNAME) && password.equals(HARDCODED_PASSWORD)) {
myPrincipal.setUsername(username); // you should also set it to empty at logout
return "redirect:/mainscreen";
} else {
model.addAttribute("loginError", true);
return "login";
}
}
@ModelAttribute("username")
public String username() {
return myPrincipal.getUsername();
}
}
@ModelAttribute
为到达此控制器的每个请求添加指定的属性,因此仅保留您希望添加此用户名的控制器方法并将其他方法移动到其他控制器是有意义的 - 但这是一个设计决策.
就像我之前提到的,这有点以不安全的方式重新发明轮子,但我记得我是如何开始的,我也从使用 thymeleaf 开始学习,然后升级我的解决方案以稍后使用 spring security,所以希望这提供了教育价值