目录
- 1 快速入门
- 2 Struts2通俗访问流程
- 3 Struts框架流程
- 4 Struts2配置详情——Struts2核心配置
- 5 Struts2配置详情——Struts2常量配置
- 6 配置进阶——动态方法调用
- 7 配置进阶——默认值
- 8 Action创建方式
- 9 结果处理方式
- 10 获得ServletAPI
- 11 参数获得
- 12 集合类型封装
- 13 OGNL
- 14 Struts与ognl结合原理:
- 15 ognl表达式与Struts2框架结合体现–参数赋值
- 16 ognl表达式与Struts2框架结合体现-配置文件中使用ognl
- 17 拦截器API
- 18 拦截器配置(参考struts-default.xml)
- 19 Struts2标签
快速入门
1. 导包
把解压后的Struts2压缩包解压,在解压后的文件夹中找到apps文件夹中的struts2-blank.war文件,把后缀改为zip后解压,在解压后文件夹中找到WEB-INF/lib,把lib文件夹里的全部jar包导入。
2. 创建Action类
在项目src文件夹下,创建一个包com.benz.action,其下创建类HelloAction(命名规则:XxxxAction)
1 2 3 4 5 6 7 8 |
public class HelloAction { public String hello() { System.out.println("hello world!!!!"); return "success"; } } |
3. 创建Struts配置文件
在src文件夹下创建struts.xml文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <package name="hello" namespace="/hello" extends="struts-default" > <!-- action元素:配置action类 name属性: 决定了Action访问资源名. class属性: action的完整类名 method属性: 指定调用Action中的哪个方法来处理请求 --> <action name="HelloAction" class="com.benz.action.HelloAction" method="hello" > <!-- result元素:结果配置 name属性: 标识结果处理的名称.与action方法的返回值对应. type属性: 指定调用哪一个result类来处理结果,默认使用转发. 标签体:填写页面的相对路径 --> <result name="success" type="dispatcher" >/hello.jsp</result> </action> </package> </struts> |
4.在web.xml中为Struts配置filter
这步很重要,也是最后一步,因为Struts的功能实现都是基于filter过滤器的,如果不为Struts配置filter过滤器,那么Struts是不会工作的。
在项目webroot下WEB-INF中的web.xml文件中配置如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<!-- 配置常量 <context-param> <param-name>struts.i18n.encoding</param-name> <param-value>UTF-8</param-value> </context-param> --> <!-- 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> |
5. 创建一个hello.jsp
1 2 3 4 5 6 7 8 9 10 11 12 |
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h1>hello world!!!!</h1> </body> </html> |
6.发布工程
发布工程,并在浏览器访问http://localhost:8080/项目名/hello/HelloAction
出现hello world!!!!。到此入门成功。
Struts2通俗访问流程
Struts框架流程
AOP思想
传统:每个servlet都有“解决乱码”这代码
AOP:把“解决乱码”放到filter里,所有servlet都接入到filter
Struts2配置详情——Struts2核心配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<!-- package:将Action配置封装.就是可以在Package中配置很多action. name属性: 给包起个名字,起到标识作用.随便起.不能其他包名重复. namespace属性:给action的访问路径中定义一个命名空间 extends属性: 继承一个 指定包(必写项) abstract属性:包是否为抽象的; 标识性属性.标识该包不能独立运行.专门被继承 --> <package name="hello" namespace="/hello" extends="struts-default" > <!-- action元素:配置action类 name属性: 决定了Action访问资源名. class属性: action的完整类名 method属性: 指定调用Action中的哪个方法来处理请求 --> <action name="HelloAction" class="cn.itheima.a_hello.HelloAction" method="hello" > <!-- result元素:结果配置 name属性: 标识结果处理的名称.与action方法的返回值对应. type属性: 指定调用哪一个result类来处理结果,默认使用转发. 标签体:填写页面的相对路径 --> <result name="success" type="dispatcher" >/hello.jsp</result> </action> </package> <!-- 引入其他struts配置文件 --> <include file="cn/itheima/b_dynamic/struts.xml"></include> |
其中,extends=”struts-default”,继承了Struts的默认配置,struts-default的文件路径,在Struts核心包struts2-core-2.3.24.jar包下的一个struts-default.xml文件
如果想给每个action单独配置一个struts.xml,(其实执行的只有src下的那个struts.xml)那么需要到src下的那个struts.xm中使用include引入其他struts.xml
Struts2配置详情——Struts2常量配置
Struts2默认常量配置为default.properties,位置为Struts核心包struts2-core-2.3.24.jar包下的一个包org.apache.struts2下的default.properties文件。
修改Struts2常量配置(方式先后也是加载顺序,以最后加载为准)
方式一:修改src下的struts.xml文件(重点掌握)
方式二:在src下创建struts.properties
方式三:修改web.xml文件
常用常量配置
1 2 3 4 5 6 7 8 9 10 11 |
<!-- i18n:国际化. 解决post提交乱码 --> <constant name="struts.i18n.encoding" value="UTF-8"></constant> <!-- 指定访问action时的后缀名 http://localhost:8080/struts2/hello/HelloAction.do --> <constant name="struts.action.extension" value="action"></constant> <!-- 指定struts2是否以开发模式运行 1.热加载主配置.(不需要重启即可生效) 2.提供更多错误信息输出,方便开发时的调试 --> <constant name="struts.devMode" value="true"></constant> |
配置进阶——动态方法调用
建立包com.benz.dynamic,其中创建类Demo1Action.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public class Demo1Action { public String add() { System.out.println("添加用户"); return "success"; } public String delete() { System.out.println("删除用户"); return "success"; } public String update() { System.out.println("修改用户"); return "success"; } public String find() { System.out.println("查询用户"); return "success"; } } |
方式一:配置struts.xml文件
访问路径:http://localhost:8080/struts2/dynamic/dynamicDemo1!add
格式:action名!方法名,如:dynamicDemo1!add
方式二:通配符方式(常用)
访问方式:
配置进阶——默认值
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<struts> <package name="default" namespace="/default" extends="struts-default" > <!-- 找不到包下的action,会使用Demo2Action作为默认action处理请求 --> <default-action-ref name="Demo2Action"></default-action-ref> <!-- method属性:默认execute --> <!-- result的name属性: 默认success --> <!-- result的type属性: 默认dispatcher 转发 --> <!-- class属性: 默认com.opensymphony.xwork2.ActionSupport --> <action name="Demo2Action" > <result >/hello.jsp</result> </action> </package> </struts> |
Action创建方式
方式一:创建一个类.可以是POJO
1 2 3 4 5 6 |
//方式1: 创建一个类.可以是POJO //POJO:不用继承任何父类.也不需要实现任何接口. //使struts2框架的代码侵入性更低. public class Demo3Action { } |
方式二:实现一个接口Action
1 2 3 4 5 6 7 8 9 10 11 |
//方式2: 实现一个接口Action // 里面有execute方法,提供action方法的规范. // Action接口预置了一些字符串.可以在返回结果时使用.为了方便 public class Demo4Action implements Action { @Override public String execute() throws Exception { return null; } } |
方式三:继承一个类.ActionSupport
1 2 3 4 5 6 7 8 9 |
//不要导错包 import com.opensymphony.xwork2.ActionSupport; //方式3: 继承一个类.ActionSupport // 帮我们实现了 Validateable, ValidationAware, TextProvider, LocaleProvider . //如果我们需要用到这些接口的实现时,不需要自己来实现了. public class Demo5Action extends ActionSupport{ } |
结果处理方式
创建包com.benz.result,创建如下类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
public class Demo1Action extends ActionSupport { public String execute() throws Exception { System.out.println("Demo1Action!"); return SUCCESS; } } public class Demo2Action extends ActionSupport { public String execute() throws Exception { return SUCCESS; } } public class Demo3Action extends ActionSupport { public String execute() throws Exception { System.out.println("Demo3Action!"); return SUCCESS; } } public class Demo4Action extends ActionSupport { public String execute() throws Exception { System.out.println("Demo4Action!"); return SUCCESS; } } |
方式一:转发
http://localhost:8080/struts2/demo1action
方式二:重定向
http://localhost:8080/struts2/demo2action
方式三:转发到Action
http://localhost:8080/struts2/demo3action
方式四:重定向到Action
http://localhost:8080/struts2/demo4action
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<package name="result" namespace="/" extends="struts-default" > <!-- 转发 --> <action name="Demo1Action" class="com.benz.result.Demo1Action" method="execute" > <result name="success" type="dispatcher" >/hello.jsp</result> </action> <!-- 重定向 --> <action name="Demo2Action" class="com.benz.result.Demo2Action" method="execute" > <result name="success" type="redirect" >/hello.jsp</result> </action> <!-- 转发到Action --> <action name="Demo3Action" class="com.benz.result.Demo3Action" method="execute" > <result name="success" type="chain"> <!-- action的名字 --> <param name="actionName">Demo1Action</param> <!-- action所在的命名空间 --> <param name="namespace">/</param> </result> </action> <!-- 重定向到Action --> <action name="Demo4Action" class="com.benz.result.Demo4Action" method="execute" > <result name="success" type="redirectAction"> <!-- action的名字 --> <param name="actionName">Demo1Action</param> <!-- action所在的命名空间 --> <param name="namespace">/</param> </result> </action> </package> |
获得ServletAPI
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
//如何在action中获得原生ServletAPI public class Demo5Action extends ActionSupport { public String execute() throws Exception { //request域=> map (struts2并不推荐使用原生request域) //不推荐 Map<String, Object> requestScope = (Map<String, Object>) ActionContext.getContext().get("request"); //推荐 ActionContext.getContext().put("name", "requestTom"); //session域 => map Map<String, Object> sessionScope = ActionContext.getContext().getSession(); sessionScope.put("name", "sessionTom"); //application域=>map Map<String, Object> applicationScope = ActionContext.getContext().getApplication(); applicationScope.put("name", "applicationTom"); return SUCCESS; } } |
方式二:通过ServletActionContext
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//如何在action中获得原生ServletAPI public class Demo6Action extends ActionSupport { //并不推荐 public String execute() throws Exception { //原生request HttpServletRequest request = ServletActionContext.getRequest(); //原生session HttpSession session = request.getSession(); //原生response HttpServletResponse response = ServletActionContext.getResponse(); //原生servletContext ServletContext servletContext = ServletActionContext.getServletContext(); return SUCCESS; } } |
方式三:通过实现ServletRequestAware接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
//如何在action中获得原生ServletAPI public class Demo7Action extends ActionSupport implements ServletRequestAware { private HttpServletRequest request; public String execute() throws Exception { System.out.println("原生request:"+request); return SUCCESS; } @Override public void setServletRequest(HttpServletRequest request) { this.request = request; } } |
Jsp文件:
1 2 3 4 5 |
<body> request: ${requestScope.name}<br> session:${sessionScope.name}<br> application:${applicationScope.name}<br> </body> |
参数获得
方式一:属性驱动获得参数
JSP:
1 2 3 4 5 6 |
<form action="${pageContext.request.contextPath}/Demo8Action"> 用户名:<input type="text" name="name" /><br> 年龄:<input type="text" name="age" /><br> 生日:<input type="text" name="birthday" /><br> <input type="submit" value="提交" /> </form> |
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
//struts2如何获得参数 //每次请求Action时都会创建新的Action实例对象 public class Demo8Action extends ActionSupport { public Demo8Action() { super(); System.out.println("demo8Action被创建了!"); } //准备与参数键名称相同的属性 private String name; //自动类型转换 只能转换8大基本数据类型以及对应包装类 private Integer age; //支持特定类型字符串转换为Date ,例如 yyyy-MM-dd private Date birthday; public String execute() throws Exception { System.out.println("name参数值:"+name+",age参数值:"+age+",生日:"+birthday); return SUCCESS; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } } |
方式二:对象驱动获得参数
JSP:
1 2 3 4 5 6 |
<form action="${pageContext.request.contextPath}/Demo9Action"> 用户名:<input type="text" name="user.name" /><br> 年龄:<input type="text" name="user.age" /><br> 生日:<input type="text" name="user.birthday" /><br> <input type="submit" value="提交" /> </form> |
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
//struts2如何获得参数-方式2 public class Demo9Action extends ActionSupport { //准备user对象 private User user; public String execute() throws Exception { System.out.println(user); return SUCCESS; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } } |
方式三:模型驱动获得参数
JSP:
1 2 3 4 5 6 |
<form action="${pageContext.request.contextPath}/Demo10Action"> 用户名:<input type="text" name="name" /><br> 年龄:<input type="text" name="age" /><br> 生日:<input type="text" name="birthday" /><br> <input type="submit" value="提交" /> </form> |
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
//struts2如何获得参数-方式2 public class Demo10Action extends ActionSupport implements ModelDriven<User> { //准备user 成员变量 private User user =new User(); public String execute() throws Exception { System.out.println(user); return SUCCESS; } @Override public User getModel() { return user; } } |
User类实体:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public class User { private String name; private Integer age; private Date birthday; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Override public String toString() { return "User [name=" + name + ", age=" + age + ", birthday=" + birthday + "]"; } } |
集合类型封装
JSP:
1 2 3 4 5 6 |
<form action="${pageContext.request.contextPath}/Demo11Action" method="post" > list:<input type="text" name="list" /><br> list:<input type="text" name="list[3]" /><br> map:<input type="text" name="map['haha']" /><br> <input type="submit" value="提交" /> </form> |
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
//struts2 封装集合类型参数 public class Demo11Action extends ActionSupport { //list private List<String> list; //Map private Map<String,String> map; public String execute() throws Exception { System.out.println("list:"+list); System.out.println("map:"+map); return SUCCESS; } public List<String> getList() { return list; } public void setList(List<String> list) { this.list = list; } public Map<String, String> getMap() { return map; } public void setMap(Map<String, String> map) { this.map = map; } } |
OGNL
OGNL:对象图像导航语言 ${user.addr.name}这种写法就叫对象图像导航
OGNL不仅仅可以视图导航,支持比EL表达式更加丰富的功能。
1.导包:
2.入门:
User 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
public class User { private String name; private Integer age; public User() { super(); // TODO Auto-generated constructor stub } public User(String name, Integer age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "User [name=" + name + ", age=" + age + "]"; } } |
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@Test //准备工作 public void fun1() throws Exception{ //准备ONGLContext //准备Root User rootUser = new User("tom",18); //准备Context Map<String,User> context = new HashMap<String,User>(); context.put("user1", new User("jack",18)); context.put("user2", new User("rose",22)); OgnlContext oc = new OgnlContext(); //将rootUser作为root部分 oc.setRoot(rootUser); //将context这个Map作为Context部分 oc.setValues(context); //书写OGNL Ognl.getValue("", oc, oc.getRoot()); } |
OGNL基本语法演示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
@Test //基本语法演示 //取出root中的属性值 public void fun2() throws Exception{ //准备ONGLContext //准备Root User rootUser = new User("tom",18); //准备Context Map<String,User> context = new HashMap<String,User>(); context.put("user1", new User("jack",18)); context.put("user2", new User("rose",22)); OgnlContext oc = new OgnlContext(); oc.setRoot(rootUser); oc.setValues(context); //书写OGNL //取出root中user对象的name属性 String name = (String) Ognl.getValue("name", oc, oc.getRoot()); Integer age = (Integer) Ognl.getValue("age", oc, oc.getRoot()); System.out.println(name); System.out.println(age); } @Test //基本语法演示 //取出context中的属性值 public void fun3() throws Exception{ //准备ONGLContext //准备Root User rootUser = new User("tom",18); //准备Context Map<String,User> context = new HashMap<String,User>(); context.put("user1", new User("jack",18)); context.put("user2", new User("rose",22)); OgnlContext oc = new OgnlContext(); oc.setRoot(rootUser); oc.setValues(context); //书写OGNL //取出context中键为user1对象的name属性 String name = (String) Ognl.getValue("#user1.name", oc, oc.getRoot()); String name2 = (String) Ognl.getValue("#user2.name", oc, oc.getRoot()); Integer age = (Integer) Ognl.getValue("#user2.age", oc, oc.getRoot()); System.out.println(name); System.out.println(name2); System.out.println(age); } @Test //基本语法演示 //为属性赋值 public void fun4() throws Exception{ //准备ONGLContext //准备Root User rootUser = new User("tom",18); //准备Context Map<String,User> context = new HashMap<String,User>(); context.put("user1", new User("jack",18)); context.put("user2", new User("rose",22)); OgnlContext oc = new OgnlContext(); oc.setRoot(rootUser); oc.setValues(context); //书写OGNL //将root中的user对象的name属性赋值 Ognl.getValue("name='jerry'", oc, oc.getRoot()); String name = (String) Ognl.getValue("name", oc, oc.getRoot()); String name2 = (String) Ognl.getValue("#user1.name='郝强勇',#user1.name", oc, oc.getRoot()); System.out.println(name); System.out.println(name2); } @Test //基本语法演示 //调用方法 public void fun5() throws Exception{ //准备ONGLContext //准备Root User rootUser = new User("tom",18); //准备Context Map<String,User> context = new HashMap<String,User>(); context.put("user1", new User("jack",18)); context.put("user2", new User("rose",22)); OgnlContext oc = new OgnlContext(); oc.setRoot(rootUser); oc.setValues(context); //书写OGNL //调用root中user对象的setName方法 Ognl.getValue("setName('lilei')", oc, oc.getRoot()); String name = (String) Ognl.getValue("getName()", oc, oc.getRoot()); String name2 = (String) Ognl.getValue("#user1.setName('lucy'),#user1.getName()", oc, oc.getRoot()); System.out.println(name); System.out.println(name2); } @Test //基本语法演示 //调用静态方法 public void fun6() throws Exception{ //准备ONGLContext //准备Root User rootUser = new User("tom",18); //准备Context Map<String,User> context = new HashMap<String,User>(); context.put("user1", new User("jack",18)); context.put("user2", new User("rose",22)); OgnlContext oc = new OgnlContext(); oc.setRoot(rootUser); oc.setValues(context); //书写OGNL String name = (String) Ognl.getValue("@cn.itheima.a_ognl.HahaUtils@echo('hello 强勇!')", oc, oc.getRoot()); //Double pi = (Double) Ognl.getValue("@java.lang.Math@PI", oc, oc.getRoot()); Double pi = (Double) Ognl.getValue("@@PI", oc, oc.getRoot()); System.out.println(name); System.out.println(pi); } @Test //基本语法演示 //ognl创建对象-list|map public void fun7() throws Exception{ //准备ONGLContext //准备Root User rootUser = new User("tom",18); //准备Context Map<String,User> context = new HashMap<String,User>(); context.put("user1", new User("jack",18)); context.put("user2", new User("rose",22)); OgnlContext oc = new OgnlContext(); oc.setRoot(rootUser); oc.setValues(context); //书写OGNL //创建list对象 Integer size = (Integer) Ognl.getValue("{'tom','jerry','jack','rose'}.size()", oc, oc.getRoot()); String name = (String) Ognl.getValue("{'tom','jerry','jack','rose'}[0]", oc, oc.getRoot()); String name2 = (String) Ognl.getValue("{'tom','jerry','jack','rose'}.get(1)", oc, oc.getRoot()); /*System.out.println(size); System.out.println(name); System.out.println(name2);*/ //创建Map对象 Integer size2 = (Integer) Ognl.getValue("#{'name':'tom','age':18}.size()", oc, oc.getRoot()); String name3 = (String) Ognl.getValue("#{'name':'tom','age':18}['name']", oc, oc.getRoot()); Integer age = (Integer) Ognl.getValue("#{'name':'tom','age':18}.get('age')", oc, oc.getRoot()); System.out.println(size2); System.out.println(name3); System.out.println(age); } |
Struts与ognl结合原理:
查看值栈中两部分
Jsp代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <!-- 调试标签 --> <s:debug></s:debug> </body> </html> |
创建一个action:
1 2 3 4 5 6 7 8 9 10 |
public class Demo1Action extends ActionSupport { @Override public String execute() throws Exception { System.out.println("Demo1Action!!"); return SUCCESS; } } |
配置struts.xml
1 2 3 4 5 6 7 8 |
<struts> <package name="showvs" namespace="/" extends="struts-default" > <action name="Demo1Action" class="cn.itheima.b_showvs.Demo1Action" method="execute" > <result name="success" type="dispatcher" >/showvs.jsp</result> </action> </package> </struts> |
访问http:// localhost:8080/xxxx/Demo1Action
结果:
ROOT 值栈:
默认情况下,栈中放置当前访问的Action对象。
Context域:
stack context放置的内容
ognl表达式与Struts2框架结合体现–参数赋值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
public class User { private String name; private Integer age; public User() { super(); // TODO Auto-generated constructor stub } public User(String name, Integer age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "User [name=" + name + ", age=" + age + "]"; } } |
创建form.jsp
1 2 3 4 |
<form action="${pageContext.request.contextPath}/Demo2Action " method="post"> 用户名:<input type="text" name="name"> <input type="submit"> </form> |
创建Demo2Action
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class Demo2Action extends ActionSupport{ private User u = new User(); @Override public String execute() throws Exception { //压入栈顶 //1获得值栈 ValueStack vs = ActionContext.getContext().getValueStack(); //2将u压入栈顶 vs.push(u); System.out.println(u); return SUCCESS; } } |
配置struts.xml:
1 2 3 |
<action name="Demo2Action" class="com.benz.action.Demo2Action" method="execute" > <result name="success" type="dispatcher" >/form.jsp</result> </action> |
//1获得值栈
ValueStack vs = ActionContext.getContext().getValueStack();
//2将u压入栈顶
vs.push(u);
form.jsp输入参数后,Demo2Action接收的参数为null
因为数据压栈前要经过二十道拦截器,拦截器把数据给处理掉了,最后到这里是接收不到数据的
所以要接收数据,要把modelDriven拦截器接口实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class Demo2Action extends ActionSupport implements ModelDriven<User>{ private User u = new User(); @Override public String execute() throws Exception { System.out.println(u); return SUCCESS; } @Override public User getModel() { // TODO 自动生成的方法存根 return u; } } |
ognl表达式与Struts2框架结合体现-配置文件中使用ognl
创建action类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public class Demo3Action extends ActionSupport { private String name; @Override public String execute() throws Exception { name = "jerry";//从数据库中查询 return SUCCESS; } public String getName() { return name; } public void setName(String name) { this.name = name; } } |
struts.xml文件配置
1 2 3 4 5 6 7 8 9 10 11 |
<action name="Demo3Action" class="com.benz.action.Demo3Action" method="execute" > <result name="success" type="redirectAction" > <param name="actionName">Demo1Action</param> <param name="namespace">/</param> <!-- 如果添加的参数struts"看不懂".就会作为参数附加重定向的路径之后. 如果参数是动态的.可以使用${}包裹ognl表达式.动态取值 ${name}:从root中从上到下寻找为name的值 --> <param name="name">${name}</param> </result> </action> |
拦截器API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
//拦截器:第一种创建方式 //拦截器生命周期:随项目的启动而创建,随项目关闭而销毁 //一般有init、destroy方法,其生命周期都长,所以才有init、destroy方法 public class MyInterceptor implements Interceptor { @Override //初始化方法 public void init() { } @Override //拦截方法 public String intercept(ActionInvocation arg0) throws Exception { return null; } @Override //销毁方法 public void destroy() { } } |
1 2 3 4 5 6 7 8 9 10 11 |
//创建方式2: 继承AbstractInterceptor -> struts2的体贴 //帮我们空实现了init 和 destory方法. 我们如果不需要实现这两个方法,就可以只实现intercept方法 public class MyInterceptor2 extends AbstractInterceptor { @Override public String intercept(ActionInvocation arg0) throws Exception { return null; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
//继承:MethodFilterInterceptor 方法过滤拦截器 //功能: 定制拦截器拦截的方法. // 定制哪些方法需要拦截. // 定制哪些方法不需要拦截 public class MyInterceptor3 extends MethodFilterInterceptor{ @Override protected String doIntercept(ActionInvocation invocation) throws Exception { //前处理 System.out.println("MyInterceptor3 的前处理!"); //放行 String result = invocation.invoke(); //后处理 System.out.println("MyInterceptor3 的后处理!"); return result; } } |
拦截器配置(参考struts-default.xml)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<struts> <package name="inter" namespace="/" extends="struts-default" > <interceptors> <!-- 1.注册拦截器 --> <interceptor name="myInter3" class="cn.itcast.a_interceptor.MyInterceptor3"></interceptor> <!-- 2.注册拦截器栈 --> <interceptor-stack name="myStack"> <!-- 自定义拦截器引入(建议放在20个拦截器之前) --> <interceptor-ref name="myInter3"> <!-- 指定哪些方法不拦截 <param name="excludeMethods">add,delete</param> --> <!-- 指定哪些方法需要拦截 --> <param name="includeMethods">add,delete</param> </interceptor-ref> <!-- 引用默认的拦截器栈(20个) --> <interceptor-ref name="defaultStack"></interceptor-ref> </interceptor-stack> </interceptors> <!-- 3.指定包中的默认拦截器栈 --> <default-interceptor-ref name="myStack"></default-interceptor-ref> <action name="Demo1Action_*" class="cn.itcast.a_interceptor.Demo1Action" method="{1}" > <!-- 为Action单独指定走哪个拦截器(栈) <interceptor-ref name="myStack"></interceptor-ref>--> <result name="success" type="dispatcher" >/index.jsp</result> </action> </package> </struts> |
创建action类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public class Demo1Action extends ActionSupport { public String add() throws Exception { System.out.println("Demo1Action_add!"); return SUCCESS; } public String delete() throws Exception { System.out.println("Demo1Action_delete!"); return SUCCESS; } public String update() throws Exception { System.out.println("Demo1Action_update!"); return SUCCESS; } public String find() throws Exception { System.out.println("Demo1Action_find!"); return SUCCESS; } } |
Struts2标签
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <!-- 遍历标签 iterator --> <!-- ------------------------------------- --> <s:iterator value="#list" > <s:property /><br> </s:iterator> <!-- ------------------------------------- --><hr> <s:iterator value="#list" var="name" > <s:property value="#name" /><br> </s:iterator> <!-- ------------------------------------- --><hr> <s:iterator begin="1" end="100" step="1" > <s:property />| </s:iterator> <!-- ------------------if else elseif------------------- --><hr> <s:if test="#list.size()==4"> list长度为4! </s:if> <s:elseif test="#list.size()==3"> list长度为3! </s:elseif> <s:else> list不3不4! </s:else> <!-- ------------------property 配合ognl表达式页面取值 ------------------- --><hr> <s:property value="#list.size()" /> <s:property value="#session.user.name" /> </body> </html> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public class Demo2Action extends ActionSupport { public String execute() throws Exception { List<String> list = new ArrayList<>(); list.add("tom"); list.add("jerry"); list.add("jack"); list.add("rose"); list.add("hqy"); ActionContext.getContext().put("list", list); return SUCCESS; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <!-- struts2表单标签 --> <!-- 好处1: 内置了一套样式. --> <!-- 好处2: 自动回显,根据栈中的属性 --> <!-- theme:指定表单的主题 xhtml:默认 simple:没有主题 --> <s:form action="Demo3Action" namespace="/" theme="xhtml" > <s:textfield name="name" label="用户名" ></s:textfield> <s:password name="password" label="密码" ></s:password> <s:radio list="{'男','女'}" name="gender" label="性别" ></s:radio> <s:radio list="#{1:'男',0:'女'}" name="gender" label="性别" ></s:radio> <s:checkboxlist list="#{2:'抽烟',1:'喝酒',0:'烫头'}" name="habits" label="爱好" ></s:checkboxlist> <s:select list="#{2:'大专',1:'本科',0:'硕士'}" headerKey="" headerValue="---请选择---" name="edu" label="学历" > </s:select> <s:file name="photo" label="近照" ></s:file> <s:textarea name="desc" label="个人简介" ></s:textarea> <s:submit value="提交" ></s:submit> </s:form> <s:actionerror/> </body> </html> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class Demo3Action extends ActionSupport { private String name; public String execute() throws Exception { System.out.println(name); this.addActionError("你错了!!!!"); return SUCCESS; } public String getName() { return name; } public void setName(String name) { this.name = name; } } |