1.使用默认拦截器时,<package>元素必须要有extends = "struts-default"
2.pageContext的作用。jsp九大内置对象都是通过pageContext来初始化的。
3.防止表单重复提交可以使用token拦截器(不过很少用),具体使用过程就是添加下边的代码:
①在相应的action中配置
<package name="test" namespace="/" extends="struts-default">
<action name="test" class="com.bjsxt.interceptor.InterceptorServlet">
<interceptor-ref name="token"></interceptor-ref>
<result name="success">/ok.jsp</result>
<result name="invalidate.token">/tokenInvalidate.jsp</result>
</action>
</package>
②增加tokenInvalidate.jsp
<%@ page language="java" jmport="java.util.*" pageEncoding="utf-8"%>
<h1>表单不能重复提交</h1>
③在所提交的表单上边增加<s:token>标记
<s:token action="InterceptorServlet">
<s:textfield name="uname"><s:/textfield>
<s:token></s:token>
<s:submit></s:submit>
</s:token>
4.在官方默认的是
private File file;
private String contentType;
若要是自己写,应该做相应的改变
private File upload;
private String uploadContentType;//一定要对应写
5.在action的指定方法执行完毕后总会返回一个字符串,struts2根据返回的字符串(注意为字符串,也就是说返回值是string类型)去action的配置中的result去找匹配的名字,根据配置执行下一步的操作。一个action可以有多个result.所以action中方法的返回值都是string类型。虽然有时用void也能达到同样的目的,但这不完整,只能实现一部分功能。下边用例子说明。如
UserAction中
public String add(){
uDao.add(user);
return "success";
}
对应的struts.xml如下
<action name="userAction" class="com.bjsxt.action.UserAction" >
<result name="success">/jsp/ok.jsp</result>
<result name="list" >/jsp/list.jsp</result>
</action>
表示在成功添加用户后,会返回到一个页面,体验比较好。
public void add(){
uDao.add(user);
}
对应的struts.xml如下
<action name="userAction" class="com.bjsxt.action.UserAction" >
</action>
这样也可以添加进用户,但在成功添加后,也不会出现任何提示,体验不好。
所以推荐返回值为string类型的。
6.struts2里的模型驱动和属性驱动还得注意在jsp页面的写法
属性驱动property-driven必须这样写
用户名:<input name="user.name"><br/><!--必须这样写,因为它是通过属性注入的,否则存不到数据库 -->
手机号:<input name="user.tel"><br/>
模型驱动model-driven通常这样写
用户名:<input name="name"><br/>
手机号:<input name="tel"><br/>
虽然它的jsp页面也可以写成和属性驱动一样的
属性驱动还必须得写相应的get/set方法,模型驱动不需要
7.要在jsp页面使用c标签,除了要添加引入语句
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
之外,还得有一个前提,那就是action向作用域设置了值。如
request.setAttribute("role",role);
才可以在jsp利用el表达式页面获取到。
而s标签是struts2内置的,若想使用,则除了引入语句
<%@ taglib prefix="s" uri="/struts-tags" %>
之外,还是得往作用域中添加,这时与c标签不一样,c得手动添加,而s必须有相应的值才行,向作用域添加已经内部封装。如
public String findAll(){
this.list = uDao.findAll();
return "view";
}
只要定义了那个list,在jsp页面就可以用
<s:iterator value="list" var="result">
<result.name>
<result.id>
</s:iterator>
这样的获取,s标签中value="list"的list和this.list中的对应。
有时获取value前边还得加一个#,这是为了获取stack context中的值(stack context常和value stack一起出现,可以用<s:debug>调出)。这也是ognl表达式。如:
Map<Integer,String> roleMap = new HashMap<Integer, String>();
roleMap.put(1, "学生");
roleMap.put(2, "教师");
sc.setAttribute("roleMap", roleMap);
此时在jsp页面获取roleMap时是这样
<s:iterator value="#application.roleMap" var="obj" >
<s:property value="#application.roleMap[#obj.type]" /><!--不要忘记最后的“/”,否则报错-->
</s:iterator>
8.struts的作用,把请求和视图分开;
namespace若不为空,则必须以“/”开头;
result的默认name为success,若不写,即表示name为success;
struts2里的action最好继承ActionSupport,因为它里边封装了许多方法,可以直接继承来使用。比如可以直接使用execute方法。不继承会很麻烦,企业里几乎所有struts2都要继承ActionSupport。
9.struts2可以通过属性接收参数,即直接在浏览器地址栏输入
http://localhost:8080/testStruts/userAction!add?name=aa&age=20
这样的值,那么本质上name和age是怎样被action接受的?如Action为
public class UserAction extends ActionSupport {
private String name;
//name和age能否被接收只与getName,getAge等方法中get后的参数有关
//而与这两处声明的全局变量是什么无关,如只要get方法不变,这儿就
//算改为private String ttttttname也能被正确接收
//但默认全局变量名和get中一致
private intring add() {
return SUCCESS;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
name和age能否被接收只与getName,getAge等方法中get后的参数有关。即实际上struts2是通过get方法接收参数的,而不是通过全局变量接收。
10.<s:property>取出的是value stack中的值property value,而值栈value stack中存储的是键值对。
11.类似于
Map request = (Map)ActionContext.getContext.get("request");
Map session = ActionContext.getContext.getSession;//获取session
Map application = ActionContext.getContext.getApplication;//获取application
//getContext是获取Action执行的上下文
//context翻译成中文就是“上下文”,表示当前程序执行时周围的环境,比如在教室学习时,context就是指电脑、空调、电灯等的情况。
//struts会把这些周围环境封装到context内,可以把context看作容器
//servletContext表示servlet运行的环境,包括servlet的各种配置
//ActionContext包括getApplication,getResponse等
是一种单例模式,与struts2多例模式相悖,虽然这也能取得参数的值,但不推荐。
12.map类型的request,session,application真实类型为HttpServerRequest,HttpSession,ServletContext
13.value stack(值栈)中的值可以直接获取
stack context中内容可以让s标签利用"# + 作用域"获取,这是ognl表达式。如
<s:property value="#request.r1">
这等同于
<%=request.getAttribute("r1")%>
类似的还有
<s:property value="#session.s1">||<%=session.getAttribute("s1")%>
<s:property value="#application.a1">||<%=application.getAttribute("a1")%>
14.ActionContext不是单例,而是ThreadLocal对象。存的是键值对,线程名和对应的存储在该线程的值。
15.IOC(inverse of control)指的是控制反转,用来访问web元素,如request,session,application等。这种方法最常用。
并且用ioc绝大部分是用来获取session的值,不需获取request和application。例如:
private Map<String, Object> request;//不需要自己初始化,struts2容器会替我们初始化
private Map<String, Object> session;
private Map<String, Object> application;
public String execute() {
request.put("r1", "r1");
//实际上我们根本就不用去获取request,它在value stack中会得到,而value stack是放在request里边
//这个方法只是用来演示ioc可以访问request
session.put("s1", "s1");
application.put("a1", "a1");//application也是几乎不用,所以综合下来ioc大部分是取session的值
return SUCCESS;
}
public void setRequest(Map<String, Object> request) {
this.request = request;
}
//几乎不用
public void setSession(Map<String, Object> session) {
this.session = session;
}
//这个需要,注意session为map类型
public void setApplication(Map<String, Object> application) {
this.application = application;
}
//几乎不用
16.result的type包括redirect和dispatcher,都只能跳转到页面,而不能是action,跳转action用chain和redirectAction