目录

一、Struts2框架执行流程

二、Struts2的快速入门

1.导入jar包

2.配置web.xml文件

3.配置struts.xml文件

4.创建Action来完成逻辑操作

三、Struts2配置详解

Struts2配置文件加载顺序

struts.xml文件配置介绍

package配置

action配置

result配置

扩展

常量配置

四、Struts2的Action详解

Action类创建方式(三种)

Action的访问方式

五、Struts2框架封装数据

属性驱动

模型驱动

小结

六、Struts2中获取Servlet API

ServletActionContext获取

采用注入方式

OGNL表达式

单独使用OGNL来完成示例

七、valueStack 值栈

valueStack介绍

valueStack内部结构

获取ValueStack

ActionContext是什么

valueStack操作---存储数据

手动向valueStack存储数据

Struts2框架自动向valueStack中存储数据

valueStack操作---获取数据

El表达式可以从valueStack中获取信息

Ognl表达式中特殊字符

八、Interceptor拦截器

Interceptor拦截器

Interceptor作用与自定义Interceptor

小结

九、Struts2文件上传

上传案例

注意事项

十、Struts2框架使用Ajax的方式

使用HttpServletResponse响应数据

使用strtus2框架的json插件来完成ajax操作

十一、Struts2注解开发

快速入门

其他注解


Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。

Struts2=struts1+webwork

一、Struts2框架执行流程

  1. 当通过浏览器发送一个请求
  2. 会被StrutsPrepareAndExecuteFilter拦截
  3. 会调用strtus2框架默认的拦截器(interceptor)完成部分功能
  4. 在执行Action中操作
  5. 根据Action中方法的执行结果来选择来跳转页面Resutl视图

Strtus2的默认拦截器(interceptor)它们是在struts-default.xml文件中配置 注意:这上xml文件是在strtus-core.jar包中,默认的拦截器是在defaultStack中定义的。

二、Struts2的快速入门

  1. 导入相关的jar文件
  2. 需要在web.xml文件中配置StrutsPrepareAndExecuteFilter
  3. 配置struts.xml文件
  4. 创建Action来完成逻辑操作

1.导入jar包

如果我们只是创建一个简单的项目的话,不需要将它的lib包下的所有的jar文件copy到项目中,而是使用其中的一部分。

2.配置web.xml文件

在web.xml文件中配置StrutsPrepareAndExecuteFilter。一般管StrutsPrepareAndExecuteFilter 叫做前端控制器(核心控制器),只有配置了这个filter我们的strtus2框架才能使用。

<filter><!-- filter-name    可以随便写 --><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.配置struts.xml文件

jsp页面的代码

<form action="${ pageContext.request.contextPath }/LoginAction" method="post">账号:<input type="text" name="username"><br/>密码:<input type="password" name="password"><br/><input type="submit" value="LOGIN">
</form>
<s:debug/>
复制代码

struts.xml文件对应配置

<struts><constant name="struts.devMode" value="true"></constant><package name="default" namespace="/" extends="struts-default"><action name="LoginAction" class="com.lbb.strus2.action.LoginAction" method="login"><result name="success" type="redirect">/success.jsp</result><result name="failer">/failter.jsp</result></action>
</package></struts>
复制代码

4.创建Action来完成逻辑操作

public class LoginAction {private String username;private String password;
/*......提供属性对应的get/set方法......
*/public String login() {System.out.println(username+"   "+password);if("tom".equals(username)&&"123".equals(password)){return "success";}else{return "failer";}}}
复制代码

三、Struts2配置详解

Struts2配置文件加载顺序

通过以下步骤可以找到加载配置文件源代码的位置

ps:我也不知道为什么只有123567,没有4

  1. 第一个加载的是default.properties文件 位置:strtus2-core.jar包 org.apache.struts2包下 作用:主要是声明了struts2框架的常量
  2. 第二个加载的是一批配置文件 Strtus-default.xml 位置:struts2-corl.jar 作用:声明了interceptor result bean Strtus-plugin.xml 位置:在strtus2的插件包中 作用:主要用于插件的配置声明 Strtus.xml 位置:在我们自己的工程中 作用:用于我们自己工程使用strtus2框架的配置
  3. 第三个加载的是自定义的strtus.properties 位置:都是在自己工程的src下 作用:定制常量
  4. 第四自定义配置提供 第五加载的是web.xml配置文件 主要是加载strtus2框架在web.xml文件中的相关配置. (项目最开始加载的就是web.xml,这里是指在前四个配置文件加载完成后,又返回来重新加载一次这个配置文件)
  5. 第六 bean相关配置

(这里的加载是指从硬盘加载到内存并进行部分的读取,而在一个请求中进行的加载是指在内存中读取配置文件)

struts.xml文件配置介绍

<package name="default" namespace="/" extends="struts-default"><action name="LoginAction" class="com.lbb.strus2.action.LoginAction" method="login"><result name="success" type="redirect">/success.jsp</result><result name="failer">/failter.jsp</result></action>
</package>
复制代码

