Spring集成JSF/PrimeFaces时ManagedBean不支持POST请求的解决办法
解决JSF ManagedBean在Spring环境中POST请求被禁止的问题
我来帮你搞定这个问题——你不用给JSF的ManagedBean加@PostMapping,因为它是JSF的控制器组件,不是Spring MVC的控制器,POST请求被禁止的根源是Spring环境和JSF的请求处理路径冲突,咱们一步步来解决:
1. 先解决最可能的问题:Spring DispatcherServlet拦截了JSF请求
从你的web.xml来看,你只配置了Spring的上下文监听器,但如果你的项目引入了Spring MVC依赖,Spring会默认尝试处理所有请求,导致JSF的FacesServlet拿不到POST请求,从而返回"POST not allowed"。
两种处理方案:
- 如果不需要Spring MVC:直接移除
spring-webmvc依赖,只保留Spring核心和上下文相关依赖,这样Spring就不会拦截请求,JSF的FacesServlet可以正常处理表单提交。 - 如果需要同时用Spring MVC和JSF:给Spring DispatcherServlet指定专属请求路径,让它和JSF划分清楚职责:
修改web.xml,添加Spring DispatcherServlet的配置:
这样JSF的<!-- 新增Spring DispatcherServlet配置 --> <servlet> <servlet-name>SpringDispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring-servlet.xml</param-value> </init-param> <load-on-startup>2</load-on-startup> <!-- 比FacesServlet晚启动 --> </servlet> <servlet-mapping> <servlet-name>SpringDispatcher</servlet-name> <url-pattern>/api/*</url-pattern> <!-- 只处理API类请求 --> </servlet-mapping>*.xhtml请求由FacesServlet处理,Spring MVC只处理/api/*路径的请求,两者就不会冲突了。
2. 改用CDI注解替代JSF原生ManagedBean(推荐)
你现在用的javax.faces.bean.ManagedBean是JSF的旧注解,在Spring集成环境下,用CDI的注解能更好地和Spring上下文兼容:
import javax.annotation.PostConstruct; import javax.enterprise.context.SessionScoped; import javax.inject.Named; import java.io.Serializable; @Named // 替代@ManagedBean @SessionScoped // CDI的会话作用域,需要实现Serializable public class UserLoginView implements Serializable { private String username; private String password; public UserLoginView() {} @PostConstruct public void init() { this.username = ""; this.password = ""; } // getter和setter保持不变 public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String login() { System.out.println("beans.backing.UserLoginView.login()->username: " + username + ", password: " + password); if (username != null && username.equals("admin") && password != null && password.equals("admin")) { System.out.println("log in success"); return "indexLogged?faces-redirect=true"; // 加redirect避免重复提交POST } else { System.out.println("login failed"); return "index?faces-redirect=true"; } } }
注意:CDI的@SessionScoped要求Bean实现Serializable接口,另外返回导航结果时加上?faces-redirect=true,可以防止用户刷新页面时重复提交表单。
3. 补全faces-config.xml的配置
你的faces-config.xml内容不完整,资源束的配置没写完,需要补充完整,确保EL表达式能正确读取消息:
<?xml version="1.0" encoding="UTF-8"?> <faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd" version="2.2"> <application> <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver> <resource-bundle> <base-name>mensajes</base-name> <var>msgs</var> <!-- 对应视图中#{msgs}的变量名 --> </resource-bundle> </application> </faces-config>
4. 检查Spring上下文配置
确保你的Spring配置文件(比如applicationContext.xml)开启了组件扫描,让Spring能管理自己的Bean,同时和JSF的Bean互通:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 扫描你的Spring组件所在的包 --> <context:component-scan base-package="com.yourpackage"/> <!-- 启用注解驱动 --> <context:annotation-config/> </beans>
最后验证
做完上面的配置后,重启项目,点击登录按钮,应该就能正常触发UserLoginView.login()方法了,不会再出现POST请求被禁止的错误。
内容的提问来源于stack exchange,提问作者david montero
相关产品推荐
相关产品推荐

