更新:
下面的编辑#2显示了此问题的临时解决方案,但提出了一个新问题。
我正在使用Spring MVC和Thymeleaf开发一个客户端。
我有两个用户,一个基本用户和一个管理员。当基本用户登录时,他的个人信息将显示在他的主页上。当管理员登录时,他可以执行各种搜索操作以在后端数据库(MongoDB)中查找用户。他可以通过州,城市,用户名等找到....
我在客户端执行特定的操作序列后才收到此错误:java.lang.ClassCastException: formBeans.User cannot be cast to java.util.Map
:
就像我说的,当基本用户登录时,应该显示他的个人信息。以基本用户身份登录可以在其他时间登录,但在此特定情况下则不行。但是,在我可能没有遇到的其他情况下可能会发生此错误。
这是我的用户模型和表单支持bean类:
package formBeans;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
public class User {
private String firstname;
private String lastname;
private String username;
private String password;
private String phoneNumber;
private String email;
private String address;
private String city;
private String state;
private String zipCode;
public String getFirstname() {
return firstname;
}
public String getLastname() {
return lastname;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public String getPhoneNumber() {
return phoneNumber;
}
public String getEmail() {
return email;
}
public String getAddress() {
return address;
}
public String getCity() {
return city;
}
public String getState() {
return state;
}
public String getZipCode() {
return zipCode;
}
public void setFirstname(String firstname) {
this.firstname = format(firstname);
}
public void setLastname(String lastname) {
this.lastname = format(lastname);
}
public void setUsername(String username) {
this.username = format(username);
}
public void setPassword(String password) {
this.password = password;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public void setEmail(String email) {
this.email = format(email);
}
public void setAddress(String address) {
this.address = format(address);
}
public void setCity(String city) {
this.city = format(city);
}
public void setState(String state) {
this.state = format(state);
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
public String format(String data) {
String firstLetter = data.substring(0, 1).toUpperCase();
String restLetters = data.substring(1).toLowerCase();
return firstLetter + restLetters;
}
}
以下是基本用户的主页:
<!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">
<head>
<title>Home</title>
<link rel="stylesheet" th:href="@{/css/topcoat-desktop-light.min.css}" href="../../css/topcoat-desktop-light.min.css"/>
</head>
<body>
<div th:include="fragment :: header"></div>
<h1>Welcome, <span th:text="${credentials.username}"></span> </h1>
<h2>My profile:</h2>
<a th:href="@{/edit}">Edit my profile</a>
<br></br>
<br></br>
<table>
<tr><td>Firstname:</td> <td th:text="${user.firstname}"></td></tr>
<tr><td>Lastname:</td> <td th:text="${user.lastname}"></td></tr>
<tr><td>Username:</td> <td th:text="${user.username}"></td></tr>
<tr><td>Address:</td> <td th:text="${user.address}"></td></tr>
<tr><td>City:</td> <td th:text="${user.city}"></td></tr>
<tr><td>State:</td> <td th:text="${user.state}"></td></tr>
<tr><td>Zip code:</td> <td th:text="${user.zipCode}"></td></tr>
<tr><td>Email:</td> <td th:text="${user.email}"></td></tr>
<tr><td>Phone number:</td> <td th:text="${user.phoneNumber}"></td></tr>
<tr><td><hr></hr></td></tr>
</table>
</body>
</html>
正如您在html页面中看到的那样,有时Thymeleaf无法识别&#34;用户&#34;宾语。
有什么想法吗?
编辑:感谢您的回复。以下是一些更相关的代码:
堆栈跟踪:堆栈跟踪不会在我的视图或任何Java类中的特定行号上给出任何错误。这似乎是Spring的Java文档中的内部错误。
java.lang.ClassCastException: formBeans.User cannot be cast to java.util.Map
at org.springframework.context.expression.MapAccessor.read(MapAccessor.java:49)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:188)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:94)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.access$000(PropertyOrFieldReference.java:46)
at org.springframework.expression.spel.ast.PropertyOrFieldReference$AccessorLValue.getValue(PropertyOrFieldReference.java:375)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:88)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:120)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:267)
at org.thymeleaf.spring4.expression.SpelVariableExpressionEvaluator.evaluate(SpelVariableExpressionEvaluator.java:139)
at org.thymeleaf.standard.expression.VariableExpression.executeVariable(VariableExpression.java:154)
at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:59)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:103)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:133)
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:120)
at org.thymeleaf.standard.processor.attr.AbstractStandardTextChildModifierAttrProcessor.getText(AbstractStandardTextChildModifierAttrProcessor.java:68)
at org.thymeleaf.processor.attr.AbstractTextChildModifierAttrProcessor.getModifiedChildren(AbstractTextChildModifierAttrProcessor.java:59)
at org.thymeleaf.processor.attr.AbstractChildrenModifierAttrProcessor.processAttribute(AbstractChildrenModifierAttrProcessor.java:59)
at org.thymeleaf.processor.attr.AbstractAttrProcessor.doProcess(AbstractAttrProcessor.java:87)
at org.thymeleaf.processor.AbstractProcessor.process(AbstractProcessor.java:212)
at org.thymeleaf.dom.Node.applyNextProcessor(Node.java:1017)
at org.thymeleaf.dom.Node.processNode(Node.java:972)
at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:695)
at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:668)
at org.thymeleaf.dom.Node.processNode(Node.java:990)
at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:695)
at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:668)
at org.thymeleaf.dom.Node.processNode(Node.java:990)
at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:695)
at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:668)
at org.thymeleaf.dom.Node.processNode(Node.java:990)
at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:695)
at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:668)
at org.thymeleaf.dom.Node.processNode(Node.java:990)
at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:695)
at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:668)
at org.thymeleaf.dom.Node.processNode(Node.java:990)
at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:695)
at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:668)
at org.thymeleaf.dom.Node.processNode(Node.java:990)
at org.thymeleaf.dom.Document.process(Document.java:93)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1155)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1060)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1011)
at org.thymeleaf.spring4.view.ThymeleafView.renderFragment(ThymeleafView.java:335)
at org.thymeleaf.spring4.view.ThymeleafView.render(ThymeleafView.java:190)
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1244)
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1027)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:971)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:85)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1521)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1478)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
&#34;用户&#34;对象存储为会话对象。以下是控制器的一些相关代码:
/* Here are my session attributes */
@Controller
@SessionAttributes({ "credentials", "user" })
public class ViewController implements ErrorController {
/* Here is the login function. If the user is a basic user, it redirects him to /getBasicUser.*/
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(@ModelAttribute("credentials") Credentials credentials,
RedirectAttributes redirect) {
RestTemplate restTemplate = new RestTemplate();
RoleInfo roleInfo = restTemplate.postForObject(
"http://localhost:8080/users/login", credentials,
RoleInfo.class);
if (roleInfo != null) {
if (roleInfo.isAdmin()) {
return "redirect:/adminHome";
} else {
redirect.addFlashAttribute("credentials", credentials);
return "redirect:/getBasicUser";
}
} else {
return "login_fail";
}
}
/* This function GETs the basic user from the back-end (MongoDB) repository and stores it as a session object in the model using redirect.addFlashAttribute("user", user);*/
@RequestMapping(value = "/getBasicUser", method = RequestMethod.GET)
public <T> String getBasicUser(
@ModelAttribute("credentials") Credentials credentials,
Model model, RedirectAttributes redirect) {
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:8080/users/getBasicUser?username="
+ credentials.getUsername();
ResponseEntity<User> responseEntity = restTemplate.exchange(
url,
HttpMethod.GET,
new HttpEntity<T>(createHeaders(credentials.getUsername(),
credentials.getPassword())), User.class);
User user;
user = responseEntity.getBody();
if (user != null) {
redirect.addFlashAttribute("user", user);
System.out.println("username: " + user.getUsername());
return "redirect:/basicHome";
} else {
return "register_fail";
}
}
/* This is the method that returns the home page. If you look at the getBasicUser() method above, it redirects it to this home page */
@RequestMapping(value = "/basicHome", method = RequestMethod.GET)
public String getBasicHomePage() {
return "basic_home";
}
编辑#2:根据https://github.com/thymeleaf/thymeleaf/issues/357,当我将${user['firstname']}, ${user['lastname']}
,....等而不是${user.firstname}, ${user.lastname}
,...等添加到我的basicHome.html页面时,此问题不再坚持。
我实现这个的原始方式是使用Thymeleaf表达式语言,而新的,解决的方式是Spring Expression Language。 Spring似乎将对象的键值对存储为地图,并且这种新方式直接访问地图的键值对。因此,访问用户[&#39;名字&#39;]将等于&#34; Bob&#34;。
但现在问题仍然存在,为什么它不能将User对象转换为map,以便我可以使用$ {user.key}来访问这些值?
答案 0 :(得分:0)
从百里香2更新到3时,我遇到了同样的问题。问题是,我们有一些代码将“字段符号”用于非字段用途。
例如,我们有:
th:if="*{someProperty}"
代替:
th:if="${bean.someProperty}"
我只需要对几个表格进行简单的修复,我们就很好了。