package配置

  1. name属性 作用:定义一个包的名称,它必须唯一。
  2. namespace属性 作用:主要是与action标签的name属性联合使用来确定一个action 的访问路径
  3. extends属性 作用:指定继承自哪个包。一般值是strtus-default strtus-default包是在strtus-default.xml文件中声明的。
  4. abstruct属性 它代表当前包是一个抽象的,主要是用于被继承 <package name="struts-default" abstract="true">

action配置

  1. name属性 作用:主要是与package的namespace联合使用来确定一个action的访问路 径
  2. class属性 作用:用于指示当前的action类
  3. method属性 作用:用于指示当前的action类中的哪个方法执行

result配置

它主要是用于指示结果视图

  1. name属性 作用是与action类的method方法的返回值进行匹配,来确定跳转路径
  2. type属性 作用是用于指定跳转方式(默认是请求转发)

关于路径跳转问题,它的name属性是与action中的方法的返回值进行对比的。

它的type属性可以取哪些值?

默认值是dispatcher 它代表的是请求转发。针对于jsp页面 redirect 它代表的是重定向 针对于jsp页面 chain 它类似于请示转发,只不过它是针对于action跳转. redirectAction 它类似于重定向 针对于action 关于路径跳转的配置 可以直接在<package>下创建全局的result

扩展

关于action配置中的class与method的默认值以及result中的name与type 默认值问题.

<action name="LoginAction"><result>/success.jsp</result>
</action>
复制代码

原因:strtus-default.xml文件中配置 <default-class-ref class="com.opensymphony.xwork2.ActionSupport" /> 它的作用就是当一个请求来时,如果查找不到指定的class及对应的method就会执行ActionSupport类中的execute方法。在这个类的execute方法中默认返回的是”success”。也就是说,result的name属性默认值是success,默认的跳转方式是请求转发 dispatcher。

常量配置

在default.properties文件中定义了struts2框架常用常量。 那么,我们怎样可以设置常量。

  1. 可以在src下创建一个strtus.properties配置文件
  2. 可以在web.xml文件中配置
  3. 可以直接在strtus.xml文件中定义常量 (推荐)

注意:后加载的配置文件中的常量会将先加载的常量覆盖

<!-- 声明常量 -->
<constant name="struts.i18n.encoding" value="UTF-8"></constant>
<!-- 可以帮助我们解决post请求乱码问题 -->
<!-- <constant name="struts.action.extension" value="action"></constant> -->
<!-- 指定访问strtsu2框架路径的扩展名 -->
<constant name="struts.devMode" value="true"></constant>
<!-- 配置这项后,它会提供更加详细报错信息,以及在struts.xml文件修改后不在需要重启服务器 -->
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
<!-- 开启动态方法调用 -->
复制代码

四、Struts2的Action详解

Struts2中的action,主要是完成业务逻辑操作。Action替代在servlet中完成的作用。

Action的学习主要有两点

  1. 如何创建一个struts2的action
  2. 如果访问一个struts2的action

Action类创建方式(三种)

  1. 创建一个pojo类 Pojo(plani Ordinary java object)简单的java对象 Pojo类就是没有实现任何接口没有继承任何类 优点:无耦合 缺点:所有的功能都要自己完成
  2. 创建一个类实现一个Action接口 com.opensymphony.xwork2.Action

在Action接口中定义了五个常量,一个execute方法。 五个常量:它们是默认的五个结果视图<result name="">: ERROR : 错误视图 INPUT: 它是struts2框架中interceptor中发现问题后会访问的一个视图 LOGIN:它是一个登录视图,可以在权限操作中使用 NONE:它代表的是null,什么都不做(也不会做跳转操作) SUCCESS:这是一个成功视图 优点:耦合度低 缺点:还是需要自己来完成功能 3. 创建一个类继承ActionSupport类 com.opensymphony.xwork2.ActionSupport ActionSupport类也实现了Action接口。 我们在开发中一般会使用这种方案: 优点:具有丰富的功能,例如 表单校验 错误信息设置 国际化 缺点:耦合度高

Action的访问方式

  1. 直接通过标签来配置,通过method来指定访问的方法,如果method没有,默认访问的是execute方法。
  2. 简化的action访问方式,可以使用*通配符来访问。
<action name="Book_*" class="com.lbb.strus2.action.BookAction" method="{1}"></action>
<action name="*_*" class="com.lbb.strus2.action.{1}Action" method="{2}"></action>
复制代码
public class BookAction extends ActionSupport{public void add() {System.out.println("bookadd");}public void del() {System.out.println("bookdel");}public void update() {System.out.println("bookupdate");}public void find() {System.out.println("bookfind");}
}
public class ProductAction extends ActionSupport{public void add() {System.out.println("productadd");}public void del() {System.out.println("productdel");}public void update() {System.out.println("productupdate");}public void find() {System.out.println("productfind");}
}
复制代码

这种方式的缺点:不建议使用过多的号,它带来程序阅读障碍,不便于理解 使用来简化操作方案,它对名称规范必须进行一个统一。

扩展--动态方法调用

<!-- localhost:8080/工程名/Book_add!add -->
<constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>
<!-- 开启动态方法调用 -->
复制代码

