<web-app>
<!-- JSF FacesServlet -->
<servlet>
<servlet-name>FacesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>FacesServlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<!-- Struts 2 FilterDispatcher -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>struts-cleanup</filter-name>
<filter-class>org.apache.struts2.dispatcher.ActionContextCleanUp</filter-class>
</filter>
<filter-mapping>
<filter-name>struts-cleanup</filter-name> <url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Spring ContextLoaderListener -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 編碼過濾器 -->
<filter>
<filter-name>CharacterEncoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>gb2312</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- JSF 監聽器 -->
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
<listener>
<listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
</web-app>
<faces-config>
<application>
<variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>
</application>
<managed-bean>
<managed-bean-name>userBean</managed-bean-name>
<managed-bean-class>com.jsf.beans.User</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>service</property-name>
<value>#{userService}</value>
</managed-property>
</managed-bean>
<navigation-rule>...</navigation-rule>
</faces-config>
<struts>
<!-- JSF 攔截器堆疊 -->
<package name="jsf" extends="jsf-default">
<interceptors>
<interceptor-stack name="jsfFullStack">
<interceptor-ref name="params"/>
<interceptor-ref name="basicStack"/>
<interceptor-ref name="jsfStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="jsfFullStack"/>
</package>
<!-- 業務包繼承 jsf 包 -->
<package name="main" namespace="/" extends="jsf">
<action name="login" class="loginAction" method="login">
<result name="input">/input2.jsp</result>
<result name="error">/error.jsp</result>
<result name="success">/success.jsp</result>
</action>
</package>
</struts>
<beans>
<bean name="userService" id="userService"
class="com.jsf.service.UserService"
factory-method="getInstance"
lazy-init="false" scope="prototype"/>
<bean id="loginAction" class="com.jsf.beans.User" scope="prototype">
<property name="service"><ref local="userService"/></property>
</bean>
</beans>
package com.jsf.beans;
public class User extends ActionSupport implements Serializable {
// 欄位、getter/setter 略
private UserService service;
// JSF 入口
public String execute() {
if (service.validate(this.id, this.password)) {
User u = service.getUser(this.id);
this.setAge(u.getAge()); this.setName(u.getName());
return "success";
}
return "error";
}
// Struts 2 入口
public String login() throws Exception {
if (service.validate(this.id, this.password)) {
User u = service.getUser(this.id);
ActionContext.getContext().put("userBean", u);
return "success";
}
return "error";
}
}
<%@ taglib uri="https://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="https://java.sun.com/jsf/html" prefix="h"%>
<f:view>
<h:form>
用戶名:<h:inputText value="#{userBean.id}"/>
密碼:<h:inputSecret value="#{userBean.password}"/>
<h:commandButton value="登錄" action="#{userBean.execute}"/>
</h:form>
</f:view>
<%@ taglib uri="/struts-tags" prefix="s"%>
<%@ taglib uri="https://java.sun.com/jsf/core" prefix="f"%>
<f:view>
<s:form action="login" namespace="/">
<s:textfield name="id" label="用戶名"/>
<s:password name="password" label="密碼"/>
<s:submit value="登錄"/>
</s:form>
</f:view>
web.xml 同時啟用 JSF FacesServlet、Struts2 FilterDispatcher、Spring ContextLoaderListener、雙 JSF 監聽器faces-config.xml 配置 DelegatingVariableResolver 打通 JSF-Springstruts.xml 定義 jsfFullStack 攔截器堆疊,業務包 extends="jsf"prototype,符合 Request 域生命週期四框架疊加極度複雜、維護成本高。現代架構建議: