struts2是什么
概念
struts2使用优势
自动封装参数
参数校验
结果的处理(转发|重定向)
国际化
显示等待页面
表单的防止重复提交
struts2具有更加先进的架构以及思想
struts2的历史
struts2与struts1区别就是技术上没有什么关系.
struts2的前身时webwork框架.
搭建struts2框架
1.导包
2.书写Action类
package com.stevezong.struts2;
public class HelloAction {
public String hello() {
System.out.println("hi stevezong");
return "success" ;
}
}
3.书写src/struts.xml
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
4.将struts2核心过滤器配置到web.xml
5.写 jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
Hello,Stevezong
6.测试
http://127.0.0.1:8080/struts2/hello/HelloAction
struts2访问流程&struts2架构
http://127.0.0.1:8080/struts2/hello/HelloAction
hello/HelloAction->
过滤器 ->
核心配置文件->
hello->
package namespace="hello" ->
HelloAction ->
action name="HelloAction" ->
class="com.stevezong.struts2.HelloAction"->
反射 创建 action 对象->
调用method="hello" hello这个方法->
return "success"->
找 result name="success"的结果->
配置详解
struts.xml配置
<--
name 属性 标识结果处理的名称 与action方法的返回值对应
type 属性 指定调用那个哪一个result类来处理结果 默认使用转发
标签提 填写页面的相对路径
-->
struts2常量配置
struts2默认常量配置位置
/org/apache/struts2/default.properties
修改struts2常量配置(方式先后也是加载顺序)
方式1:src/struts.xml ***一般都是在这里配置
...
...
...
方式2:在src下创建struts.properties
...
struts.i18n.encoding=UTF-8
...
方式3:在项目的web.xml中
xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
顺序
常量配置
struts.i18n.encoding=UTF-8
struts.action.extension=action,,
struts.devMode = false
struts2配置的进阶
动态方法调用
方式1
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
package com.stevezong.struts2;
public class UserAction {
public String add() {
System.out.println("addUser");
return "success";
}
public String deleteDemo() {
System.out.println("deleteUser");
return "success";
}
public String updateDemo() {
System.out.println("updateUser");
return "success";
}
public String findDemo() {
System.out.println("findUser");
return "success";
}
}
http://127.0.0.1:8080/struts2/user/UserAction
http://127.0.0.1:8080/struts2/user/UserAction!
http://127.0.0.1:8080/struts2/user/UserAction!updateDemo
http://127.0.0.1:8080/struts2/user/UserAction!add
!方法名
方式2
http://127.0.0.1:8080/struts2/user/UserAction
http://127.0.0.1:8080/struts2/user/UserAction_
http://127.0.0.1:8080/struts2/user/UserAction_updateDemo
http://127.0.0.1:8080/struts2/user/UserAction_add
struts2中的默认配置
action method 的默认是 execute
没有写 就去找这个方法
action class 的默认是com.opensymphony.xwork2.ActionSupport
没有写 就用这个class
result name 的默认是 success
没有写 就去找这个
result type 的默认是 dispatcher
没有写,就是用转发
default-action-ref name="defaultAction"
如果找不到包下的action, 会使用一个defaultAction 作为默认action
action类详解
Action类的书写方式
方式1 少用
创建一个类 可以是POJO 不用继承任何父类 也不需要实现任何接口
public class Demo{
public String add(){
}
}
方式2
实现一个接口 Action 接口预制了一写字符串
package com.stevezong.struts2;
import com.opensymphony.xwork2.Action;
public class DemoAction implements Action{
//没什么作用,放着就可以就是提供一个规范
public String execute() throws Exception {
return null;
}
}
方式3 常用
继承一个类 ActionSupport
package com.stevezong.struts2;
import com.opensymphony.xwork2.ActionSupport;
public class DemoAction extends ActionSupport{
/**
*
*/
private static final long serialVersionUID = 1L;
}
结果跳转方式
转发
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
重定向
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
转发到Action
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
Demo3Action
/da
重定向到Action
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
Demo3Action
/da
Demo4Action
/da
访问servletAPI方式
原理
通过ActionContext *****
Java:
package com.stevezong.struts2;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class Demo6Action extends ActionSupport{
@Override
public String execute() throws Exception {
//session 域
Map
session.put("name", "session");
Map
application.put("name", "application");
//=====================================================================================
//不推荐使用原生的request域
String key = "request";
Map
// 推荐
ActionContext.getContext().put("name", "request");
//=====================================================================================
System.out.println("execute5");
return super.execute();
}
}
JSP:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
request:${ requestScope.name }
session:${sessionScope.name }
application: ${applicationScope.name }
XML:
通过ServletActionContext
package com.stevezong.struts2;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class Demo7Action extends ActionSupport {
@Override
public String execute() throws Exception {
// 不推荐
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
ServletContext servletContext = ServletActionContext.getServletContext();
HttpSession session = request.getSession();
System.out.println("execute7");
return super.execute();
}
}
通过实现接口方式
package com.stevezong.struts2;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import com.opensymphony.xwork2.ActionSupport;
public class Demo8Action extends ActionSupport implements ServletRequestAware, ServletResponseAware {
// 实现不同的XXXXAware接口 重写 setxxx方法
private HttpServletRequest request;
private HttpServletResponse response;
@Override
public String execute() throws Exception {
System.out.println("execute8");
return super.execute();
}
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}
}
如何获得参数
1、第一种
1、jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
2、java
package com.stevezong.struts2;
import com.opensymphony.xwork2.ActionSupport;
public class Demo9Action extends ActionSupport {
private String name;
@Override
public String execute() throws Exception {
// 如何获得参数
System.out.println("name参数的值" + name);
System.out.println("execute9");
return "success";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3、xml
扩展
strutsMVC
Action生命周期
1.每次请求到来时,都会创建一个新的Action实例
2.Action是线程安全的.可以使用成员变量接收参数
属性驱动获得参数
1、给action 添加一个属性
1、java
package com.stevezong.struts2;
import java.util.Date;
import com.opensymphony.xwork2.ActionSupport;
public class Demo9Action extends ActionSupport {
private String name;
//自动类型装换,8大基本类型和包装类
private Integer age;
//支持特定的类型字符串转换为Date yyyy-MM-dd
private Date br;
@Override
public String execute() throws Exception {
// 如何获得参数
System.out.println("name参数的值" + name);
System.out.println("age参数"+age);
System.out.println("br的参数"+br);
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 getBr() {
return br;
}
public void setBr(Date br) {
this.br = br;
}
}
2、jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
对象驱动(jsp中注意)
1创建一个User 类
2、Action中 private User user;
3、修改jsp中 name 的值为 user.xxx
1、java
package com.stevezong.struts2;
import com.opensymphony.xwork2.ActionSupport;
import com.stevezong.struts2.domain.User;
public class Demo9Action extends ActionSupport {
private User user;
@Override
public String execute() throws Exception {
// 如何获得参数
System.out.println(user);
return "success";
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
2、java
package com.stevezong.struts2.domain;
import java.util.Date;
public class User {
private String name;
private Integer age;
private Date br;
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 getBr() {
return br;
}
public void setBr(Date br) {
this.br = br;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + ", br=" + br + "]";
}
}
3、jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
模型驱动
1实现一个ModelDriven 接口 有一个泛型就是你要接受的类
2、private User user = new User();
3、实现 接口的方法 格式固定
public User getModel() {
return user;
}
1、
package com.stevezong.struts2;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.stevezong.struts2.domain.User;
public class Demo9Action extends ActionSupport implements ModelDriven
private User user = new User();
@Override
public String execute() throws Exception {
// 如何获得参数
System.out.println(user);
return "success";
}
public User getModel() {
return user;
}
}
2、
package com.stevezong.struts2.domain;
import java.util.Date;
public class User {
private String name;
private Integer age;
private Date br;
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 getBr() {
return br;
}
public void setBr(Date br) {
this.br = br;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + ", br=" + br + "]";
}
}
3、jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
集合类型参数封装
list
1、java
package com.stevezong.struts2;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
public class Demo9Action extends ActionSupport {
private List
@Override
public String execute() throws Exception {
// 如何获得参数
System.out.println(list);
return "success";
}
public List
return list;
}
public void setList(List
this.list = list;
}
}
2、jsp list 可以指定下标
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
map
1、java
package com.stevezong.struts2;
import java.util.Map;
import com.opensymphony.xwork2.ActionSupport;
public class Demo9Action extends ActionSupport {
private Map
@Override
public String execute() throws Exception {
// 如何获得参数
System.out.println(map);
return "success";
}
public Map
return map;
}
public void setMap(Map
this.map = map;
}
}
2、jsp 结果:{br=3, name=1, age=2}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
OGNL表达式
OGNL:对象视图导航语言. ${user.addr.name} 这种写法就叫对象视图导航.
OGNL不仅仅可以视图导航.支持比EL表达式更加丰富的功能.
使用OGNL准备工作
导包
struts2 的包中已经包含了.所以不需要导入额外的jar包
代码准备
OGNL 表达式
OGNLContext Ognl上下文对象
ROOT Context
放任何对象那个未做root 都可以
Map
语法
基本取值
赋值
调用方法
调用静态方法
创建对象(List,Map)
package com.stevezong.struts2;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
import com.stevezong.struts2.domain.User2;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
public class Demo1 {
@Test
public void fun1() throws Exception {
// 准备 ROOT
User2 user = new User2("stevezong", 18);
// 准备Context
Map
context.put("user1", new User2("steve", 17));
context.put("user2", new User2("zong", 18));
// 准备OGNLContext
OgnlContext oc = new OgnlContext();
oc.setRoot(user);
oc.setValues(context);
// 书写OGNL
//取出root中的user对象的name属性和age属性
String name = (String) Ognl.getValue("name", oc,oc.getRoot());
Integer age = (Integer) Ognl.getValue("age", oc,oc.getRoot());
System.out.println(name+":"+age);
// 书写OGNL
//取出Context中的 #从context中取 user1 获取那个 .name 获取那个属性
String name1 = (String) Ognl.getValue("#user1.name", oc,oc.getRoot());
Integer age1 = (Integer) Ognl.getValue("#user1.age", oc,oc.getRoot());
System.out.println(name1+":"+age1);
// 书写OGNL
//root 赋值
Ognl.getValue("name='zongsteve'", oc,oc.getRoot());
String name2 = (String) Ognl.getValue("name", oc,oc.getRoot());
System.out.println("name2:"+name2);
// 书写OGNL
//Context 赋值
Ognl.getValue("#user1.name='zong'", oc,oc.getRoot());
String name3 = (String) Ognl.getValue("#user1.name", oc,oc.getRoot());
System.out.println("name3:"+name3);
// 书写OGNL
//调用Root的get set方法
Ognl.getValue("setName('steve')", oc,oc.getRoot());
String name4 = (String) Ognl.getValue("getName()", oc,oc.getRoot());
System.out.println("name4:"+name4);
// 书写OGNL
//调用Context的get set方法
Ognl.getValue("#user1.setName('steve')", oc,oc.getRoot());
String name5 = (String) Ognl.getValue("#user1.getName()", oc,oc.getRoot());
System.out.println("name5:"+name5);
// 书写OGNL
//调用静态方法@加类的全限定名@方法名(参数)
String str = (String) Ognl.getValue("@com.stevezong.struts2.TestUtil@echo('hi stevezong')", oc,oc.getRoot());
System.out.println("str:"+str);
// 书写OGNL
//创建list对象
Integer size = (Integer) Ognl.getValue("{'stevezong','steve','zong'}.size()", oc,oc.getRoot());
//获取list中的对象
String name6 = (String) Ognl.getValue("{'stevezong','steve','zong'}[0]", oc,oc.getRoot());
//获取list中的对象
String name7 = (String) Ognl.getValue("{'stevezong','steve','zong'}.get(1)", oc,oc.getRoot());
System.out.println("size:"+size);
System.out.println("name6:"+name6);
System.out.println("name7:"+name7);
// 书写OGNL
//创建map对象
Integer size2 = (Integer) Ognl.getValue("#{'name':'stevezong','age':'18'}.size()", oc,oc.getRoot());
String name8 = (String)Ognl.getValue("#{'name':'stevezong','age':'18'}['name']", oc,oc.getRoot());
Integer age2 = (Integer)Ognl.getValue("#{'name':'stevezong','age':18}.get('age')", oc,oc.getRoot());
System.out.println("size2:"+size2);
System.out.println("name8:"+name8);
System.out.println("age2:"+age2);
}
}
package com.stevezong.struts2.domain;
public class User2 {
private String name;
private Integer 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 "User2 [name=" + name + ", age=" + age + "]";
}
public User2() {
super();
}
public User2(String name, Integer age) {
super();
this.name = name;
this.age = age;
}
}
OGNL与Struts2的结合
结合原理
Ognl 表达式要想运行 要有 OGNLContext Struts2 就提供了一个OGNLContext 不过名字换成了 ValueStack
ValueStack中的两部分
Root 放了一个栈
Context 放的是ActionContext(数据中心)
栈原理
栈是由ArrayList模拟的
栈中的两个方法的实现
访问栈中属性的特点.由上到下
查看值栈中两部分内容(使用DEBUG标签)
Root
默认情况下,栈中放置当前访问的Action对象
Context
Context部分就是ActionContext数据中心
struts2与ognl结合体现
参数接收
如何获得值栈对象,值栈对象与ActionContext对象是互相引用的
配置文件中
语法:${ognl表达式}
${name}
就会从 当前的Action对象的中查找 name这个属性
struts2标签
扩展:request对象的getAttribute方法
查找顺序
自定义拦截器
架构
拦截器创建
创建方式1 实现一个 接口 Interceptor
package com.stevezong.struts2;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class MyInterceptor implements Interceptor{
//拦截器的生命周期 随项目的启动而创建 随项目的关闭而销毁
//销毁方法
public void destroy() {
}
//初始化方法
public void init() {
}
//拦截方法
public String intercept(ActionInvocation invocation) throws Exception {
return null;
}
}
创建方式2 继承一个 类AbstractInterceptor 帮助我们写好了 init方法 和 destroy方法
package com.stevezong.struts2;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class MyInterceptor2 extends AbstractInterceptor{
@Override
public String intercept(ActionInvocation invocation) throws Exception {
return null;
}
}
创建方式3
package com.stevezong.struts2;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
public class MyInterceptor3 extends MethodFilterInterceptor{
//功能 定制拦截器拦截的方法
//定制哪些方法需要拦截
//定制哪些方法不需要拦截
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
return null;
}
}
拦截器api
放行
前后处理
不放行,直接跳转到一个结果页面
不执行后续的拦截器以及Action,直接交给Result处理结果.进行页面跳转
拦截器配置
步骤1:注册拦截器
步骤2:配置拦截器栈
步骤3:指定包中默认拦截器栈
如何定制拦截方法
全局结果集
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
add,del
package com.stevezong.struts2;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
public class MyInterceptor3 extends MethodFilterInterceptor{
//功能 定制拦截器拦截的方法
//定制哪些方法需要拦截
//定制哪些方法不需要拦截
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
//前处理
System.out.println("1");
//放行
invocation.invoke();
System.out.println("2");
//后处理
return "success";
}
}
package com.stevezong.struts2;
import com.opensymphony.xwork2.ActionSupport;
public class Demo3 extends ActionSupport{
@Override
public String execute() throws Exception {
System.out.println("execute");
return "success";
}
public String add() throws Exception {
System.out.println("Demo3add");
return "success";
}
public String del() throws Exception {
System.out.println("Demo3del");
return "success";
}
public String update() throws Exception {
System.out.println("Demo3update");
return "success";
}
public String find() throws Exception {
System.out.println("Demo3find");
return "success";
}
}
struts2标签(了解)
标签体系'
struts2标签结构
控制标签
数据标签
表单标签
非表单标签
在action中添加错误信息
取出错误信息
异常 配置