注意:对于strtus2的动态方法调用,要想使用我们必须配置一个常量来开启动态方法调用。 个人不建议使用动态方法调用(出现过漏洞!)

五、Struts2框架封装数据

在action中如果获取请求参数? 主要有两类三种方法

属性驱动

第一种,直接在action类中提供与请求参数匹配属性,提供get/set方法。

public class LoginAction {private String username;private String password;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 login() {System.out.println(username+"   "+password);if("tom".equals(username)&&"123".equals(password)){return "success";}else{return "failer";}}
}
复制代码

第二种,在action类中创始一个javaBean,对其提供get/set ,在请求时页面上要进行修改, 例如 user.username user.password ,要使用ognl表达式

public class LoginAction2{private User user = new User();public User getUser() {return user;}public void setUser(User user) {this.user = user;}public String login() {System.out.println(user.getUsername()+"   "+user.getPassword());if("tom".equals(user.getUsername())&&"123".equals(user.getPassword())){return "success";}else{return "failer";}}
}
复制代码

以上两种方式的优缺点: 第一种:比较简单,在实际操作我们需要将action的属性在赋值给模型(javaBean) 去操作 第二种:不需要在直接将值给javaBean过程,因为直接将数据封装到了javaBean 中。它要求在页面上必须使用ognl表达式,就存在页面不通用问题。

模型驱动

步骤:

  1. 让Action类要实现一个指定接口ModelDriven
  2. 实例化模型对象(就是要new出来javaBean)
  3. 重写getModel方法将实例化的模型返回。 对于模型驱动它与属性驱动对比,在实际开发中使用比较多,模型驱动缺点,它只能对 一个模型数据进行封装。
public class LoginAction3 implements ModelDriven<User>{private User user = new User();public User getModel() {return user;}public String login() {System.out.println(user.getUsername()+"   "+user.getPassword());if("tom".equals(user.getUsername())&&"123".equals(user.getPassword())){return "success";}else{return "failer";}}
}
复制代码

小结

六、Struts2中获取Servlet API

在action类中获取request response session...对象,有两种方案。

ServletActionContext获取

采用注入方式

Struts2框架在运行时,请求会被StrutsPrepareAndExecuteFilter拦截,会根据请求,去 strtus.xml文件中查找到匹配的action,在action执行前,会走一些interceptor。

默认执行的拦截器是struts-default.xml文件中定义的,在默认执行的拦截器中有一个

<interceptor name="servletConfig" "lass="org.apache.struts2.interceptor.ServletConfigInterceptor"/>
......
<interceptor-ref name="servletConfig"/>
复制代码

查看一下ServletConfigInterceptor源代码。以下是部分源代码

ServletRequestAware, 实现这个接口可以获取HttpServletRequest ServletResponseAware ,实现这个接口可以获取HttpServletResponse ServletContextAware 实现这个接口可以获取ServletContext

OGNL表达式

OGNL是Object-Graph Navigation Language(对象图导航语言)的缩写,它是一种功能强大的表达式语言,通过它简单一致的表达式语法,可以存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。

Strtsu2框架内置了OGNL OGNL本身也是一个项目,它是可以单独使用。

OGNL作用 支持对象的操作,调用对象的方法 支持静态成员访问 支持赋值操作与表达串联 访问OGNL上下文,访问ActionContext 操作集合对象。

单独使用OGNL来完成示例

OGNL三要素: 1.表达式 2.OgnlContext 上下文 3. Root 根

支持对象操作

// 表达式 OgnlContext 上下文 Root 根
@Test
public void test1() throws OgnlException {// String s="hello";// int length = s.length();// 1.获取上下文对象OgnlContextOgnlContext context = new OgnlContext(); // 它就是一个java.util.Map// 2.操作Object root = context.getRoot();Object value = Ognl.getValue("'hello'.length()", context, root);System.out.println(value);
}
复制代码

支持静态成员访问

// 1.获取上下文对象OgnlContext
OgnlContext context = new OgnlContext(); // 它就是一个java.util.Map
// 2.操作
Object value = Ognl.getValue("@java.lang.Math@random()", context, context.getRoot());
Object value2 = Ognl.getValue("@java.lang.Math@PI", context, context.getRoot());
System.out.println(value);
System.out.println(value2);
复制代码

访问Ognl上下文

@Test
public void test3() throws Exception {// 1.获取上下文对象OgnlContextOgnlContext context = new OgnlContext(); // 它就是一个java.util.Map// 2.向上下文中存储数据context.put("username", "tom");// 3.操作Object value = Ognl.getValue("#username", context, context.getRoot());System.out.println(value);
}@Test
public void test4() throws Exception {// 1.获取上下文对象OgnlContextOgnlContext context = new OgnlContext(); // 它就是一个java.util.Map// 2.存储数据Map<String, String> map = new HashMap<String, String>();map.put("username", "fox");context.put("username", "tom");// 将map存储到context的根中context.setRoot(map);// 3.操作Object value = Ognl.getValue("username", context, context.getRoot());System.out.println(value);
}
复制代码

如果从根中获取数据,不需要添加#号,如果不是从根中获取,需要#。

如果root中存了一个对象,可以直接访问这个对象的属性。如果是存在上下文context中的对象则需要通过”对象.属性”的形式访问

操作集合

// 操作集合
@Test
public void test5() throws OgnlException {// 1.获取上下文对象OgnlContextOgnlContext context = new OgnlContext(); // 它就是一个java.util.Map//2.操作Object value = Ognl.getValue("{'hello','good','well'}", context,context.getRoot()); //相录于创建了一个List集合context.setRoot(value);      System.out.println(Ognl.getValue("[0]",context, context.getRoot()));      //Object value2 = Ognl.getValue("#{'username':'tom','age':20}", context,context.getRoot()); //相当于创建了一个Map集合        //System.out.println(value2.getClass());
}//支持表达式赋值及串联
@Test
public void test6() throws OgnlException {// 1.获取上下文对象OgnlContextOgnlContext context = new OgnlContext(); // 它就是一个java.util.Map        //2.操作      Object value = Ognl.getValue("#{'username':'tom','age':20}", context,context.getRoot()); //相当于创建了一个Map集合   context.setRoot(value);     Object value2 = Ognl.getValue("username='张三',age=45", context,context.getRoot());System.out.println(value2);
}
复制代码

Strtus2框架中如何使用ognl表达式

在struts2框架中我们使用ognl表达式的作用是从valueStack中获取数据。我们在struts2框架中可以使用ognl+valueStack达到在页面(jsp)上来获取相关的数据。要想在jsp页面上使用ognl表达式,就需要结合struts2框架的标签 <%@taglib prefix="s" uri="/struts-tags"%> <s:property value="表达式"> 来使用.

七、valueStack 值栈

valueStack介绍

我们使用valueStack的主要目的是为我将我们action中产生的数据携带到页面上,也就是说valueStack它就是一个容器。

在Struts2框架中将valueStack设计成一个接口。 com.opensymphony.xwork2.util.ValueStack

我们主要使用的是它的实现类 com.opensymphony.xwork2.ognl.OgnlValueStack。

当客户端向我们发送一个请求,服务器就会创始一个Action来处理请求,struts2中的action是一个多例,每一次请求都会有一个新的action对应。所以它不存在线程安全问题。 一个valueStack对应一个action,valueStack贯穿整个action的生命周期。 rquest------Action------ValueStack

struts2框架将valueStack保存在request中。 在Dispatcher.class中有以下代码

valueStack内部结构

valueStack主要有两部分组成: CompoundRoot:它就是一个ArrayList 它主要存储的是action的相关数据 Map<String,Object> context:就是一个Map Context中主要存储了一些引用,这个引用主要是关于web开发中相关信息 pameters :请求参数 request:请求对象中所有属性 session:会话对象中所有属性 application:application对象中的所有发展 以上都是Map

在struts2框架中我们通过ognl表达式来获取valueStack中数据,没有使用#就会从CompoundRoot中获取数据,如果使用#来获取,这时就会从context中来获取。

获取ValueStack

一种方式:可以直接通过request对象来获取

ValueStack stack = (ValueStack) ServletActionContext.getRequest().getAttribute("ServletActionContext.STRUTS_VALUESTACK_KEY");
复制代码

二种方式:使用ActionContext来获取

ValueStack stack = ActionContext.getContext().getValueStack();
复制代码

ActionContext是什么

ActionContext它是action上下文,strtus2框架它使用actionContext来保存Action在执行过程中所需要的一些对象,例如 session, application…

ActionContext的获取 是通过它的静态方法getContext()得到。 Struts2会根据每一次的http请求来创建对应的ActionContext,它是与当前线程绑定的。

每一次请求,就是一个线程,对应着一个request,每一次请求,会创建一个Action,每一个action对应一个ActionContext.每一次请求也对应着一个valueStack. request---ActionContext----Action-----ValueStaci它们都对应着一次请求(一个线程). valueStack与ActionContext本质上是可以获取

ActionContext里存有一个valueStack的context,而valueStack的context里存有valueStack的一个Root

valueStack操作---存储数据

手动向valueStack存储数据

// 向valueStack存储数据
stack.set("name", "tom");
// 底层会创建一个HashMap,保存数据,在将hashMap存储到root中。
stack.push("hello word!");
// 向root中存储
复制代码

Struts2框架自动向valueStack中存储数据

每次请求,访问action,这个对象会存储到valueStack中。 在DefaultActionInvocation的init方法内

在ModelDrivernInterceptor中会将模型对象存储到valueStack中。

valueStack操作---获取数据

在jsp页面中如何从valueStack中获取数据的问题,让我们通过以下代码和运行结果来分析。

<body>
<s:property value="[0].top"/>
<br/>
<s:property value="username2"/>
<br/>
<s:property value="username"/>
<br/>
<s:property value="password"/>
<br/>
<s:property value="user.username"/>
<br/>
<s:property value="model.username"/>
<br/>
<s:property value="loginMsg"/>
<s:actionerror />
<form action="${ pageContext.request.contextPath }/LoginAction" method="post">账号:<input type="text" name="username"><br/>密码:<input type="password" name="password"><br/><input type="submit" value="LOGIN">
</form>
<s:debug/>
</body>
复制代码

