Struts2
来源:互联网 发布:网络安全法宣传图片 编辑:程序博客网 时间:2024/06/06 03:39
- MVC 和 JSP Model 2
什么是MVC?
1) M-Model 模型
模型(Model)的职责是负责业务逻辑。包含两部分:业务数据和业务处理逻辑。
在之前学习的类中,比如实体类、DAO、Service都属于模型层。
2) V-View 视图
视图(View)的职责是负责显示界面和用户交互(收集用户信息)。
属于视图的类是不包含业务逻辑和控制逻辑的JSP(如果在JSP页面中有<%%>就不能算是视
图层的类,或者JSP中有转发和或者重定向的控制逻辑也是不可以的)。
3) C-Controller 控制器
控制器是模型层M和视图层V之间的桥梁,用于控制流程。
比如我们之前项目中写的ActionServlet。 - MVC JSP Model2
之前我们写的模式被我们称之为JSP Model1,在其中我们有模型层(M),但是视图层(V)的
JSP中包含了业务逻辑或控制逻辑。JSP Model2的不同之处在于将JSP中的业务逻辑和控制逻辑全部
剔除,并全部放入控制层(C)中,JSP仅具有显示页面和用户交互的功能。
1) 所有的请求发给控制层的前端控制器(ActionServlet)
2) 前端控制器维护一个配置文件 (配置文件中指明了不同的请求和某个Action的对应关系)
3) 前端控制器可以根据请求的不同调用不同的Action
4) 控制层的Action调用Model,实现业务功能
5) 模型层DAO将请求中的数据从数据库中查出后绑定到Request对象上
6) 模型层DAO将请求转发给View层(JSP)JSP显示数据
3.拷贝Struts2的核心Jar包到WEB-INF/lib/下
基本功能核心jar 包 5个(2.1.8)struts2-core-2.1.8.1.jar(*)
Struts2核心包,是Struts 框架的“外衣”
xwork-core-2.1.6.jar(*)
Struts2核心包,是WebWork 内核。
ognl-2.7.3.jar
用来支持ognl表达式的,类似于EL表达式,功能比EL表达式强大的多。
freemarker-2.3.15.jar
freemarker 是比jsp更简单好用,功能更加强大的表现层技术,用来替代jsp的。
在Struts2中提倡使用 freemarker 模板,但实际项目中使用jsp也很多。
commons-fileupload-1.2.1.jar
用于实现文件上传功能的jar 包。
4.在web.xml 中配置Struts2的前端控制器
Struts2用Filter 实现的前端控制器(注意不是Servlet)<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<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>
</web-app>
5.Struts2提供的方便之处:
数据的自动的封装根据页面组件的name属性,自动封装到Action中对应的 name属性中。
在Jsp页面<input name=’name’ type=’text’/>
在action中会自动给属性private String name 赋值
数据的自动的传递
Action中得属性会在jsp页面可以直接用EL表达式拿到
Action中属性private String name;
在jsp页面上可以直接${name}的到对应的值
6.写struts2所需要的配置文件struts.xml
struts.xml文件告诉Struts2\请求对应的Java类注意:在编写时放在src中(编译后该文件位于WEB-INF/classes/下)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
"http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<package name="helloworld" extends="struts-default"
namespace="/day01">
<action name="welcome"
class="com.tarena.outman.WelcomeAction">
<result name="success">/jsp/welcome.jsp</result>
<result name="fail">/jsp/nameform.jsp</result>
</action>
</package>
</struts>
注:
name="helloworld"
唯一的标识,表示包名为helloworld
extends="struts-default"
继承的包的name,一般继承Struts2默认提供的struts-default包,该包中定义了很多
Struts2应用必须的组件(比如:拦截器);
该package声明的位置在struts2-core-2.1.8.jar/struts-default.xml文件中
namespace
用来设置该包中的action的地址的命名空间
namespace="/" 表示没有命名空间(后续再讲解)
访问http://localhost:8080/outman/welcome.action即可
如果namespace="day01"之后,Action地址为:
http://localhost:8080/outman/day01/welcome.action
name="welcome"
表示请求的名字为welcome(即welcome.do)
class="com.tarena.outman.WelcomeAction"
指定了对应的Action类
method="xxx"
用于指定在对应的类中要执行的方法名,该方法的返回值必须是String类型(规定)
public String xxx(){......}
如果没有method=""属性,默认执行execute()方法
该result的名称,Action返回哪一个result的name值,意味着要转发到哪一个result
所对应的JSP地址
- <package>
name="helloworld"
唯一的标识,表示包名为helloworld
extends="struts-default"
继承的包的name,一般继承Struts2默认提供的struts-default包,该包中定义了很多
Struts2应用必须的组件(比如:拦截器);
该package声明的位置在struts2-core-2.1.8.jar/struts-default.xml文件中
namespace
用来设置该包中的action的地址的命名空间
namespace="/" 表示没有命名空间(后续再讲解)
访问http://localhost:8080/outman/welcome.action即可
如果namespace="day01"之后,Action地址为:
http://localhost:8080/outman/day01/welcome.action
- <action>
name="welcome"
表示请求的名字为welcome(即welcome.do)
class="com.tarena.outman.WelcomeAction"
指定了对应的Action类
method="xxx"
用于指定在对应的类中要执行的方法名,该方法的返回值必须是String类型(规定)
public String xxx(){......}
如果没有method=""属性,默认执行execute()方法
- <result>
该result的名称,Action返回哪一个result的name值,意味着要转发到哪一个result
所对应的JSP地址
7.Action 的小结
在Struts2框架中,我们写一个Actionclass FooAction {}
一般情况下,在该类中有一个public String execute()方法
class FooAction {
public String execute() {}
}
execute()方法通过返回不同的String决定转到哪个页面
class FooAction {
public String execute() {
return "success"; //return "abc";亦可
}
}
我们为该Action添加成员变量 name
注意:
1) 只有当为成员变量添加get/set方法时,我们才称该成员变量是类的属性
2) 所有的属性都会被“带”到页面(在页面能够使用)
3) 在页面form表单中提交的信息可以赋值给属性
class FooAction {
private String name; //成员变量
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public String execute() {
return "success"; //return "abc";亦可
}
}
对与一般的Action有2种属性
1) 第1种,用来接收用户的提交 input属性
2) 第2种,用来把数据带给视图(JSP)output属性
public class ProjectListAction {
// input属性
private int page = 1;
// output属性
private List<Project> projectList;
public String execute() {
ProjectDao projectDao = new ProjectDao();
projectList = projectDao.findAll(page, 5);
return "success";
}
public int getPage() {return page;}
public void setPage(int page) {this.page = page;}
public List<Project> getProjectList() {return projectList;}
public void setProjectList(List<Project> projectList) {
this.projectList = projectList;
}
}
8.El表达式翻译为Java代码的含义
${foo.name}翻译为Java代码是out.print(foo.getName());意味着调用foo的getName()方法,而非访问foo的成员变量name(同时注意成员变量一般是私
有的,不能直接访问)
9.EL表达式是干什么用的?
EL表达式把数据从四个范围(pageContext、request、session、application)中取出来显示或者计算。EL表达式解决了Java 代码和HTML的不匹配问题(让html页面中不再有java代码)。
EL表达式用字符串表达式替换Java代码,用来表示对数据的获取或计算。
OGNL 是干什么的?
OGNL和EL相似,但功能更加强大。
OGNL 是怎么工作的?
给ognl引擎一个字符串(OGNL表达式),可以让ognl引擎去读取和设置对象的属性。
OGNL 表达式
1) 基本类型属性(包括String)
例如: id,name
2) 数组和List
例如:arry[0], list[1]
3) Map
例如:map['key'], map.key
4) 基本运算
5) 调用方法
6) 调用静态方法
7) 创建对象List,Map
创建List: {1,2,3,4,5}
创建Map: #{'one':'java','two':'javajava'}
8)关联属性(不常用,理解即可)
empList[1].name
9)投影(不常用,理解即可)
empList.{name}
10)过滤(不常用,理解即可)
empList.{?#salary>10000}
10.Ognl引擎访问对象的格式:
Ognl.getValue("OGNL表达式", root对象); //root对象是Ognl要操作的对象
Ognl.getValue("OGNL表达式", root对象); //root对象是Ognl要操作的对象
11. OGNL 引擎的基本结构
标准的Ognl 涉及到3个概念:Ognl 引擎、root对象、context对象
标准的Ognl 涉及到3个概念:Ognl 引擎、root对象、context对象
root对象:Ognl操作的对象
context对象:就是一个Map,用于存放一个和整个系统都相关的公共数据
当有了Ognl引擎,我们就可以访问各种各样的root对象(比如Foo对象、Emp对象、Dept对
象等),在访问中有一些数据是每一次访问都需要用到的,这些数据就可以保存在context对象中
context对象:就是一个Map,用于存放一个和整个系统都相关的公共数据
当有了Ognl引擎,我们就可以访问各种各样的root对象(比如Foo对象、Emp对象、Dept对
象等),在访问中有一些数据是每一次访问都需要用到的,这些数据就可以保存在context对象中
12. XWork中对OGNL 的扩展
在之前讲的Ognl的应用是通用的,接下来讲解XWork 中对Ognl做的改动。
在之前讲的Ognl的应用是通用的,接下来讲解XWork 中对Ognl做的改动。
OGNL引擎
CompoundRoot对象:在XWork 中,root对象被改为类似“栈”一样的存储空间,
在该对象空间内可以存放多个root对象;
当取数据时符合“栈”的规则,如果OGNL表达式是“name“,
在CompoundRoot从栈顶开始依次看是否有name属性...
Context(Map)对象
CompoundRoot对象:在XWork 中,root对象被改为类似“栈”一样的存储空间,
在该对象空间内可以存放多个root对象;
当取数据时符合“栈”的规则,如果OGNL表达式是“name“,
在CompoundRoot从栈顶开始依次看是否有name属性...
Context(Map)对象
13.ValueStack基本结构
Struts2将之前讲的XWork 对Ognl的扩展这一套机制封装起来,这个对象叫ValueStack。
Struts2将之前讲的XWork 对Ognl的扩展这一套机制封装起来,这个对象叫ValueStack。
Struts2在启动时,会创建一个ValueStrack 对象
当用户发送请求到对应的Action时,Struts2会把当前被请求的Action01放入CompoundRoot
对象的“栈空间”栈顶,请求结束,Action01会被清除。
(当下一次另一个请求到来时,Struts2会把该请求对应的Action02放入“栈顶”)
所以,我们可以通过Ognl表达式访问CompoundRoot对象栈顶的Action。
当用户发送请求到对应的Action时,Struts2会把当前被请求的Action01放入CompoundRoot
对象的“栈空间”栈顶,请求结束,Action01会被清除。
(当下一次另一个请求到来时,Struts2会把该请求对应的Action02放入“栈顶”)
所以,我们可以通过Ognl表达式访问CompoundRoot对象栈顶的Action。
14.ValueStack核心概念
Struts2在请求到来时,首先会创建一个ValueStack;
然后,把当前的Action对象放入栈顶(CompoundRoot);
Struts2会把ValueStack 存放在request中,属性为”struts.valueStack“,
所以,标记库可以访问到ValueStack
Struts2的很多标记就是通过访问ValueStack 获得数据的:
通过ognl从ValueStack 取数据,并且显示
<s:property value="ognl..."/>
省略value,取出ValueStack 的栈顶
<s:property />
通过ognl从ValueStack 取出集合,依次将集合中的对象置于栈顶,在循环中,ValueStack 栈
顶即为要显示的数据
Struts2在请求到来时,首先会创建一个ValueStack;
然后,把当前的Action对象放入栈顶(CompoundRoot);
Struts2会把ValueStack 存放在request中,属性为”struts.valueStack“,
所以,标记库可以访问到ValueStack
Struts2的很多标记就是通过访问ValueStack 获得数据的:
通过ognl从ValueStack 取数据,并且显示
<s:property value="ognl..."/>
省略value,取出ValueStack 的栈顶
<s:property />
通过ognl从ValueStack 取出集合,依次将集合中的对象置于栈顶,在循环中,ValueStack 栈
顶即为要显示的数据
<s:iterator value="ognl...list">
<s:property value="name"/>
</s:iterator>
<s:property value="name"/>
</s:iterator>
15. Struts2 如何支持 EL
Struts2通过StrutsRequestWrapper,重写了getAttribute方法。
设计模式
Sun公司提供了HttpServletRequest接口
HttpServletRequest
Sun提供的另一个类HttpServletRequestWrapper 继承了该接口;
在该类中有一个HttpServletRequest request属性,
同时提供一个getAttribute方法,可以访问到该属性,
public class HttpServletRequestWrapper implements HttpServletRequest{
private HttpServletRequest request;
public Object getAttribute(String name){
return request.getAttribute(name);
}
}
从上面来看,我们认为HttpServletRequestWrapper 和HttpServletRequest作用是一样的
方式1:如果我们写一个过滤器,在过滤器中使用HttpServletRequestWrapper 做包装
doFilter(request , response , chain){
chain.doFilter(new HttpServletRequestWrapper(request) , response);
}
这和我们直接传request的效果是一样的,所以这样写意义也不大。
方式2:但是如果我们再写一个类,让该类继承HttpServletRequestWrapper。
在该类中重写了父类构造方法,同时重写getAttribute方法,在该方法中从valueStack 中取数据;
public class StrutsRequestWrapper extends HttpServletRequestWrapper{
public StrutsRequestWrapper(HttpServletRequest request){
super(request);
}
Struts2通过StrutsRequestWrapper,重写了getAttribute方法。
设计模式
Sun公司提供了HttpServletRequest接口
HttpServletRequest
Sun提供的另一个类HttpServletRequestWrapper 继承了该接口;
在该类中有一个HttpServletRequest request属性,
同时提供一个getAttribute方法,可以访问到该属性,
public class HttpServletRequestWrapper implements HttpServletRequest{
private HttpServletRequest request;
public Object getAttribute(String name){
return request.getAttribute(name);
}
}
从上面来看,我们认为HttpServletRequestWrapper 和HttpServletRequest作用是一样的
方式1:如果我们写一个过滤器,在过滤器中使用HttpServletRequestWrapper 做包装
doFilter(request , response , chain){
chain.doFilter(new HttpServletRequestWrapper(request) , response);
}
这和我们直接传request的效果是一样的,所以这样写意义也不大。
方式2:但是如果我们再写一个类,让该类继承HttpServletRequestWrapper。
在该类中重写了父类构造方法,同时重写getAttribute方法,在该方法中从valueStack 中取数据;
public class StrutsRequestWrapper extends HttpServletRequestWrapper{
public StrutsRequestWrapper(HttpServletRequest request){
super(request);
}
public Object getAttribute(String name){
//从valueStack 中取数据
//....
return ....
}
}
在过滤器中使用StrutsRequestWrapper 做包装。
doFilter(request , response , chain){
chain.doFilter(new StrutsRequestWrapper(request) , response);
}
如此,在编程过程中,如果不使用getAttribute方法,request的使用和之前没有区别,如果调
用getAttribute方法,则会调用Struts2框架重写的方法。
类似的设计模式
Collections.synchronizedList方法是如何实现的?
//从valueStack 中取数据
//....
return ....
}
}
在过滤器中使用StrutsRequestWrapper 做包装。
doFilter(request , response , chain){
chain.doFilter(new StrutsRequestWrapper(request) , response);
}
如此,在编程过程中,如果不使用getAttribute方法,request的使用和之前没有区别,如果调
用getAttribute方法,则会调用Struts2框架重写的方法。
类似的设计模式
Collections.synchronizedList方法是如何实现的?
该方法的实现机制可以描述为:
首先,定义了一个包装类,在该包装类中有List list属性,
其次,新建synchroized 关键字的方法
private ListWrapper implements List{
List list;
public synchroized void add(){
list.add();
}
}
首先,定义了一个包装类,在该包装类中有List list属性,
其次,新建synchroized 关键字的方法
private ListWrapper implements List{
List list;
public synchroized void add(){
list.add();
}
}
16.修改debug.jsp
<%@page pageEncoding="utf-8"%><%@taglib uri="/struts-tags" prefix="s"%>
<%
Object obj = request.getAttribute("struts.valueStack");
out.println(obj);
%>
<!-- s:debug标签用于看valueStack,用于调试-->
17.Struts Action 核心 *
1.1. Action **1) Action基本原理 *
每次請求都会创建一个新的Action的实例
因为每次请求都对应一个单独的Action,所以不需要考虑线程安全问题。
Action对象将置于ValueStack 的栈顶
Action的业务方法(默认为execute)根据输入算输出
2) 在Action中如何访问Session&Application
使用ActionContext访问Session
ActionContext ctx = ActionContext.getContext();
Map session = ctx.getSession();
或者
Map application = ctx.getApplication();
session, application 将存放在ValueStack 的Context中
<s:property value="#session..."/>
或者
<s:property value="#application..."/>
通过实现SessionAware接口访问session (更好)
首先,新建BaseAction implements SessionAware
其次,所有需要session的XXXAction extends BaseAction
类似的,还有:
ServletRequestAware
ServletResponseAware
ServletContextAware
3) 使用通配符配置Action
<action name="*_*_*" class="com.tarena.outman.{1}Action" method="{2}">
<result name="success">/WEB-INF/jsp/day03/{3}.jsp</result>
</action>
4) 给Action注入参数(属性注入)
<param name="rowsPerPage">5</param>
5) 在result的配置中使用OGNL 表达式
<result name="success" type="dispatcher">
/WEB-INF/jsp/day03/user.jsp?userId=${user.userId}
</result>
18.什么时候jsp用<%@taglib uri="/struts-tags" prefix="s"%> ,什么时候用<tr> </tr>,<td></td>,<h1></h1>,<tbody></tbody>
19.不推荐使用ActionContext访问Session的方式,因为这种方式的“侵入性”较强。
ActionContext是Struts2的API,如果使用其他框架代替目前的Struts2框架,而我们
实际项目中的Action的数量非常庞大,每个类都修改会很费劲。可以通过实现SessionAware接口访问session
ActionContext是Struts2的API,如果使用其他框架代替目前的Struts2框架,而我们
实际项目中的Action的数量非常庞大,每个类都修改会很费劲。可以通过实现SessionAware接口访问session
package com.tarena.outman.day03;
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
public class BaseAction implements SessionAware{
//为了让子类也能使用,所以访问控制符为protected
protected Map<String, Object> session;
public void setSession(Map<String, Object> session) {
this.session = session;
}
}
该类实现了SessionAware接口,表明Struts2在启动BaseAction时,
首先,创建出该Action的对象,放入“栈顶”
然后,会调用BaseAction的setSession方法,把session传入给BaseAction对象
(注意:如果是普通的Action,Struts2在启动时仅创建出该Action的对象,然后放入“栈顶”)
由此,我们定义了属性session,以便在之后其他的方法中使用。为了让子类也能使用,所以访问
控制符为protected。
按照这样的机制,我们可以让所有的Action(如LoginAction)继承实现了SessionAware接口
的BaseAction,当需要更换Struts2框架为其他框架时,只需要修改BaseAction即可(另外的
框架只要提供一个类似SessionAware接口的接口,由BaseAction继承)
import java.util.Map;
import org.apache.struts2.interceptor.SessionAware;
public class BaseAction implements SessionAware{
//为了让子类也能使用,所以访问控制符为protected
protected Map<String, Object> session;
public void setSession(Map<String, Object> session) {
this.session = session;
}
}
该类实现了SessionAware接口,表明Struts2在启动BaseAction时,
首先,创建出该Action的对象,放入“栈顶”
然后,会调用BaseAction的setSession方法,把session传入给BaseAction对象
(注意:如果是普通的Action,Struts2在启动时仅创建出该Action的对象,然后放入“栈顶”)
由此,我们定义了属性session,以便在之后其他的方法中使用。为了让子类也能使用,所以访问
控制符为protected。
按照这样的机制,我们可以让所有的Action(如LoginAction)继承实现了SessionAware接口
的BaseAction,当需要更换Struts2框架为其他框架时,只需要修改BaseAction即可(另外的
框架只要提供一个类似SessionAware接口的接口,由BaseAction继承)
20. Struts2 核心标记库
知识点
1) UI标记
常用UI标记
a. form
b. textfield
c. password
d. submit
e. textarea
f. checkbox
g. radio
h. select
Struts2标记
a. 通用属性(所有标记都具备的属性)
注:带”*“星号的属性表示在任意主题,如xhtml下才可以使用
label (*)
labelposition(*)
required(*)
tooltip(*)
tooltipIconPath(*)
-------html原来的属性--------
cssClass(html中的class)
cssStyle(html中的sytle)
name
value
....
b. <s:form><form>
theme 主题
namespace 命名空间
action
知识点
1) UI标记
常用UI标记
a. form
b. textfield
c. password
d. submit
e. textarea
f. checkbox
g. radio
h. select
Struts2标记
a. 通用属性(所有标记都具备的属性)
注:带”*“星号的属性表示在任意主题,如xhtml下才可以使用
label (*)
labelposition(*)
required(*)
tooltip(*)
tooltipIconPath(*)
-------html原来的属性--------
cssClass(html中的class)
cssStyle(html中的sytle)
name
value
....
b. <s:form><form>
theme 主题
namespace 命名空间
action
method
c.<s:textfield> && <s:password>
maxLength
size
readonly
d.<s:textarea>
cols
rows
e.<s:checkbox>
使用1个
<s:checkbox name="ok"/>
查看页面源代码,我们会发现生成这样的html
<input type="checkbox" name="ok" value="true"/>
<input type="hidden" name="_checkbox_ok" value="true"/>
使用多个
写在页面
<s:checkbox name="product" fieldValue="1"/>
<s:checkbox name="product" fieldValue="2"/>
<s:checkbox name="product" fieldValue="3"/>
动态获得
<s:iterator value="products"> <!--products, Product类型的List-->
<s:checkbox name="product" fieldValue="%{id}"/>
</s:iterator>
<s:radio>
我们原来这么写
<input type="radio" name="abc" value="1"/>One
<input type="radio" name="abc" value="2"/>Two
<input type="radio" name="abc" value="3"/>Three
后来我们这么写
<s:radio list="productOptions" label="Radio" name="abc"
listValue="label" listKey="value" />
属性含义:
name
label
list OGNL--需要迭代的集合
listValue 作用于每一个选项的提示 OGNL --
listKey 作用于每一个要提交的值 OGNL --
c.<s:textfield> && <s:password>
maxLength
size
readonly
d.<s:textarea>
cols
rows
e.<s:checkbox>
使用1个
<s:checkbox name="ok"/>
查看页面源代码,我们会发现生成这样的html
<input type="checkbox" name="ok" value="true"/>
<input type="hidden" name="_checkbox_ok" value="true"/>
使用多个
写在页面
<s:checkbox name="product" fieldValue="1"/>
<s:checkbox name="product" fieldValue="2"/>
<s:checkbox name="product" fieldValue="3"/>
动态获得
<s:iterator value="products"> <!--products, Product类型的List-->
<s:checkbox name="product" fieldValue="%{id}"/>
</s:iterator>
<s:radio>
我们原来这么写
<input type="radio" name="abc" value="1"/>One
<input type="radio" name="abc" value="2"/>Two
<input type="radio" name="abc" value="3"/>Three
后来我们这么写
<s:radio list="productOptions" label="Radio" name="abc"
listValue="label" listKey="value" />
属性含义:
name
label
list OGNL--需要迭代的集合
listValue 作用于每一个选项的提示 OGNL --
listKey 作用于每一个要提交的值 OGNL --
g. <select>
<select name="abc">
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
Struts2标记
<s:select list="productOptions" label="Select" name="abc"
listValue="label" listKey="value" />
属性含义:
listValue 对应每一个Option的文本
listKey 对应每一个Option提交的值
headerValue 提示头的文字
headerKey 提示头对应的提交值
<interceptor name="" class="">
2) 在package 中定义拦截器栈
<interceptor-stack name="">
<interceptor-ref name="">
</interceptor-stack>
3) package中定义默认拦截器
<default-interceptor-ref name=""/>
4) action定义拦截器
<action name="" class="">
<!-- 表示访问该action前先调用这个拦截器-- >
<interceptor-ref name="">
<param name=""></param>
</interceptor-ref>
</action>
<select name="abc">
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
Struts2标记
<s:select list="productOptions" label="Select" name="abc"
listValue="label" listKey="value" />
属性含义:
listValue 对应每一个Option的文本
listKey 对应每一个Option提交的值
headerValue 提示头的文字
headerKey 提示头对应的提交值
21.拦截器
1) 在package 中定义拦截器<interceptor name="" class="">
2) 在package 中定义拦截器栈
<interceptor-stack name="">
<interceptor-ref name="">
</interceptor-stack>
3) package中定义默认拦截器
<default-interceptor-ref name=""/>
4) action定义拦截器
<action name="" class="">
<!-- 表示访问该action前先调用这个拦截器-- >
<interceptor-ref name="">
<param name=""></param>
</interceptor-ref>
</action>
22.Struts2 结构图
图示流程说明
当HttpServletRequest请求到来
当HttpServletRequest请求到来
经过一些初始化的工作(这些仅先做了解):
1) 请求发送给ActionMapper,
2) 再发送给由ActionContextCleanUp、Other Filters、FilterDispatcher 组成的前端控制器
3) 再发送给ActionProxy
4) ...
先调用拦截器,再调用Action、再是Result,
之后,还可以调用拦截器(拦截器前拦后堵)
23.Struts2 控制流程
Struts2控制流程(面试可能会问到)1) 请求到来
2) 创建ValueStack(Action放栈顶),进行初始化
3) 调用拦截器Interceptor,在拦截器中是可以访问ValueStack 的
4) 调用Action,执行execute()方法
5) 调用Result,Result负责把数据显示给用户
6) 最后到页面,通过标记库(Taglib)取出数据
24.自定义拦截器步骤
1) 实现Interceptor 接口,实现intercept方法2) 获取ValueStack
ValueStack stack = actionInvocation.getStack();
stack.findValue("ognl");
stack.setValue("ognl", obj);
3)获取Servlet API
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
ServletContext application = ServletActionContext.getServletContext();
4)调用Action
Action连Result一起调用
actionInvocation.invoke();
此后,intercept方法的返回值无意义
只调用Action,没有调用Result
actionInvocation.invokeActionOnly();
此后,由intercept方法的返回值来决定执行哪个Result
5)设置参数
25.资源文件与国际化(i18n)
之前我们学习了Struts2的五大组件(ValueStack、拦截器、Result、Action、标记库)。现在我们开始关于这些组件的一些技巧的学习:国际化、错误处理、表单验证等等。
资源文件的国际化internationalization(又名i18n,来由是以i开头n结尾的中间共18个字母)。
国际化的核心:页面显示的文字是可配置的(如中文、英文、日文等,不能写死在页面中)。
1) 资源文件
资源文件一般是属性文件*.properties
2) 对于中文
MyEclipse8.5可以方便的得到unicode编码
使用JDK提供的命令工具native2ascii也可以
3) 资源文件的命名和位置(重要)
如果项目非常大,所有资源文件放入同一个目录下是不好的。资源文件需要分层和分类。
包级资源文件
表示某资源文件是被一个包中所有Action所使用的,
类级资源文件
表示某资源文件只能被指定类使用
4) Action必须继承ActionSupport
ActionSupport类中已经封装了对资源文件的访问。
注意,在我们之前学习中,如果在配置文件中action没有class 属性,则调用的就是
ActionSupport类。
26.
0 0
- Struts2
- struts2
- struts2
- Struts2
- struts2
- struts2
- Struts2
- struts2
- struts2
- struts2
- Struts2
- Struts2
- Struts2
- struts2
- struts2
- STRUTS2
- Struts2
- Struts2
- Android SQLite
- MFC框架程序中OnIdle
- 大数据安全的六大挑战
- android intent 传递list 或 对象
- 每天进步一点点——分布式文件系统下的本地缓存
- Struts2
- Gamification Design Framework——游戏化设计框架
- Intellij13 IDEA常用快捷键 (mac 10.5 +),优化,使用出现的问题汇总
- 关于Fragment 不响应onActivityResult的情况分析
- image and video processing听课笔记(五)
- Java事务处理全解析(八)——分布式事务入门例子(Spring+JTA+Atomikos+Hibernate+JMS)
- Hibernate
- Android studio查看Genmotion模拟器上的文件夹
- python 脚本处理IDA的Dif文件