当前位置: 首页 > 知识库问答 >
问题:

Thymeleaf意外和奇怪的类强制转换异常

壤驷乐邦
2023-03-14

更新:

下面的编辑#2显示了此问题的临时解决方案,但提出了一个新问题。

我正在为我的视图开发一个使用Spring MVC和Thymeleaf的客户端。

我有两个用户,一个基本用户和一个管理员。当基本用户登录时,其个人信息将显示在主页上。当管理员登录时,他可以执行各种搜索操作以在后端数据库(MongoDB)中查找用户。他可以按州、市、用户名等查找。。。。

我得到这个错误:java.lang.ClassCastException: formBeans。只有在客户端上执行特定的操作序列后,才能将用户强制转换为java.util.Map

  1. 以管理员身份登录

就像我说的,当基本用户登录时,应该会显示他的个人信息。以基本用户身份登录其他时候也有效,但在这种特定情况下无效。但是,此错误可能发生在我可能没有遇到的其他情况下。

下面是我的用户模型和表单支持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无法识别“user”对象。

有什么想法吗?

编辑:感谢您的回复。以下是一些更相关的代码:

堆栈跟踪:在我的视图或任何Java类中,堆栈跟踪不会给出特定行号的任何错误。这似乎是SpringJava文档中的内部错误。

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)

“user”对象存储为会话对象。以下是来自控制器的一些相关代码:

   /* 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]}。。。。etc而不是${user.firstname},${user.lastname}。。。等我的基本情况。html页面,此问题不再存在。

我实现这一点的最初方法是使用Thymeleaf表达式语言,而新的解决方法是Spring表达式语言。Spring似乎将对象的键值对存储为映射,这种新方法直接访问映射的键值对。所以访问用户['firstname']就等于“Bob”。

但现在问题仍然存在,为什么它不能将用户对象强制转换为map,这样我就可以使用${User.key}访问这些值?

共有1个答案

元叶秋
2023-03-14

我刚刚在从百里舞2升级到3的时候遇到了同样的事情。问题是,我们有一些代码将“字段符号”用于非字段用途。

例如,我们有:

th:if="*{someProperty}"

而不是:

th:if="${bean.someProperty}"

我只需要对几个表单进行简单的修改,我们就可以开始了。

 类似资料:
  • 例外情况: java.lang.ClassCastException:com.interconnect.library.gcm.util.checkplayServices(util.java:96),com.interconnect.library.gcm.regiseter.handleRegister(regiseter.java:53),com.interconnect.library.g

  • 问题内容: 这可能是在某个地方被问到的,但我找不到。有人可以澄清为什么此代码可以编译并打印出来吗? 问题答案: 它被解析为: 所有和运算符都是一元或的。 在这种情况下,两次取反,因此将其打印为。

  • 我在一个项目中遇到了一些奇怪的行为,我举了一个例子: 重点是类中的方法和接口的方法。方法中的前两行给出了编辑器中的错误,这些错误解释了

  • 我模拟了Jsch()类,并在下面的方法中获得了类强制转换异常。 原始方法。 联机获取Mockito异常。 例外情况: java.lang.ClassCastException:com.jcraft.jsch。频道$MockitoMock$1983492043不能转换为com.jcraft.jsch.ChannelSftp 测试用例调用方法。

  • 问题内容: 尝试将结果集强制转换为映射类时,我收到了hibernate类的类强制转换异常…我能够查看返回的结果集中的数据…但是它以Object []的形式返回我可以将Object []设置为List …我可以正确地进行hibernate映射吗?我从查询中获取了正确的数据,但映射不正确… 映射 映射类 参加班 主要 问题答案: 对于测试,我建议您在产生类强制转换异常的语句周围放置一个try-catc

  • 调用AffineTransform: 它驻留在自定义形状类(YingYang)中。 当我进行调用时,当我试图从绘图面板或在类本身(如果我将返回类型更改为YingYang)中将它转换回一个YingYang时,我会得到一个类转换异常。 java.lang.ClassCastException:java.awt.Geom.Path2D$Double不能强制转换为Animation.Yingyang 任何