输入用户名和密码:tom:111

public class LoginAction extends ActionSupport implements ModelDriven<User>{private String username2 = "rose";public String getUsername2(){return "Rose";}private User user = new User();public User getModel() {return user;}public User getUser() {return user;}public String login(){ if("tom".equals(user.getUsername())&&"123".equals(user.getPassword())){System.out.println(user);ServletActionContext.getRequest().getSession().setAttribute("user", user);return "success";}else{ActionContext actionContext = ActionContext.getContext();ValueStack valueStack = actionContext.getValueStack();user = new User();user.setUsername("fox");user.setPassword("456");valueStack.set("username","jack");valueStack.set("loginMsg","用户名或密码错误!");valueStack.push("hello word!");return "failer";}    }  public class User {private String username;private String password;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;}@Overridepublic String toString() {return "User [username=" + username + ", password=" + password + "]";}
}
复制代码

结果图如下

分析结论:

  1. com.lbb.struts2.action.LoginAction代表Action本身
  2. com.lbb.struts2.domain.User代表的是最初始的接受的model实例对象,而LoginAction中的model和user代表的是LoginAction类中user属性这个引用。如果在类的方法中user属性没有被重新赋值,那么他们指向同一个实例对象,如果user属性被重新赋值,则com.lbb.struts2.domain.User仍指向最初的model对象,而LoginAction中的model和user则指向新的实例对象。从com.lbb.struts2.domain.User中取属性直接写属性名就行,参考第四行结果,如果要从com.lbb.struts2.action.LoginAction的对象中取属性,要写上对象名,参考第五行,第六行结果。 可以参考下图进行理解
  3. com.lbb.struts2.domain.User以上的数据就是我们手动向添加valueStack中添加的数据
  4. 从valueStack中取数据的顺序是从上向下取第一个找到的对应的元素。例如手动设置的和com.lbb.struts2.domain.User中都有的时候,取手动存的。没有手动存的时候取com.lbb.struts2.domain.User中的。参考第三行和第四行的数据。

El表达式可以从valueStack中获取信息

为什么el表达式可以从valueStack中获取数据? 在org.apache.struts2.dispatcher.StrutsRequestWrapper中

Struts2框架对request进行了增强,重写了getAttribute方法,如果在request域中查找不到数据,就会在valueStack中获取。

Ognl表达式中特殊字符

OGNL是通常要结合Struts 2的标志一起使用。主要是#、%和$这三个符号的使用

#号:它是从非root中获取数据 %用于强制是否要解析ognl表达式

<%request.setAttribute("username", "tom");session.setAttribute("password", "123");%><h1>#号用法</h1><s:property value="#request.username" /><br><s:property value="#session.password" /><br><!-- localhost:8080/struts2-day02/ognl3.jsp?username=tom --><s:property value="#parameters.username"/><h2>%号用法</h2><s:property value="%{#request.itcast}"/><br> <!-- 会解析成ognl --><s:property value="%{'#request.itcast'}"/><br> <!-- 不会解析ognl --><s:debug />
复制代码

$它主要是在配置文件中来获取valueStack中数据

<action name="vs" class="com.lbb.action.ValueStackAction">   <result name="success" type="redirect">/ognl2.jsp?username=${model.username}</result>
</action>
复制代码

八、Interceptor拦截器

Interceptor拦截器

Struts2中的interceptor它是基于spring aop思想,而aop思想它本质上是通过动态代理来实现。我们strtus2的拦截器它主要是拦截Action的操作,在action的执行前或执行后进行一些其它的功能操作。

以下是struts2的执行流程图

执行的过程 当我们发送请求访问Action时,会被StrutsPrepareAndExecuteFilter拦截 在其doFilter方法内执行了 execute.executeAction(request, response, mapping)。

这个代码执行后,dispatcher.serviceAction(request, response, mapping), serviceAction方法执行。

在这个方法执行过程中会创建Action代理对象

ActionProxy proxy = getContainer().getInstance(ActionProxyFactory.class).createActionProxy(namespace, name, method, extraContext, true, false);
复制代码

通过proxy去执行了proxy.execute(),在execute方法内return invocation.invoke()。

invocation它是ActionInvocation一个对象。 在invoke方法内

会去加载我们的配置文件,将配置文件中所有的interceptor得到进行遍历。 在struts-default.xml文件中定义了默认加载的拦截器栈 defaultStack

在每一个拦截器的interceptor方法内,又调用了DefaultActionInvocation的invoke方法,其实就是递归调用。

Interceptor作用与自定义Interceptor

