Action与Servlet的区别:
Servlet在类第一次被调用的时候创建,且仅创建一次。也就是说,Servlet为单例对象。
Action在类每一次调用的时候都会重新创建一次。
1、Struts2的使用步骤
- 在WEB-INF下的lib文件夹中添加是Strust2相关的jar包。
- 在src下添加配置文件struts.xml文件。注意:文件的位置和名称不能错。
- 在WEB-INF下的web.xml文件中配置过滤器。Struts2所有的功能都是基于过滤器的,所以这一步不能落下。
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2、struts.xml的配置说明
在配置文件中首先需要引入约束:
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
- package标签
<package name="website" extends="struts-default" namespace="/"></package>
name属性:package的名字,可以任意取,但是必须保证package的name属性值唯一。
extends属性:固定取值为struts-default。
namespace属性:与action标签中的name属性一起构成访问路径
- action标签
<action name="user" class="com.website.action.UserAction"></action>
name属性:与外层package标签中的namespace属性值一起构成访问路径
class属性:需要配置的action类的全路径
由于Action类中默认执行execute()方法,如果想执行类中的其他方法,可以通过action中的method属性进行配置。
<action name="findUser" class="com.website.action.UserAction" method="findUser">
但是,如果Action类中的方法很多,上述配置就会很麻烦。可以使用正则表达式来简化此类配置。
<action name="user_*" class="com.website.action.UserAction" method="{1}">
*表示访问路径中匹配到的方法名,{1}表示执行*匹配到的方法名。例如,如果访问路径为user_findUser,则执行的方法为findUser()。
- result标签:用来控制页面的跳转
<result name="success" type="redirect">/index.jsp</result>
name属性:action类中指定方法执行完后的返回值
type属性:页面跳转的方式。默认为dispatcher。
- dispatcher:页面转发
- redirect:页面重定向
- chain:action转发
- redirectAction:action重定向
3、表单数据获取及封装
在servlet中,表单数据的获取是通过service方法中的参数request实现的(request.getParameter()、request.getParameterMap()),但是action对象中的方法是没有参数的,因此如法直接用request对象获得。
获取表单中的数据有二种常用的方法:
- ActionContext类
ActionContext context = ActionContext.getContext(); //获取ActionContext对象
Map<String,Object> params = ActionContext.getParameters();//获取表单数据
- ServletActionContext对象
HttpServletRequest request = ServletActionContext.getRequest();//获得request对象,其他的代码与servlet一样
在action中操作域对象(request、session、servletContext):
HttpServletRequest request = ServletActionContext.getRequest();
HttpSession session = ServletActionContext.getSession();
ServletContext context = ServletActionContext.getServletContext();
表单数据封装方式:
原始的封装方法是先获得表单的数据,再手动封装到对象中去。当对象中的属性较多时,代码比较冗余。
HttpServletRequest request = ServletActionContext.getRequest();
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = new User();
user.setUsername(username);
user.setPassqord(password);
- 属性驱动封装
在action成员变量位置定义变量。(注意:变量的名称和表单的输入项的name属性一致)
生成变量相对应的set()方法。
当DataAction1中的execute()方法执行时,表单中的数据会自动封装到DataAction1的成员变量中。
public class DataAction1 extends ActionSupport {
/*
* 使用属性驱动封装表单数据
*/
//1.定义成员变量
private String username;
private String password;
private String address;
//2.生成set方法
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println(username + " : " + password);
return NONE;
}
}
- 模型驱动封装
Action类实现ModelDriven接口
实现接口中的方法getModel(),在此方法中返回实体类分对象
在Action类中创建实体类的对象
public class DataAction2 extends ActionSupport implements ModelDriven<User>{
private User user = new User();
public User getModel() {
// TODO Auto-generated method stub
return user;
}
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println(user);
return NONE;
}
}
当同时使用模型驱动与属性驱动对同一张表单的数据进行封装时,会默认使用模型驱动封装。
- 表达式封装数据
在Action类中声明实体类
生成实体类的get与set方法
在表单输入项的name属性值里面写表达式形式
public class DataAction3 extends ActionSupport {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println(user.getUsername() + " : " + user.getPassword());
return NONE;
}
}
表单:
<form action="${pageContext.request.contextPath }/data3.action" method="POST">
username:<input type="text" name="user.username">
<br/>
password:<input type="password" name="user.password">
<br/>
<input type="submit" value="提交" />
</form>
4、值栈
值栈类似于javaweb中的域对象。可以在之战中存值,然后在jsp页面中进行显示。
值栈的结构主要包含两部分:
- root:结构是List集合(主要的)
- context:结构是map集合。其中的key值时固定的,为:request、session、application、parameters、attr
- set方法:
ActionContext context = ActionContext.getContext();
ValueStack stack = context.getValueStack();
接着便可以往值栈中添加值:
stack.set("username", "aaa");
- put方法
stack.push("abcd");
- 在action类中定义变量,生成变量的get方法(最常用)
在成员变量位置定义变量
生成变量的get方法
在执行的方法里面,向对象中设置值
public class ValueStackAction1 extends ActionSupport {
private String username;
private User user = new User();
private List<User> list = new ArrayList<User>();
public String getUsername() {
return username;
}
public User getUser() {
return user;
}
public List<User> getList() {
return list;
}
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
username = "itcast";
user.setUsername("asc");
user.setPassword("111");
user.setAddress("China");
list.add(user);
return SUCCESS;
}
}
用第三种方式往值栈中添加值时,不会分配新的空间,会直接放在Action中。
从值栈中获取数据(与ognl一起工作):
- 获取字符串
<s:property value="username"></s:property>
- 获取对象
<s:property value="user.username"></s:property>
- 获取List集合
<s:iterator value="list" var="l">
<s:property value="#l.username"></s:property>
<s:property value="#l.password"></s:property>
</s:iterator>
使用<s:iterator>遍历list集合时,将每次遍历出来的对象,即var属性的值会存放到context中。所以在使用var属性的值时,需要加一个“#”。
获取session中值:
<s:property value="#existUser.username"></s:property>
由于使用set与put方法存值到值栈中时,会开辟新的空间,所以,获取值栈的取值的方式稍有不同。
- get方式
<s:property value="username"/>
- put方式
<s:property value="[0].top"/>
5、拦截器
原理:AOP+责任链
自定义拦截器:
首先,定义一个类继承MethodFilterInterceptor类,并实现doIntercept方法,在方法中实现增强的功能,并使用invocation.invoke()方法执行类似于过滤器中的放行功能。
public class AutoLoginInterceptor extends MethodFilterInterceptor{
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
// TODO Auto-generated method stub
...
return invocation.invoke();
}
}
接着,在src下的struts.xml文件中配置拦截器:
- 在要拦截的action标签所在的package标签中声明拦截器
<interceptors>
<interceptor name="autologin" class="com.website.filter.AutoLoginInterceptor"></interceptor>
</interceptors>
- 在具体的action标签里面使用拦截器
<interceptor-ref name="autologin"></interceptor-ref>
- 在具体的action标签中使用默认的拦截器
<interceptor-ref name="defaultStack"></interceptor-ref>
- 如果不需要对某些方法进行拦截,可以在使用拦截器时,使用param标签对其进行配置
<interceptor-ref name="autologin">
<param name="excludeMethods">login.jsp,register.jsp</param>
</interceptor-ref>