java - 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: 此答案被标记为重复。但事实并非如此。我已经尝试了引用问题中的所有解决方案,但它们对我不起作用。主要区别在于,在我的情况下,百里香上下文中似乎没有“会话”对象。
解决方案
首先,让我纠正你。使用 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");
注意:无论您是否得到预期的结果,请给出回应。
推荐阅读
- html - 在我的网页中,一些字符在上传到主机时发生了变化,但在本地 Asp.net MVC 中很好
- javascript - javascript:在重复时拆分多维数组
- ruby-on-rails - 如何从rails中的路由将参数传递给控制器?
- android - MapView 和 Expandablelistview 滚动
- c# - NamedPipeServerStream.ReadAsync() 在 CancellationToken 请求取消时不退出
- android - Android 语音转文本问题
- azure - Azure AdlCopy 错误:无效的 JSON 基元:
- windows - 使用变量后 PowerShell 命令失败
- sql - 如何比较不同的数据库表列并在 SQL Server 中添加?
- javascript - 想要使用 jQuery 以垂直方式获取 td 选择框选定值