我们使用intercep[tor可以在action执行前后进行处理工作。例如,完成权限控制。

问题:如何定义Interceptor

所有的Interceptor都要实现一个接口 com.opensymphony.xwork2.interceptor.Interceptor

在配置文件中声明Interceptor

我们也可以将多个interceptor封装成一个stack

可以在Action的配置中引入自己的interceptor 在使用时name也可以引入一个interceptor stack.

注意:当我们显示的引入了一个自定义的Interceptor,那么默认的defaultStack就不会在导入,需要手动导入

<!-- 声明 -->
<interceptors><interceptor name="myInterceptor" class="cn.lbb.utils.MyInterceptor"><param name="includeMethods">showProduct</param><param name="excludeMethods">addProduct</param></interceptor><interceptor-stack name="myStack"><interceptor-ref name="myInterceptor"/><interceptor-ref name="defaultStack"></interceptor-ref> </interceptor-stack>
</interceptors>   <action name="product_*" class="cn.lbb.action.ProductAction" method="{1}"><result name="success">/product.jsp</result><result name="login">/login.jsp</result><interceptor-ref name="myStack"/>
</action>
复制代码

我们在struts.xml文件中配置action时,可以使用*通配置符,这时它可以处理多个方法,你指定的interceptor只想拦截某一个方法,可以使用Interceptor接口的一个实现类来完成操作MethodFilterInterceptor

小结

注意:在实际开发中,我们一般会让action去继承ActionSupport类,这样可以使用父类提供的对于错误操作的处理this.addActionError("错误信息!") 在struts2中处理简单的信息(字符串)

this.addActionError("错误信息!")
this.addFieldError(fieldName,errorMessage)
this.addActionMessage(amessage)
复制代码

第一个:一般用于逻辑业务操作 第二个:对接收的参数进行格式校验,是否满足格式 第三个:普通信息 获取

<s:actionerror/>
<s:fielderror/>
<s:actiommessage/>
复制代码

要想在页面上展示集合信息可以使用<s:iterator>标签来完成

<s:iterator value="ps"><tr><td><s:property value="name" /></td><td><s:property value="price" /></td><td><s:property value="count" /></td></tr>
</s:iterator><s:iterator value="ps" var="p"><tr><td><s:property value="p.name" /></td><td><s:property value="p.price" /></td><td><s:property value="p.count" /></td></tr>
</s:iterator>
复制代码

九、Struts2文件上传

浏览器端注意事项

表单提交方式method=post 表单中必须有一个组件 表单中必须设置enctype=”multipart/form-data”

服务器端

Commons-fileupoad.jar包完成。

Struts2框架使用一个fileupload的interceptor来完成文件上传

上传案例

<form action="${ pageContext.request.contextPath }/upMany" enctype="multipart/form-data" method="post">
<input type="file" name="upload">
<input type="file" name="upload">
<input type="submit" value="上传">
</form>
复制代码
public class UploadActionMany extends ActionSupport{
//   extends ActionSupport private File[] upload;private String[] uploadContentType;private String[] uploadFileName;
/*提供对应的set/get方法
*/public String upload(){System.out.println(3);String path = ServletActionContext.getServletContext().getRealPath("/upload");try {for (int i = 0; i < upload.length; i++) {File file = new File(path,uploadFileName[i]);FileUtils.copyFile(upload[i], file);}} catch (IOException e) {e.printStackTrace();}System.out.println(4);return null;}
}
复制代码

注意事项

<!-- 开发模式 -->
<constant name="struts.devMode" value="true"></constant>
<!-- 设置文件上传的大小限制 -->
<constant name="struts.multipart.maxSize" value="40971520"></constant>
<action name="upMany" class="com.lbb.struts2.action.UploadActionMany" method="upload"><!-- 文件上传出错后的视图 --><result name="input">/error.jsp</result><interceptor-ref name="fileUpload"><!-- <param name="maximumSize"></param> --><!-- 设置每一个文件的单独的上传大小 --><!-- <param name="allowedTypes"></param> --><!-- 文件的mime类型 --><param name="allowedExtensions">txt,jpg,bmp</param><!-- 设置允许的后缀名 --></interceptor-ref><interceptor-ref name="defaultStack"></interceptor-ref>
</action>
复制代码

input接受错误信息

<s:actionerror/>
<s:fielderror/>
复制代码

十、Struts2框架使用Ajax的方式

使用HttpServletResponse响应数据

在struts2框架中可以获取HttpServletResponse对象,就可以通过response来完成将数据(json)响应到浏览器过程。

使用strtus2框架的json插件来完成ajax操作

首先要导入插件包struts2-json-plugin-2.3.24.jar

我们怎样使用struts2提供的json插件

  1. 将我们自己配置文件中的<package extends=”json-default”>.
  2. Action的返回视图<result name=”” type=”json”>
  3. 因为我们配置了上面两步,那么struts2框架就会将valueStack中的栈顶元素转换成json响应到浏览器

案例

<script type="text/javascript">
$(function(){$("#productaa").toggle(function(){$.post("/day03_struts2/struts2_ajax/showProduct",{},function(data){$("#product").append("<tr><td>商品名</td><td>价格</td></tr>")$.each(data,function(i,n){$("#product").append("<tr><td>"+n.name+"</td><td>"+n.price+"</td></tr>")});},"json");},function(){$("#product").html("");});
});
</script>
<body>
<a href="javascript:void(0)" id="productaa">查看商品</a>
<div>
<table id="product" border="1"></table>
</div>
</body>
复制代码
<package name="default3" namespace="/struts2_ajax" extends="json-default"><action name="showProduct" class="com.lbb.struts2.action.ProductAction" method="show"><result name="success" type="json"><!-- 设置生成数据时的根 --><!-- 没有设置root前返回的json结构   ps:[{},{}]设置root它的根为ps后的返回的json结构  [{},{}]--><param name="root">list</param><!-- 生成json数据时包含或不包含属性 --><param name="excludeProperties">\[\d+\]\.releaseDate</param><!-- <param name="includeProperties">ps\[\d+\]\.id,ps\[\d+\]\.name</param> --></result></action></package>
复制代码
public String show(){List<Product> list = new ArrayList<Product>();/*......*/list.add(product1);list.add(product2);list.add(product3);ActionContext.getContext().getValueStack().set("list",list);return "success";}
复制代码
public class Product {private int id;private String name;private double price;private Date releaseDate;
//  @JSON(serialize=false)    生成json数据时忽略属性public Date getReleaseDate() {return releaseDate;}/*对应的set/get方法*/
}
复制代码

十一、Struts2注解开发

想使用struts2的注解,我们必须单独在导入一个jar包。它是在strtus2的2.1版本后引入。struts2-convention-plugin-2.3.24.jar

我们在action类中定义了注解,strtus2框架怎样识别它们 我们必须查看插件包中的配置,会发现 <constant name="struts.convention.package.locators" value="action,actions,struts,struts2"/> 是在action,actions,struts,struts2这样的包下扫描注解

快速入门

案例 登录页面

<body>
<s:actionerror/>
<form action="${ pageContext.request.contextPath }/user/login" method="post">
用户名<input type="text" name="username"><br/>
密码<input type="password" name="password"><br/>
<input type="submit" value="登录">
</form>
</body>
复制代码

登录Action

@Namespace("/user")
@ParentPackage("struts-default")
public class UserAction extends ActionSupport implements ModelDriven<User>{private User user = new User();@Overridepublic User getModel() {return user;}@Action(value="login",results = { @Result(name="success",type="redirect",location="/product2.jsp"),@Result(name="error",location="/login.jsp") })public String login(){IUserService userService = new UserServiceImpl();try {user = userService.login(user);if(user!=null){ServletActionContext.getRequest().getSession().setAttribute("user",user);return SUCCESS;}else{addActionError("用户名或密码错误!");return ERROR;}} catch (SQLException e) {e.printStackTrace();throw new RuntimeException();}}
}
复制代码

商品展示页面

<script type="text/javascript" src="/day04_struts2_exam/js/jquery-1.8.3.js"></script>
<body>
<script type="text/javascript">
$(function(){$("#productaa").toggle(function(){$.post("${pageContext.request.contextPath}/product/productlist",{},function(data){if(data.type=="1"){$("#product").append("<tr><td>商品名</td><td>价格</td></tr>")$.each(data.list,function(i,n){$("#product").append("<tr><td>"+n.name+"</td><td>"+n.price+"</td></tr>")});}else{alert(data.message);}},"json");},function(){$("#product").html("");});
});
</script>
<a href="javascript:void(0)" id="productaa">查看商品</a>
<div>
<table id="product" border="1"></table>
</div>
</body>
复制代码

定义一个被商品Action继承的包,声明权限控制拦截器

<package name="base" namespace="/" extends="struts-default"><interceptors><interceptor name="myInterceptor" class="com.lbb.struts2.interceptor.MyInterceptor"></interceptor><interceptor-stack name="myStack"><interceptor-ref name="myInterceptor"></interceptor-ref><interceptor-ref name="defaultStack"></interceptor-ref></interceptor-stack></interceptors></package>
复制代码

商品展示Action

@Namespace("/product")
@ParentPackage("base")
public class ProductListAction {@Action(value="productlist",interceptorRefs={@InterceptorRef("myStack")})public void showProduct2(){ServletActionContext.getResponse().setContentType("text/html;charset=UTF-8");IProductService productService = new ProductServiceImpl();try {Result<Product> result = new Result<>();result.setType(1);List<Product> list = productService.findAll();result.setList(list);String resultString = JSONObject.toJSONString(result);System.out.println(resultString);ServletActionContext.getResponse().getWriter().println(resultString);} catch (Exception e) {e.printStackTrace();}}
}
复制代码

权限控制拦截器

public class MyInterceptor extends MethodFilterInterceptor{@Overrideprotected String doIntercept(ActionInvocation arg0) throws Exception {ServletActionContext.getResponse().setContentType("text/html;charset=UTF-8");User user = (User) ServletActionContext.getRequest().getSession().getAttribute("user");if(user!=null){return arg0.invoke();}else{Result<Product> result = new Result<>();result.setMessage("权限不足!");String resultString = JSONObject.toJSONString(result);ServletActionContext.getResponse().getWriter().println(resultString);return null;}}
}
复制代码

其他注解

@Actions 用在方法上

@Actions({@Action(value = "testAction",results = {@Result(location="/success.jsp")}),@Action(value = "testAction2",results = {@Result(location="/success.jsp")})
})
public String demo1(){......
}
复制代码

@Results 用在类上,相当于全局结果视图

@Results( { @Result(name = "global", location = "/global.jsp") })
public class demo1 extends ActionSupport {  @Action(value = "test1", results = { @Result(name = "success", location = "/success.jsp"),  @Result(name = "failure", location = "/fail.jsp") })  public String execute() {  if (...) {  return "failure";  } else if (...) {  return "success";  } else {  return "global";  }  }  @Action("test2")  public String demo2() {  return "global";  }
}
复制代码

java struts2 框架 入门简介相关推荐

  1. 车联网大数据框架_大数据基础:ORM框架入门简介

    作为大数据开发技术者,需要掌握扎实的Java基础,这是不争的事实,所以对于Java开发当中需要掌握的重要框架技术,也需要有相应程度的掌握,比如说ORM框架.今天的大数据基础分享,我们就来具体讲一讲OR ...

  2. Java Spring框架入门详解教程【多测师_何sir】

    Spring框架入门详解教程 spring概述 spring结构 spring IOC spring DI spring概述 Spring是一个非常活跃的开源框架, 它是一个基于IOC和AOP来构架多 ...

  3. JAVA三大框架入门(学习)

    一.基本概念 了解框架的定位可以帮助我们更好的找到学习的切入点 1.Spring 依赖注入(DI)又称为控制反转(IOC),通常来说,当某个角色需要另一个角色才能正常运行时,通常是由调用者来创建被调用 ...

  4. java struts2国际化代码下载_【Java框架】java struts2框架中页面表示国际化的方法 - 思诚科技...

    在struts2框架中,前端页面表示国际化的实现更加简单.简单的应用struts2框架提供的支持国际化的表达式即可快速方便的进行页面的国际化的实现.如何做呢?本文以英文和中文为例进行说明. 1,自定义 ...

  5. struts2框架入门

    1.struts2的工作原理和文件结构 2.struts2核心文件 struts核心文件包括: 1)web.xml 2)struts.xml 3)struts.properties 3.Action搜 ...

  6. Java Collection框架入门

    容器在Java语言开发中有着非常重要的作用,Java提供了多种类型的容器来满足开发的需要,容器不仅在面试笔试中也是非常重要的一个知识点,在实际开发的过程中也是经常会用到.因此,对容器的掌握是非常有必要 ...

  7. Java爬虫框架WebMagic简介及使用

    一.介绍 ​ webmagic的是一个无须配置.便于二次开发的爬虫框架,它提供简单灵活的API,只需少量代码即可实现一个爬虫.webmagic采用完全模块化的设计,功能覆盖整个爬虫的生命周期(链接提取 ...

  8. Java基础 -IO入门简介、文件操作、与IO流分类简述

    文章目录 IO流入门概念 文件概念 什么是文件 文件流 文件常用操作 创建文件对象相关构造器和方法 创建文件案例 注意 获取文件相关信息 目录的操作和文件删除 delete mkdir.mkdirs ...

  9. java web框架struts,JavaWeb框架_Struts2_(五)-----Struts2的标签库

    1.Struts2的标签库 1.1 Struts2标签库概述 Struts2的标签库可以分为以下3类:用户界面标签.非用户界面标签.AJAX标签; 2.1.1 Struts2标签库的分类和使用 1.  ...

最新文章

  1. 斯坦福团队开发智能盲杖,搭载激光雷达,可探测障碍规划路线,完全开源可在家DIY...
  2. JSP简单练习-获取表单数据
  3. 阿里云Tech Insight 企业迁云实战专场强势来袭!
  4. 企业私有云部署im,视频服务
  5. View绘制--onMeasure() 、onLayout()
  6. android qq空间 sdk,Android中使用腾讯的SDK完成分享图文到qq空间
  7. Unity3D之移植学习笔记:移植到Android平台
  8. utilities(C++)——Null类的设计
  9. python 求点集的距离矩阵
  10. 阶段5 3.微服务项目【学成在线】_day02 CMS前端开发_16-CMS前端工程创建-导入系统管理前端工程...
  11. Windows 下使用 Mingw32-make 来执行 Makefile示例
  12. 汇编语言:协处理器浮点指令:FILD
  13. 基于PTPX的功耗分析
  14. quicktime ogv_Windows的QuickTime已死,应卸载以确保安全
  15. html5下拉菜单清除样式,如何取消下拉菜单格式
  16. 整理了上千个Python类库,简直太酷啦!
  17. Photoshop使用背景图层的方法
  18. 记录一下uni-app开发中遇到的坑
  19. CCF201803-4-棋局评估
  20. The Devil Wears Prada-18

热门文章

  1. 在MSN、QQ群、论坛上提问的决窍
  2. channel rabbitmq 配置_「喵咪MQ(2)」RabbitMQ单机模式使用
  3. 5G 承载网 — 三大运营商承载网技术的演进方向
  4. Python 是一门怎样的语言
  5. KeilKill.bat删除keil编译生成的过程文件
  6. Altium Designer旋转PCB、PCB中绕某点旋转
  7. 数据结构-双向链表的实现
  8. 如何让云存储更好为“我”所用
  9. XenApp/XenDesktop 7.11中对于视频、图片、文字的优化的说明
  10. Spring 5.0 GA版本发布,支持JDK9及反应式编程