首页 > 解决方案 > java.lang.IllegalStateException:Bean 名称“会话”的 BindingResult 和普通目标对象都不能用作请求属性

问题描述

我正在开发我的新 Java + Spring + Thymeleaf 项目。所以今天我从 thymeleaf 收到了一条非常奇怪的信息:

java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'session' available as request attribute

你知道,这真的很奇怪。根据 thymeleaf 文档https://www.thymeleaf.org/doc/articles/springmvcaccessdata.html(第 3 章):

Similarly to the request parameters, session attributes can be access by using the session. prefix:
    <p th:text="${session.mySessionAttribute}" th:unless="${session == null}">[...]</p>

那么好吧。我尝试了另一种方法:

Or by using #session, that gives you direct access to the javax.servlet.http.HttpSession object: ${#session.getAttribute('mySessionAttribute')}

并得到了例外:

java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name '#session' available as request attribute

我在谷歌上没有找到这个问题的任何解决方案。因此,是时候向您展示一些代码了。控制器映射:

@Controller
@RequestMapping("/admin")
public class AdminController {
@GetMapping("/addPost")
    public String addPost(HttpSession session, Model model) {
        session.setAttribute("post", new Post());
        return "admin/add-post";
    }

    @PostMapping("/addPost")
    public String processAddPost(HttpSession session) {
        Post post = (Post)session.getAttribute("post");
        try {
            postService.addPost(post);
        } catch (Exception ignore) {}
        session.removeAttribute("post");
        return "redirect:/admin/listPosts";
    }
...
}

一段 HTML 页面(在对 /admin/addPost 的 GET 请求中显示):

<form 
        th:action="@{/admin/previewPost}" 
        th:object="${session.post}" 
        method="post">
        <input 
            id="post_name_input"
            placeholder="Post name" 
            th:field="*{name}" />
        <br>

        <textarea
            id="post_description_textarea"
            class="wide-input"
            placeholder="Post content" 
            th:field="*{description}" />
        <br>
        <button type="submit">Create</button>
    </form>

我究竟做错了什么?也许,百里香中有一个错误?我的 build.gradle:

buildscript {
    repositories {
        mavenCentral()
        jcenter()
    }
    dependencies {
        classpath 'com.bmuschko:gradle-tomcat-plugin:2.4.1'
    }
}

apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'com.bmuschko.tomcat'

compileJava.options.encoding = 'UTF-8'

tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}

def tomcatVersion = '9.0.22'
dependencies {
    testImplementation 'junit:junit:4.12'
    tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
            "org.apache.tomcat.embed:tomcat-embed-logging-juli:8.5.2",
            "org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}"

    testCompile group: 'org.hamcrest', name: 'hamcrest-all', version: '1.3'
    testCompile group: 'org.mockito', name: 'mockito-all', version: '1.8.4'
}

tomcat {
    httpProtocol = 'org.apache.coyote.http11.Http11Nio2Protocol'
    ajpProtocol  = 'org.apache.coyote.ajp.AjpNio2Protocol'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.apache.tomcat:tomcat-dbcp:9.0.22'
    implementation 'org.postgresql:postgresql:42.2.6'
    implementation 'org.springframework:spring-context:5.1.8.RELEASE'
    implementation 'org.springframework:spring-webmvc:5.1.8.RELEASE'
    implementation 'org.springframework:spring-orm:5.1.8.RELEASE'
    implementation 'org.springframework:spring-tx:5.1.8.RELEASE'
    implementation 'org.springframework:spring-aspects:5.1.8.RELEASE'
    implementation 'org.hibernate:hibernate-core:5.4.1.Final'
    implementation 'org.springframework.security:spring-security-core:5.1.5.RELEASE'
    implementation 'org.springframework.security:spring-security-web:5.1.5.RELEASE'
    implementation 'org.springframework.security:spring-security-config:5.1.5.RELEASE'
    implementation 'org.springframework.data:spring-data-jpa:2.1.10.RELEASE'
    implementation 'javax.servlet:servlet-api:2.5' 
    implementation 'org.hibernate.validator:hibernate-validator:6.0.2.Final'
    implementation 'org.hibernate.validator:hibernate-validator-annotation-processor:6.0.2.Final'
    implementation 'org.thymeleaf:thymeleaf:3.0.11.RELEASE'
    implementation 'org.thymeleaf:thymeleaf-spring5:3.0.11.RELEASE'
    implementation 'org.aspectj:aspectjrt:1.5.4'
    implementation 'org.apache.logging.log4j:log4j-api:2.8.2'
    implementation 'org.apache.logging.log4j:log4j-core:2.8.2'

}

UPD: 此答案被标记为重复。但事实并非如此。我已经尝试了引用问题中的所有解决方案,但它们对我不起作用。主要区别在于,在我的情况下,百里香上下文中似乎没有“会话”对象。

标签: javaspringthymeleaf

解决方案


首先,让我纠正你。使用 get 控制器,当您重定向到需要提交表单的页面时,您需要发送模型对象。但是你正在投入 session.setAttribute("post", new Post()). 所以首先你必须修改你的get控制器,比如

@GetMapping("/addPost")
public String addPost(Model model) {
    model.addAttribute("post", new Post());
    return "admin/add-post";
}

你的html表单应该是这样的

<form 
        th:action="@{/admin/addPost}" 
        th:object="${post}" 
        method="post">
        <input 
            id="post_name_input"
            placeholder="Post name" 
            th:field="*{name}" />
        <br>

        <textarea
            id="post_description_textarea"
            class="wide-input"
            placeholder="Post content" 
            th:field="*{description}" />
        <br>
        <button type="submit">Create</button>
    </form>

现在你需要修改你的 post 控制器来保存 post 对象。为此,请修改您的后控制器,例如

   @PostMapping("/addPost")
    public String processAddPost(@ModelAttribute("post") Post post,  HttpSession session) {
         session.setAttribute("post", post);
         postService.addPost(post);
         return "redirect:/admin/listPosts";
    }

在您正在使用的这个控制器中,postService但您没有自动连接您的postService. 所以postService在这个控制器中自动接线。希望这会奏效。

如果您想投入价值,请session使用

session.setAttribute("post", post);

这条线。无论如何,如果您想检索会话数据,那么您可以使用语句

Post post = (Post)session.getAttribute("post");

注意:无论您是否得到预期的结果,请给出回应。


推荐阅读