分为4个方面:
1.struts2的配置 及其配置中属性的介绍 2.数据操作 3 值栈 4拦截器
(1).
问题一:struts2与struts1有什么不同
struts2是在struts1和webwork的基础之上一个全新的框架 他是web层的框架
配置
核心文件的配置
1.核心文件的名称和位置是固定的
位置:在src的目录下 名称:struts.xml
2.具体的标签配置与介绍
引入dtd约束
最外层 有struts标签
3个常用的标签
package标签的使用和配置
name属性 :package的名称来区分不同的package
extends属性:继承了struts-default才具有struts的功能
namespace属性:默认值为"/"与action的名称构成访问路径
action标签的使用和配置
name属性:与package的namespace构成访问路径
class属性:填写action类的具体的路径
method属性:在action执行默认的execute()方法 但是你要访问其他的方法这时你就需要用到这个属性 值为方法名
result标签的使用和配置
name属性:action方法的返回值
type属性:这个属性来决定重定向和转发 默认的值为dispatcher redirect为重点向 redirectAction为重定向到action中 chain为转发到action当中 (一般不用 缓存问题)
常量的配置
在环境当中寻找到default.properties文件里面有常量
配置下面的常量是干嘛呢?
<constant name="struts.i18n.encoding" value="utf-8"></constant>在发送表单数据的时候时常会有中文 会产生乱码的问题 配置这个就可以解决
post:提交直接配置就可以
get:提交通过编码的方式进行new String()
分模块开发:
在实际开发中是协同开发 这就意味着核心文件会经过不同的人员进行修改就会容易出错
<include file=""></include>导入其他的配置文件
常用的创建action的方式:
1.创建普通类 不继承也不实现
2.创建类实现Action接口
3.创建类继承ActionSupport
常用的访问action的方式
1 常用的为通配符的实现方式
2.action的method属性方式实现
3.动态访问的方式实现
全局结果页面的配置
<global-results><result></result></global-results>
如果即配置了全局也配置了局部结果页面 那么只会执行局部结果页面
(2)
获取表单数据的3中方式
1.ActionContext对象的getParameters()方法
public String execute(){ ActionContext actionContext=ActionContext.getContext(); Map<String,Parameter> map=actionContext.getParameters(); Set<String> key=map.keySet(); for (String string : key) { Parameter parameter=(Parameter)map.get(string); System.out.println(parameter.toString()); } return NONE; }
2.ServletActionContext对象的getRequest .getServletContext()方法
public String execute(){ HttpServletRequest request=ServletActionContext.getRequest(); String username=request.getParameter("username"); String password=request.getParameter("password"); String address=request.getParameter("address"); System.out.println(username); System.out.println(password); System.out.println(address); return NONE; }
3.action实现一个接口得到request
public class Form1DemoAction extends ActionSupport implements ServletRequestAware{ private static HttpServletRequest request; @Override //要有这种思想:相当于构造函数将声明的类具有这个函数传过来的参数进行对接 让这个声明类具有这个参数的属性 public void setServletRequest(HttpServletRequest arg0) { // TODO Auto-generated method stub this.request=arg0; } public String execute(){ String username=request.getParameter("username"); String password=request.getParameter("password"); String address=request.getParameter("address"); System.out.println(username); System.out.println(password); System.out.println(address); return NONE; }
封装表单数据的三种方式:
1 属性封装
public class TypeFZDemoActoin extends ActionSupport{ /** * 属性封装表单数据 * @return */ private String username; private String password; private String address; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String execute(){ System.out.println("username:"+username+"password:"+password+"address:"+address); return NONE; }
2模型驱动封装
public class ModelDrivernDemoAction extends ActionSupport implements ModelDriven<User>{ //实例化实体类 private User user=new User(); public String execute(){ System.out.println(user.toString()); return NONE; } @Override public User getModel() { // TODO Auto-generated method stub return user; } }
3.表达式封装
public class BiaoDaShiFZDemoAction extends ActionSupport { //声明实力类 private User user; //创建他的setget方法 public User getUser() { return user; } public void setUser(User user) { this.user = user; } public String execute(){ System.out.println(user.toString()); return NONE; } }
模型驱动封装与表达式封装的区别:
模型封装只能封装单个对象 表达式封装可以封装多个对象
将表单数据封装到list和map集合当中
1.list
public class FZListDemoAction extends ActionSupport { //声明实力类所存储的集合 将数据封装到不同的实体类中 list中 private List<User> list; /** * @return the list */ public List<User> getList() { return list; } /** * @param list the list to set */ public void setList(List<User> list) { this.list = list; } public String execute(){ for (User user : list) { System.out.println(user.toString()); } return NONE; } }
前端该这样写
密码:<input type="password" name="list[1].password"/> 地址:<input type="text" name="list[1].address"/> 姓名:<input type="text" name="list[0].username"/> 密码:<input type="password" name="list[0].password"/> 地址:<input type="text" name="list[0].address"/> -->
2.map
public class FZMapDemoAction extends ActionSupport { private Map<String,User> map; /** * @return the map */ public Map<String, User> getMap() { return map; } /** * @param map the map to set */ public void setMap(Map<String, User> map) { this.map = map; } public String execute(){ Set<String> keys=map.keySet(); for (String string : keys) { System.out.println(map.get(string)); } return NONE; }
前端页面
姓名:<input type="text" name="map['one'].username"/> 密码:<input type="password" name="map['one'].password"/> 地址:<input type="text" name="map['one'].address"/> 姓名:<input type="text" name="map['two'].username"/> 密码:<input type="password" name="map['two'].password"/> 地址:<input type="text" name="map['two'].address"/>
one two没有固定要这样写,写其他的也可以
(3)
什么是值栈 ?他有什么用?该怎么用?
值栈相当于域对象 。用来存放数据 用法在后面讲到
ognl表达式:
ognl不是struts2的一部分而是独立的项目 经常和struts2的标签一起使用
servlet与action的区别
servlet:在第一次访问的时候创建 ,只创建一次
action:每次访问都创建,创建多次
值栈的存储位置
每个action对象中有且只有一个值栈对象 (存储在action对象当中) 值栈对象中有acition对象的引用
怎么获取值栈对象
public class GetValueStackDemoAction extends ActionSupport{ /** * 验证每次访问action都将创建一个action对象 */ public GetValueStackDemoAction(){ System.out.println("action对象被创建。。。。"); } /** * 验证一个action对象中只有一个值栈对象 */ public String execute(){ //获得值栈对象 //首先得到ActionContext对象 ActionContext context=ActionContext.getContext(); //通过方法得到值栈对象 ValueStack vs=context.getValueStack(); ValueStack vs1=context.getValueStack(); //只要比较地址(因为得到的都是值栈对象 ,如果两个对象不相同只是对象的引用(也就是地址)不同而已)如果地址相同则为一个对象 System.out.println(vs==(vs1)); return "success"; } }
值栈的内部结构:
root和context两部分组成
root为栈 机构 context为map集合结构
struts2标签的<s:debug></s:debug>可查看值栈结构
向值栈中放入数据 3种方式
1.值栈对象的set方法
public String execute(){ //获得ActoinContext对象 ActionContext context=ActionContext.getContext(); ValueStack vs=context.getValueStack(); vs.set("aa", "你好"); vs.push("bb"); return "success"; }
2.值栈对象的push方法
3.action定义变量 然后设置其get方法
//声明字符串 private String method; // public String getMethod() { return method; } public String execute(){ method="sbsbsbsbsb"; return "success"; }
//创建实体类对象可以new也可以不new private User user=new User(); //创建get方法 public User getUser() { return user; } public String execute(){ //给对象赋值 user.setAddress("上海"); user.setPassword("123"); user.setUsername("付鹏鹏"); return "success"; }
private List<User> list=new ArrayList<User>(); public List<User> getList() { return list; } public String execute(){ HttpServletRequest req=ServletActionContext.getRequest(); req.setAttribute("req", "nihao"); User user=new User(); user.setUsername("李飞"); user.setAddress("北京"); user.setPassword("123"); User user1=new User(); user1.setUsername("李飞"); user1.setAddress("北京"); user1.setPassword("123"); list.add(user); list.add(user1); return "success"; }
取值栈当中的数据
<%--<!-- <!--查看值栈结构和值<s:debug> 不能使用html注释标签来注释struts2标签要使用jsp注释标签--> --> --%> <s:debug></s:debug> <%-- <s:property value="method"/> <s:property value="[0].top"/> --%> 取对象的值: <br/> <s:property value="user.username"/> <s:property value="user.password"/> <s:property value="user.address"/> <br/> <br/> 取list集合中的值 3中方式: <br/> 第一中: <br/> <s:property value="list[0].username"/> <s:property value="list[0].password"/> <s:property value="list[0].address"/> <br/> <s:property value="list[1].username"/> <s:property value="list[1].password"/> <s:property value="list[1].address"/> <br/> <!-- 第一种有弊端 必须要知道list集合中对象的个数 不能够进行大规模的得到数据 --> 第二种: <br/> <!--遍历集合 --> <s:iterator value="list"> <s:property value="username"/> <s:property value="password"/> <s:property value="address"/> <br/> </s:iterator> <br/> 第三种: <br/> <s:iterator value="list" var="user"> <s:property value="#user.username"/> <s:property value="#user.password"/> <s:property value="#user.address"/> <br/> </s:iterator> <br/> <s:iterator value="list" var="user"> <s:textfield name="username" value="%{#request.req}"></s:textfield> </s:iterator> </body>
增强request的getAttribute方法
1:如果域中有值就取到返回
2:如果域中没有值就去值栈中寻找值然后放入域中 进行取值
在strut2标签当中使用ognl表达式 如果直接在struts2表单标签当中使用ognl表达式将不能识别必须使用
%{#request.req}才能识别
(4)拦截器
介绍两个思想:
1.aop思想:不经过修改源代码进行功能的扩张
2.责任链模式:有多个操作每次操作完之后进行类似放行的操作
拦截器执行的时机
在action对象创建之后方法调用之前
拦截器是什么?有什么用?怎么用?
拦截器其实就是功能的集合 就是封装了许多的功能 用来实现一些功能
struts2当中有许多的拦截器 不是所有的拦截器都会执行 只会执行默认的拦截器
拦截器和过滤器的区别:
过滤器:理论上可以过滤任何内容
拦截器:只可以拦截action
自定义拦截器:
常用的方式继承MethodFilterInterceptor类
复写其方法
在action中和 拦截器的关系
1.在要拦截的action的package中声明拦截器
2.在action标签中使用拦截器
3.这样使用会出现一个问题
使用了自定义的拦截器默认的拦截器将不会执行 手动使用默认的拦截器
在一些情况中 必须先要执行action的方法 但是拦截器使他永远不会被调用 所以需要在自定义的拦截器中需要配置不拦截方法
<param name="excludeMethods">add,aaa(方法的名称)</param>
struts常用的标签
<body> <!-- struts标签 表单标签 --> <s:form> <s:textfield name="username" label="用户名"></s:textfield> <s:password name="password" label="密码"></s:password> <s:radio list="{'男','女'}" name="sex" label="性别"></s:radio>
//值和文本不相同的时候 <s:radio list="#{'nv':'女','nan':'男 '}" name="sex1" label="性别"></s:radio> <s:checkboxlist list="{'吃饭','吃屎','游泳'}" name="love" label="爱好"></s:checkboxlist> <s:checkboxlist list="#{'吃饭':'吃屎','吃屎':'吃饭' }" name="love1" label="爱好"></s:checkboxlist> <s:select list="{'小鸡巴','惠琳菲'}" name="aa" label="不好"></s:select> <s:select list="#{'小鸡巴':'惠琳菲','惠琳菲':'小鸡巴' }" name="aaa" label="你好"></s:select> <s:file name="dd" label="上传文件件"></s:file> <s:hidden name="bb" label="不好"></s:hidden> <tr><td><div align="right"><input type="submit" value="提交"></div></td><td><div align="right"><input type="reset" value="重置"></div></td></tr> </s:form> </body>