struts2框架(二)
struts2参数封装
属性驱动
属性驱动:只需要在Action中准备与条件的键相同的属性即可自动接收参数.struts2在接收参数时可以帮助我们完成自动类型转换,转换范围:8大基本数据类型及包装类和特定格式(yyyy-mm-dd)的Date.
Action对象生命周期:每次请求都会创建一个新的Action对象,请求处理完销毁
public class Demo1Action extends ActionSupport{
private String name;
private int age;
private Date hiredate;
public Date getHiredate() {
return hiredate;
}
public void setHiredate(Date hiredate) {
this.hiredate = hiredate;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String execute() throws Exception {
System.out.println(name+"=>"+age+"=>"+hiredate);
return SUCCESS;
}
}
对象驱动
对象驱动:与属性驱动相似,主要区别在于表单提交参数键上,使用”对象属性名.属性”来提交参数,不常使用
public class Demo2Action extends ActionSupport{
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String execute() throws Exception {
System.out.println(user);
return SUCCESS;
}
}
jsp页面:
<form action="${pageContext.request.contextPath}/Demo2Action" method="post">
用户名:<input type="text" name="user.name"/><br>
年龄:<input type="text" name="user.age" /><br>
入职日期:<input type="text" name="user.hiredate"/> <br>
<input type="submit" value="提交"/>
</form>
模型驱动
模型驱动:让Action继承ModelDriven接口,在接口方法中返回封装参数的对象.
public class Demo3Action extends ActionSupport implements ModelDriven<User>{
private User user = new User();
@Override
public String execute() throws Exception {
System.out.println(user);
return SUCCESS;
}
@Override
public User getModel() {
return user;
}
}
jsp页面:
<form action="${pageContext.request.contextPath}/Demo3Action" method="post">
用户名:<input type="text" name="name"/><br>
年龄:<input type="text" name="age" /><br>
入职日期:<input type="text" name="hiredate"/> <br>
<input type="submit" value="提交"/>
</form>
复杂参数封装
复杂参数封装:将参数提交到list或map中
1、在action中准备复杂类型的属性
2、表单提交格式
//准备List|Map属性,提供set/get方法
public class Demo4Action extends ActionSupport {
private List list;
private Map<String, String> map;
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
@Override
public String execute() throws Exception {
System.out.println(list);
System.out.println(map);
return SUCCESS;
}
}
jsp页面(表单提交格式):
<form action="${pageContext.request.contextPath}/Demo4Action" method="post">
list:<input type="text" name="list"/><br>
list:<input type="text" name="list"/><br>
list:<input type="text" name="list[5]"/><br>
map:<input type="text" name="map['name']"/><br>
map:<input type="text" name="map['age']"/><br>
<input type="submit" value="提交"/>
</form>
OGNL表达式
OGNL:对象视图导航语言,第三方独立的语言,并不是由Struts2项目组开发,struts2只是整合该语言.
该语言类似于EL表单式语言,用于取值,OGNL要更加强大.
开发准备
导包
只需要导入struts2的包就相当于导入了OGNL的包
代码准备
- 准备Root(Object)
准备Context(Map)
//准备Root对象
User root = new User();
root.setName(“tom”);
root.setAge(22);
//准备Context对象
Map context = new HashMap();User user1 = new User(); user1.setName("jack"); user1.setAge(18); User user2 = new User(); user2.setName("rose"); user2.setAge(16);
context.put(“user1”, user1);
context.put(“user2”, user2);
语法
取值
- 参数1:填写表达式
- 参数2:填写Context部分
参数3:填写Root部分
//取出Root中name属性值
//参数1:填写表达式,参数2:填写Context部分,参数3:填写Root部分,取出Root中的name属性值
System.out.println(Ognl.getValue(“name”, context, root));//取出Context中u1对应的name属性值
System.out.println(Ognl.getValue(“#user1.name”, context, root));
赋值
//为Root中name属性赋值
//参数1:填写表达式,参数2:填写Context部分,参数3:填写Root部分,
Ognl.getValue("name='张三'", context, root);
System.out.println(root.getName());
//为Context中u1对应的name属性赋值
Ognl.getValue("#user1.name ='李四'", context, root);
System.out.println(user1.getName());
访问方法
//调用方法为Root中name属性赋值
//参数1:填写表达式,参数2:填写Context部分,参数3:填写Root部分,
Ognl.getValue("setName('James')", context, root);
System.out.println(root.getName());
//调用方法为Context中u1对应的name属性赋值
Ognl.getValue("#user1.setName('Koby')", context, root);
System.out.println(user1.getName());
访问静态方法
//调用静态方法
System.out.println(Ognl.getValue("@cn.it.ognl.OGNLUtils@echo('hello')", context, root));
//调用Math类中的静态方法,不需要书写完整类型
System.out.println(Ognl.getValue("@@random()", context, root));
//调用静态属性
System.out.println(Ognl.getValue("@@PI", context, root));
创建List|Map
//创建list
List list = (List) Ognl.getValue("{1,2,3,4}", context, root);
System.out.println(list);
//创建map
Map map = (Map) Ognl.getValue("#{'name':'james','age':'18'}", context, root);
System.out.println(map);
OGNL表达式与Struts2整合
整合原理
栈结构
结论:Root在访问时,访问时优先访问栈顶对象.
valuestack中的内容
- Root -> Value Stack Contents
- Context -> Stack Context
OGNL表达式与struts2整合应用
表单参数封装
属性驱动
<form action="${pageContext.request.contextPath}/Demo1Action" method="post">
用户名:<input type="text" name="name"/><br>
年龄:<input type="text" name="age" /><br>
入职日期:<input type="text" name="hiredate"/> <br>
<input type="submit" value="提交"/>
</form>
对象驱动
<form action="${pageContext.request.contextPath}/Demo2Action" method="post">
用户名:<input type="text" name="user.name"/><br>
年龄:<input type="text" name="user.age" /><br>
入职日期:<input type="text" name="user.hiredate"/> <br>
<input type="submit" value="提交"/>
</form>
模型驱动
<form action="${pageContext.request.contextPath}/Demo3Action" method="post">
用户名:<input type="text" name="name"/><br>
年龄:<input type="text" name="age" /><br>
入职日期:<input type="text" name="hiredate"/> <br>
<input type="submit" value="提交"/>
</form>
配置文件中的应用
在struts2配置文件中使用 ognl表达式 {name}:从顶端的Action中取得name属性.
<result name="success" type="redirectAction">
<param name="namespace">/</param>
<param name="actionName">/Demo5Action</param>
<!-- 在strust2配置文件中使用${ognl表达式}
${name}:从root顶端的Action中获得name属性
-->
<param name="name">${name}</param>
</result>
页面struts标签
/**
* OGNL页面取值
*/
public class Demo8Action extends ActionSupport {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String execute() throws Exception {
//栈顶Action的name属性
name = "actionTest";
// request域
ActionContext.getContext().put("requestName", "requestTest");
// session域
ActionContext.getContext().getSession().put("sessionName", "sessionTest");
// application域
ActionContext.getContext().getApplication().put("applicationName", "applicationTest");
return SUCCESS;
}
}
OGNL表达式取值
<h1>OGNL取值</h1>
Action的name属性:<s:property value="name"/><br>
ActionContext|requst的name属性:<s:property value="#requestName"/><br>
session域的name属性:<s:property value="#session.sessionName"/><br>
application域的name属性:<s:property value="#application.applicationName"/><br>
EL表达式取值
<h1>EL表单式取值</h1>
Action的name属性:${name}<br>
ActionContext|requst的name属性:${requestName}<br>
session域的name属性:${sessionName}<br>
application域的name属性:${applicationName}<br>
struts2重写了getAttribute()方法,可以从原生request域、ValueStack中的Root、ValueStack中的Context取值。
struts2处理异常机制
- 抛出异常
struts.xml中配置异常映射
页面取出异常信息
${exception.message}
<td>
<font> ${exception.message}</font>
</td>
自定义拦截器
自定义拦截器方式
方式1:实现Interceptor接口
方式2:继承抽象类AbstractInterceptor
方式3:继承抽象类MethodFilterInterceptor
MethodFilterInterceptor可以指定哪些方法需要拦截或哪些方法不需要拦截
结论
推荐使用第三种,可以定制拦截的方法,也可以不定制,功能强大.
拦截器中的操作
放行
//放行
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
//业务代码
//前处理
System.out.println("MyInterceptor3前处理");
String invoke = invocation.invoke();
//后处理
System.out.println("MyInterceptor3后处理");
return invoke;
}
拦截:就是不调用invoke方法,直接返回一个字符串跳转指定的页面.
//拦截处理
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
//业务代码
System.out.println("需要拦截");
//拦截操作不调用invoke方法,直接返回一个字符串跳转指定的页面
return "error";
}
配置拦截器
- 注册拦截器
- 配置拦截器栈
- 指定默认拦截器栈
- 配置定义拦截方法
指定哪些方法不拦截或不拦截只能选一个配置
注意:受dtt约束,要按顺序配置拦截器
<interceptors>
<!-- 1.注册拦截器 -->
<interceptor name="myInter" class="cn.it.interceptor.MyInterceptor3"></interceptor>
<!-- 2.配置拦截器栈(21个) -->
<interceptor-stack name="myStack">
<!-- 为拦截器指定拦截的方法
注意:指定哪些方法拦截或不拦截只能选一个配置
-->
<interceptor-ref name="myInter">
<!-- 指定哪些方法不拦截 -->
<param name="excludeMethods">execute</param>
<!-- 指定只拦截哪些方法
<param name="includeMethods">execute</param>-->
</interceptor-ref>
<!-- 引用默认栈(20个) -->
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 3.指定默认拦截器栈 -->
<default-interceptor-ref name="myStack"></default-interceptor-ref>
指定全局结果集
<!--全局结果配置 -->
<global-results>
<result name="toLogin" type="redirect" >/login.jsp</result>
</globalt-results>