十三、Struts2的处理流程
request—>StrutsPrepareAndExecuteFilteràInterceptor(Struts2内置的一些拦截器或用户自定义拦截器)àAction(用户编写的Action,类似Struts1中的Action)àResult(类似Struts1中的forward)àJsp/Htmlàresponse
StrutsPrepareAndExccuterFilter是Struts2框架的核心控制器,它负责拦截由<url-pattern>/*</url-pattern>指定的所有用户请求,当用户请求到达时,该Filter会过滤用户的请求。默认情况下,如果用户请求的路径不带后缀或者后缀以.action结尾,这时请求将被转入Struts2框架处理,否则Struts2框架将过滤该请求的处理。当请求转入Struts2框架处理时会经过一系列的拦截器,然后再转到Action。与Struts1不同,Struts2对用户每一次请求都会创建一个Action,所以Struts2的Action是线程安全的
十四、Struts2指定多个配置文件
将配置文件以模块进行划分,然后通过include导入
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<include file="struts-user.xml"></include>
<include file="struts-trade.xml"></include>
</struts>
十五、Struts2动态方法调用(在Struts2.1版本文档中已经不推荐使用了)
如果在action中存在多个方法时,我们可以使用!+方法方法名调用指定的方法,如下:
public class HelloWorldAction{
private String message;
public String getMessage(){
return message;
}
public String execute() throws Exception{
this.message = “我是execute方法”
return “success”;
}
public String other() throw Exception{
this.message = “我是other方法”;
}
}
假设访问上面的action的URL路径为:/struts2/test/helloworld.action
要访问action的other方法,我们可以这样调用:
/struts2/test/helloworld!other.action
如果不想使用动态方法调用,我们可以通过常量
struts.enable.DynamicMethodInvocation关闭动态方法调用.
<constant name=”struts.enable.DynamicMethodInvocation” value=”false”/>
Struts2使用通配符定义action(官方推荐)
<package name=”employee”
namespace=”/control/employee” extends=”struts-default”>
<action name=”list_*”
class=”cn.itcast.action.HellWorldAction method=”{1}”>
<result name=”success”>
/WEB-INF/page/message.jsp
</result>
</action>
</package>
注:
a). *通配符可以添加多个如: list_*_*_*
b). method=”{1}” 表示取第一个*
c). 通配符可以放置多个地方如 class、result中
十六、Struts2 请求参数的接受
以下两种方法,当参数比较多的时候,用第一种方法,将会发现action中有很多setter、getter方法,这样不利于阅读action,所以建议使用第二种。
a). 采用基本类型接收请求参数(get/post)
在Action类中定义与请求参数同名的属性,Struts2便能接受请求参数并赋值给同名属性:
如:请求路径,http://localhost:8080/test/view.action?id=78
public class ProductAction{
private Integer id;
//struts2通过反射技术调用与请求参数同名的属性的setter方法来获取请求参数值
public void setId(Integer id) {
this.id = id;
}
public Integer getId{
return id;
}
}
b). 采用符合类型接收请求参数
如:请求路径,http://localhost:8080/test/view.action?product.id=78
public class ProductAction{
private Product product;
public void setProduct(Product product) {
this.product = product;
}
public Product getProduct() {
return product;
}
}
Struts2首先通过反射技术调用Product的默认构造器创建product对象然后在通过反射技术调用product中与请求参数同名的属性的setter方法来获取请求参数
十七、Struts2有两种类型转换器
局部类型转换器/全部类型转换器
a). 自定义转换类型
package cn.itcast.type.converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter;
publicclass DateTypeConverter extends DefaultTypeConverter {
@Override
public Object convertValue(Map<String, Object> context, Object value, Class toType) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
try {
if(toType == Date.class){//当字符串向Date类型转换时
String[] params = (String[]) value;// request.getParameterValues()
return dateFormat.parse(params[0]);
}elseif(toType == String.class){//当Date转换成字符串时
Date date = (Date) value;
return dateFormat.format(date);
}
} catch (ParseException e) {}
returnnull;
}
}
完成具体的双向转化代码后,需要将上面的类型注册为局部类型转换器:
在Action类所有的包下放置ActionClassName-conversion.properties文件,ActionClassName是Action的类名,后面的-conversion.properties是固定写法,对于本例而言,文件的名称应为HelloWroldAction-conversion.properties。
properties文件中的内容为:
birthday=cn.itcast.type.converter.DateTypeConverter
b).自定义全局类型转换器
将上面的局部类型转换器注册为全局类型转换器:
在WEB-INF/classes下放置xwork-conversion.properties文件。在properties文件中的内容为:
待转换的类型=类型转换器的全类名
java.util.Date=cn.itcast.conversion.DateConverter
十八、访问或添加request/session/application属性
import java.util.Arrays;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
public class HelloWorldAction {
public String execute(){
ActionContext ctx = ActionContext.getContext();
ctx.getApplication().put("app", "应用范围");//往ServletContext里放入app
ctx.getSession().put("ses", "session范围");//往session里放入ses
ctx.put("req", "request范围");//往request里放入req
ctx.put("names", Arrays.asList("老张", "老黎", "老方"));
return "message";
}
public String rsa() throws Exception{
HttpServletRequest request = ServletActionContext.getRequest();
ServletContext servletContext = ServletActionContext.getServletContext();
request.setAttribute("req", "请求范围属性");
request.getSession().setAttribute("ses", "会话范围属性");
servletContext.setAttribute("app", "应用范围属性");
//HttpServletResponse response = ServletActionContext.getResponse();
return "message";
}
}
备注:ognl表达式其实完全可以通过JSTL、EL结合来代替ognl