加载流程
StrutsPrepareAndExecuteFilter Struts2中的核心类,有两个功能:预处理与执行
-
预处理
-
配置文件加载顺序
struts.properties ---- 配置常量
name = value
-
struts.xml ---- 配置Action及常量
<constant name="" value="">
使用
include
进行分模块开发,在struts.xml中包含其他配置文件,被包含的文件都是标准的struts配置文件<include file="struts.xml"/> <include file="com/sd/struts.xml"/>
-
web.xml ---- 配置核心过滤器及常量
init-param
以上三个配置文件均可添加常量,后加载的配置文件中的常量值会将先加载配置文件中的常量值覆盖
-
配置常量
-
国际化,解决post提交乱码
<constant name="struts.i18n.encoding
-
指定访问action的后缀名,以下指定后缀为action或不进行配置
<constant name="struts.action.extension" value="action,,"/>
-
指定struts2是否以开发模式运行
- 热加载主配置
- 提供更多的错误信息输出,方便开发时调试
<constant name="struts.devMode" value="true"/>
默认配置
<struts>
<package name="demo" extends="struts-default" namespace="/">
<!-- 如果访问路径404时,跳转到default-action-ref指定action -->
<default-action-ref name="demo1"/>
<!-- method 默认为execute()-->
<!-- result name 默认为success-->
<!-- result type 默认为dispatcher-->
<!-- class 默认为com.opensymphony.xwork2.ActionSupport -->
<action name="demo1">
<result name="*" type="dispatcher">/welcome.jsp</result>
</action>
</package>
</struts>
Action编写方式
-
普通POJO类
定义业务方法,默认为execute()方法
public String execute()
,也可实现其他方法(需要在struts.xml中定义,method
参数执行定义的方法) -
实现Action接口,定义了五个字符串常量
SUCCESS,NONE,ERROR,INPUT,LOGIN
-
继承ActionSupport类
提供了许多默认方法,包括获取国际化信息的方法,数据校验方法,默认的用户请求方法等
Action动态方法调用
-
通配符配置
- 配置struts.xml
<struts> <package name="demo" extends="struts-default" namespace="/"> <global-allowed-methods>regex:.*</global-allowed-methods> <action name="demo1_*" class="com.sd.action.Action1" method="{1}"> <result name="*">/welcome.jsp</result> </action> </package> </struts>
name属性中的*代表任意字符,method中的{1}代表name属性中出现的第一个 * 所代替的字符
-
定义
public String add() { System.out.println("增加"); return SUCCESS; }
-
引用
<h4><a href="${pageContext.request.contextPath}/demo1_add">示例一:增加</a></h4>
-
-
动态访问(使用!来匹配方法,不符合SEO引擎优化)
-
开启动态访问struts.xml
<struts> <constant name="struts.enable.DynamicMethodInvocation" value="true"/> <package name="demo" extends="struts-default" namespace="/"> <global-allowed-methods>regex:.*</global-allowed-methods> <action name="demo1" class="com.sd.action.Action1"> <result name="*">/welcome.jsp</result> </action> </package> </struts>
-
-
定义
public String add() { System.out.println("增加"); return SUCCESS; }
-
引用
<h4><a href="${pageContext.request.contextPath}/demo1!add">示例一:增加</a></h4>
Structs2访问servlet API
-
ActionContext
-
HttpServletRequest(获取,设置request参数)
void put(String key,Object value)
Object get(String key)
HttpParameters getParameters()
-
Application
void setApplication(Map<String,Object> application)
Map<String,Object> getApplication()
-
Session
void setSession(Map<String,Object> session)
Map<String,Object> getSession()
-
ActionContext
static ActionContext getContext();
//获取当前线程的ActionContext 对象
-
ServeletActionContext
-
通过特定接口访问
- ServletRequestAware:实现该接口的Action可以直接访问web应用的HttpServletRequest实例
- ServletResponseAware:实现该接口Action可以直接访问web应用的HttpServletResponse实例
- SessionAware:实现该接口Action可以直接访问web应用的HttpSession实例
- SevletContextAware:实现该接口Action可以直接访问web应用的SevletContext实例
结果页面配置
- 跳转方式
//转发到Action
<result name="*" type="chain">
<param name="actionName">demo1</param>
<param name="namespace">/</param>
</result>
//转发到JSP
<result name="*" type="dispatcher">/welcome.jsp</result>
//重定向到JSP
<result name="*" type="redirect">/welcome.jsp</result>
//重定向到Action
<result name="*" type="redirect">
<param name="actionName">demo1</param>
<param name="namespace">/</param>
</result>
-
全局结果页面配置
在这个包下所有返回相同字符串的值,都可以向这个页面进行跳转
<global-results> <result name="error">/welcome.jsp</result> </global-results>
-
局部页面配置
某个Action中返回的字符串的值,会向这个页面跳转
<action name="demo1"> <result name="*" type="dispatcher">/welcome.jsp</result> </action>
获得参数的方式
-
属性驱动
- 准备与参数键名称相同的属性
- 自动类型转换,只能转换8大基本数据类型及对应包装类
- 支持特定类型字符串转化为Date,例如yyyy-MM-dd
对象驱动
-
模型驱动(实现ModelDriven接口)
//此处必须手动new 对象,否则会报NPE private User userhaha=new User(); @Override public User getModel() { return userhaha; }
-
集合类型参数封装
-
List
-
定义
private List<User> userList; public List<User> getUserList() { return userList; } public void setUserList(List<User> userList) { this.userList = userList; }
-
jsp配置
<form action="${pageContext.request.contextPath}/parm" method="post"> 姓名:<input type="text" name="userList.name"></br> 年龄:<input type="text" name="userList.age"></br>//userList默认为userList[0] 生日:<input type="text" name="userList[0].birthday"> </br> </br> </br> 姓名:<input type="text" name="userList[1].name"></br> 年龄:<input type="text" name="userList[1].age"></br> 生日:<input type="text" name="userList[1].birthday"> <input type="submit" value="提交"> </form>
-
-
Map
-
定义
private Map<String,User> users; public Map<String, User> getUsers() { return users; } public void setUsers(Map<String, User> users) { this.users = users; }
-
配置
<form action="${pageContext.request.contextPath}/param" method="post"> 姓名:<input type="text" name="users['one'].name"><br> 年龄:<input type="text" name="users['one'].age"><br> 生日:<input type="text" name="users['one'].birthday"><br> 爱好: 跑步:<input type="checkbox" name="users['one'].love" value="run"><br> 读书:<input type="checkbox" name="users['one'].love" value="book"><br> 宠物:<input type="checkbox" name="users['one'].love" value="pat"><br> 联系人1:<br> 姓名:<input type="text" name="users['two'].name"><br> 年龄:<input type="text" name="users['two'].age"><br> 生日:<input type="text" name="users['two'].birthday"><br> <%-- 联系人2:<br> 姓名:<input type="text" name="users['two'].name"><br> 年龄:<input type="text" name="users['two'].age"><br> 生日:<input type="text" name="users['two'].birthday"><br>--%> <input type="submit" value="提交"><br> </form> //备注:同一个name值不能出现两次及两次以上
-
-
声明式异常处理
根据<exception-mapping>
出现的位置,异常映射分为两种:
- 局部异常映射:将
<excepion-mapping>
元素作为<action>
元素的子元素配置; - 全局异常映射:将
<exception-mapping>
元素作为<global-exception-mappings>
元素的子元素
<package name="demo" namespace="/" extends="struts-default">
<global-results>
<result name="sql">/index.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping result="sql" exception="java.sql.SQLException"/>
</global-exception-mappings>
<action name="testParams" class="com.ognl.Demo1Action">
<exception-mapping result="sql" exception="java.sql.SQLException"/>
</action>
</package>
全局异常映射对所有的 Action 类都有效,但局部异常映射仅对该异常映射所在的 Action 有效;
拦截器
-
生命周期
生命周期随项目启动创建,随项目关闭而销毁
-
自定义拦截器
实现Interceptor接口
继承AbstractInterceptor类
-
继承MethodFilterInterceptor类(方法过滤拦截器)
定制拦截器拦截方法(拦截哪些方法,哪些方法不拦截)
@Override protected String doIntercept(ActionInvocation actionInvocation) throws Exception { /** * 拦截器放行,需要调用actionInvocation.invoke()方法,返回null即可,逻辑视图由Action处理 * 拦截器不放行,不需要调用actionInvocation.invoke()方法,需要返回一个字符串作为逻辑视图, * 系统会根据返回的字符串跳转到对应的视图资源 */ //前处理 actionInvocation.invoke();//放行 //后处理 return null;//返回逻辑视图 }
-
配置拦截器
注册拦截器
指定拦截器栈
-
指定默认拦截器栈,定制方法是否拦截
<interceptors> <!-- 注册拦截器 --> <interceptor name="myInters" class="com.interceptor.MyInterceptor"/> <!-- 指定拦截器栈--> <interceptor-stack name="myStack"> <!-- 引用定义拦截器 --> <interceptor-ref name="myInters"> <!-- 不能同时指定 --> <!-- 指定方法不拦截 --> <param name="excludeMethods">add,select</param> <!-- 指定方法拦截 --> <!-- <param name="includeMethods"></param> --> </interceptor-ref> <!-- 引用默认拦截器 --> <interceptor-ref name="defaultStack"/> </interceptor-stack> </interceptors> <!-- 指定默认的拦截器栈 --> <default-interceptor-ref name="myStack"/>
OGNL与Struts2的体现(ValueStack)
默认情况下,栈(CompoundRoot root)中放置当前访问的Action对象,提供push()
和pop()
方法。Context部分就是ActionContext数据中心
-
参数接受
通过ognl来实现原生接受到的参数转换成最终Action对象的参数获取方法(以上三种)
//获取值栈 ValueStack stack = ActionContext.getContext().getValueStack(); stack.push(xxx);
-
配置文件
<struts> <package name="demo" namespace="/" extends="struts-default"> <action name="testParams" class="com.ognl.Demo1Action"> <result name="success" type="redirectAction"> <param name="namespace">/</param> <param name="actionName">params</param> <!-- 如果添加的参数 struts "看不懂",则就会作为参数,附加到重定向的路径之后, 如果参数是动态的,可以使用${ }包裹ognl表达式动态取值,取值的位置位于ognl 的值栈区,即对应的Action对象--> <param name="name">${name}</param> </result> </action> <action name="params" class="com.ognl.Demo2Action"> <result name="*">/index.jsp</result> </action> </package> </struts>
public class Demo1Action extends ActionSupport{ private String name="李雷与韩梅梅"; @Override public String execute() throws Exception { return SUCCESS; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
http://localhost:8080/params.action?name=李雷与韩梅梅
-
Struts2标签
<%@ taglib prefix="s" uri="/struts-tags" %>
-
Debug
<s:debug/>
-
遍历标签
!-- 遍历标签 --> <s:iterator value="#names" status="st"> <s:if test="#st.odd"> <s:property value="#st.index"/><br/> </s:if> <s:property/><br/> </s:iterator> <s:iterator value="#names" var="name"> <s:property value="#name"/><br/> </s:iterator> <s:iterator begin="1" end="10" status="1"> <s:property/> </s:iterator> <br/> <s:if test="#names.size()==4"> list 长度为4 </s:if> <s:elseif test="#names.size()==5"> list 长度为5 </s:elseif> <s:else> list 长度不为4 </s:else>
-
属性标签
根据是否带#决定是在ValueStack哪个部分取值
<s:property value="hello"/><br/> <s:property value="hello.length()"/><br/> <s:debug/>
-