Struts2使用
1、环境依赖(jar包)
2 、在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>
3、在src目录下新增struts.xml配置文件(位置固定,名称固定)
<?xml version="1.0" encoding="UTF-8" ?>
<!-- struts2标签依赖 -->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- 常量配置 -->
<constant name="struts.i18n,encoding" value="UTF-8"></constant>
<!-- package中name不能重复,必须extends继承struts-default -->
<package name="p1" extends="struts-default" namespace="/">
<!-- action标签中,name不能重复 -->
<action name="hello" class="lamose.struts2.controller.HelloAction" method="sayHello">
<result name="ok">/success.jsp</result>
</action>
<action name="FormDemo1" class="lamose.struts2.controller.FormDemoActionServletContextAction"></action>
</package>
</struts>
struts.xml标签说明
1、package标签
***package标签是struts的子标签***
<package name="p1" extends="struts-default" namespace="/"> </package>
(1)name属性:作为区分包的属性,可以有多个,但属性值必须唯一
(2)extends属性:自带,继承struts-default
(3)namespace属性:命名空间,默认是斜杠,与action中的name属性值构成方法的访问路径
2、action标签
actino标签是package的子标签
<action name="hello" class="lamose.struts2.controller.HelloAction" method="sayHello">
(1)name属性:进入方法的入口,唯一,与package中namespace属性值构成访问路径
(2)class属性:方法具体路径,即方法的全类名,底层需要通过反射找到
(3)method属性:方法名称,方法中具体执行的哪个方法,在这里定义
3、result标签
result是action标签的子标签
<result name="ok" type="">/success.jsp</result>
(1)name属性:返回值,根据程序返回的Sting值,找到对应的返回结果(页面或者Action)
(2)type属性:
dispatcher(默认的): 转发 , redirect: 重定向 , 页面操作
chain: 转发到一个 Action , redirectAction: 重定向到一个 Action ,action操作
Action三种编写方式
1、创建普通类,不实现任何接口,不继承任何类
public class HelloAction {
public String sayHello(){
System.out.println("成功");
return "ok";
}
}
2、创建普通类,实现Action接口
public class HelloAction implements Action{
@Override
public String execute() throws Exception {
return NONE;
}
}
3、创建普通类,继承ActionSupport类(常用)
public class FormDemoActionServletContextAction extends ActionSupport {
public String execute() {
return NONE;
}
}
Action三种访问方式
1、使用methoed属性访问
<action name="hello" class="lamose.struts2.controller.HelloAction" method="sayHello">
<result name="ok" type="">/success.jsp</result>
</action>
2、使用通配符方式
<action name="book_*" class="lamose.struts2.controller.HelloAction" method="{1}"></action>
3、动态方法访问(不常用)
<!-- Struts2中,动态方法访问默认是关闭的,如果用,需要开启 -->
<constant name="struts.enbke,DynamicMethodInvocation" value="true"></constant>
<action name="UserAction" class="lamose.struts2.controller.HelloAction" ></action>
<form action="${pageContext.request.contextPath }/UserAction!save.action" method="post">
获取表单数据的三种方式
1、使用ActionContext类
返回一个ActionContext对象,使用context.getParameters()方法返回一个Map<String,Object>的集合
ActionContext context = ActionContext.getContext();
Map<String, Object> contextMap = context.getParameters();
Set<String> keySet = contextMap.keySet();
for (String key : keySet) {
Object[] object = (Object[]) contextMap.get(key);
System.out.println(Arrays.toString(object));
}
2、使用ServletActionContext类
返回一个HttpServletRequest对象
HttpServletRequest request = ServletActionContext.getRequest();
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println("username:----" + username + "----password:---" + password);
3、实现ServletRequestAware接口
为了得到HttpServletRequest对象
实现ServletResponseAware接口,得到HttpServletResponse对象
public class FormDemoActionServletContextAction extends ActionSupport implements ServletResponseAware , ServletRequestAware{
private HttpServletRequest request;
private HttpServletResponse response;
@Override
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
@Override
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}
封装表单数据
1、属性封装操作(捞)
(1)、在action中定义变量与页面中标签的name属性值相同
(2)、生成get和set方法
2、模型驱动封装(常用)
(1)、action类实现ModelDriven< T >接口,T泛型:实现时添加实体类
(2)、实现ModelDriven中的getModel方法
(3)、new一个实体类对象,在getModel中返回实体类对象
public class UserAction extends ActionSupport implements ModelDriven<User>{
private User user = new User();
@Override
public User getModel() {
return user;
}
@Override
public String execute() throws Exception {
return NONE;
}
}
3、表达式封装(常用)
(1)、在action中声名一个Entity实体类
(2)、生成实体类的get和set方法
(3)、在页面的name属性中使用表达式
public class UserAction extends ActionSupport{
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
页面
<form action="${pageContext.request.contextPath }/FormDemo1.action" method="post">
username: <input name="user.username" type="text" />
<br />
password: <input name="user.password" type="text" />
<br />
<input type="submit" value="提交"/>
</form>
比较模型驱动封装和表达式封装
1、模型驱动封装和表达式封装都可以将数据封装到实体类中
2、表达式可以将数据封装到不同的实体类中,而模型驱动封装只能封装到单个实体中
OGNL
什么是值栈
1、Servlet中,将数据存放大域对象中,在页面使用EL表达式获取,域对象在一定范围内,存值和取值
2、在Struts2里面,提供了本身一种存储机制,类似于域对象,是值栈,可以存值和取值
----(1)、在action里面把数据放到值栈中,在页面可以获取
3、Servlet和Action的区别
----(1)、Servlet,在默认第一次访问时创建一次,单例多线程对象
----(2)、Action,访问时创建,每次访问都会创建action对象,多例对象
4、值栈存储位置
----(1)、每次访问action都会创建action对象
----(2)、在每个action对象里面都会有且只有一个值栈对象
存值和取值
存值的三种方式:
1、获取值栈对象,调用值栈对象的set方法
2、获取值栈对象,调用值栈对象的push方法
3、在action中定义变量,生成变量的get方法
方法1和2
public class UserGetAction extends ActionSupport {
@Override
public String execute() throws Exception {
//1、获取ActionContext对象
ActionContext context = ActionContext.getContext();
//2、获取值栈对象stack
ValueStack stack = context.getValueStack();
//3、通过值栈对象的set方法存值
stack.set("String", "Object");
//4、通过值栈对象的push方法存值
stack.push("Object");
return "ok";
}
}
方法三(最常用)
public class UserGetAction extends ActionSupport {
//1、声名一个变量
private User user = new User();
//2、生成变量的get方法
public User getUser() {
return user;
}
@Override
public String execute() throws Exception {
//3、设置值
user.setUsername("Lamose");
user.setPassword("123456");
return "ok";
}
}
值栈取值:
1、从值栈中获取普通字符串
<s:property value="username"/>
2、从值栈中获取对象的值
<s:property value="user.username"/>
<s:property value="user.password"/>
3、从值栈中获取List对象的值
— — 第一种方式 — ---
<s:property value="list[0].username"/>
<s:property value="list[0].password"/>
<s:property value="list[1].username"/>
<s:property value="list[1].password"/>
— – — 第二种方式(常用)— – —
<s:iterator value="list">
<s:property value="username"/>
<s:property value="password"/>
<br />
</s:iterator>
— – — 第三种方式 — – —
从
<s:iterator value="list" var="user">
<s:property value="#user.username"/>
<s:property value="#user.password"/>
<br />
</s:iterator>
OGNL中#、%使用
- 在iterator遍历标签中使用
- 在Action的Request中放值,在页面中可以用 # 来取值
// action中
HttpServletRequest request = ServletActionContext.getRequest();
request.setAttribute("req", "FFFFFFWWWWW");
// 页面中
<s:property value="#request.req"/>
- %号使用
在struts2标签里面使用OGNL表达式,如果在使用的时候不识别,只有加上%后才会识别
<s:textfield value="%{#request.req}" name="username"></s:textfield>
Struts2拦截器
- 继承AbstractInterceptor类,实现其中的intercept方法
- 在struts.xml中注册自定义拦截器
- 设置自定义拦截器不拦截的方法
- 使用默认拦截器
拦截器的使用
public class StrutsInter extends AbstractInterceptor {
@Override
public String intercept(ActionInvocation invocation) throws Exception {
HttpServletRequest request = ServletActionContext.getRequest();
Object obj = request.getSession().getAttribute("user");
if(obj != null) {
//放行
return invocation.invoke();
}
return "login";
}
}
拦截器的配置
<struts>
<package name="p1" extends="struts-default" namespace="/">
<!- -注册拦截器 -->
<interceptors>
<interceptor name="checkLogin" class="lamose.struts2.entity.StrutsInter"></interceptor>
</interceptors>
<action name="check" class="lamose.struts2.controller.UserAction">
<!- -设置不拦截的方法 -->
<interceptor-ref name="checkLogin"></interceptor-ref>
<!- -加载一次默认拦截器 -->
<interceptor-ref name="defaultStack"></interceptor-ref>
<result name="success">/success.jsp</result>
<result name="login">/success.jsp</result>
</action>
</package>
</struts>
设置不拦截的方法
<interceptor-ref name="checkLogin"></interceptor-ref>
加载一次默认拦截器(必须要有)
必须要有,不然很多方法无法使用,例如ModelDriven< T >(模型驱动封装)方法
<interceptor-ref name="defaultStack"></interceptor-ref>