struts总结

1.为什么学习Struts框架

a.Struts框架好处

struts2是主流的开发技术,大多数公司在使用,struts把相关的servlet组件的各种操作都进行了相应的封装,这样就可以轻松地完成复杂的操作。Struts2是基于MVC模式开发的,MVC结构是一个优秀的设计思想,可以提高程序结构的灵活性,便于日后的维护和扩展。

--简化开发工作量,提高开发效率

--采用了优秀的设计思想(MVC)

b.Struts框架作用

struts充当控制器,接收请求,分发处理,

c.如何学习Struts框架

先重点掌握框架使用,原理性有余力可以多了解些。

注:我们目前使用的Struts版本为struts2 2.1.8。(2.1.6版本bug较多)

d.学校struts要掌握的重点:

valuestack

action

result

拦截器

标记库

2.MVC模式在JavaWeb中的应用

*a.什么是MVC

是一种软件架构的思想,将一个软件的组成部分划分成三种不同类型的 模块,分别是:

模型(用于封装业务逻辑,包括业务数据和业务处理逻辑,由JavaBean组件   (比如实体类,DAO,Service)实现),

视图(负责显示界面与用户交互,处理表示逻辑,一种是展示数据,另一种      是接受数据,由jsp组件实现),

控制器(用于控制流程,协调模型与视图,由Servlet、Filter组件(比如之 前的ActionServlet)实现)。

使用mvc的最主要的原因是为了实现模型的复用:即模型只需要开发 一次, 模型不关心处理的结果如何展现,模型将结果交给不同的视 图,由视图来展 现这些数据;另外,可以利用不同的视图来访问 同一个模型。

MVC:基于面向对象的一种常见的体系架构

Model:

封装数据以及对数据操作的方法(相当于饭店中做菜的材料(数据)和做菜的厨师(方法)

一个流程用一个方法

View:

封装的是用户界面,接收用户请求,负责输入和输出(和用户打交道)(相当于服务员)

Controller:

封装的是业务流程,控制业务流程(相当于饭店中的管理者)(如果程序比较简单,可以把Controller写在Model里面)

b.为什么使用MVC

企业程序更强调结构灵活,易于扩展和升级。所以广泛选用MVC模式开发。

*c.JavaWeb中如何实现MVC结构

JavaWeb技术主要有:Servlet,JSP,JavaBean,Filter,Listener等

V部分:JSP组件 (cart.jsp)

M部分:JavaBean组件(entity,dao)

C部分:Servlet,Filter组件 (ShoppingCartServlet)

*d.MVC处理流程

--首先浏览器发出请求

--请求进入C控制器

--C控制器调用M模型组件处理

--M模型组件处理后返回处理结果

-- C控制器调用V视图组件生成响应信息

*e.Struts框架的MVC实现

原有ShoppingCart程序,虽然符合MVC结构,但不适合大型项目开发,因为请求一多,ShoppingCartServlet会出现大量的if..else... ,可以进行以下方式的改造:

为ShoppingCartServlet配置一个XML文件,该文件定义不同请求和不同Action组件的对应关系,将原有if..else..分支处理用Action组件封装。

**f.Struts框架的处理流程

--浏览器发出struts请求

--请求进入struts控制器

--struts控制器解析xml配置文件(xml定义了请求和Action对应关系)

--控制器根据不同请求,调用不同的Action

--Action调用DAO处理请求,之后返回结果

--控制器根据结果调用视图组件为用户响应

struts总结

3.了解Struts历史

Struts框架分成Struts1和Struts2.Struts2和Struts1没有必然联系。Struts2是以WebWork框架核心(xwork)为基础构建起来

最早出现的Struts1是一个非常著名的框架,它实现了MVC模式。Struts1简单小巧,其中最成熟的版本是Struts1.2。之后出现了WebWork框架,其实现技术比Struts1先进,但影响力不如Struts1。在框架技术不断发展过程中,有人在WebWork核心XWork的基础上包装了Struts1(算是两种框架的整合),由此,结合了Struts1的影响力和WebWork的先进技术,Struts 2诞生了。所以说,Struts2不是Struts1的升级,它更像是WebWork的升级版本。

*4.Struts基本使用

a.引入struts2核心开发包(5个)

(1).struts2-core-2.1.8.1.jar

Struts2核心包,是Struts框架的“外衣。

(2).xwork-core-2.1.6.jar

Struts2核心包,是WebWork内核。

(3).ognl-2.7.3.jar

用来支持ognl表达式的,类似于EL表达式,功能比EL表达式强大的

多。

(4).freemarker-2.3.15.jar

freemarker是比jsp更简单好用,功能更加强大的表现层技术,用来 替代jsp的。在Struts2中提倡使用freemarker模板,但实际项目中使 用jsp也很多。

(5).commons-fileupload-1.2.1.jar

用于实现文件上传功能的jar包。

b.在web.xml中配置下struts控制器

c.根据请求编写Action,JSP

d.在struts.xml定义Action和请求对应关系

5.HelloWord入门实例

welcome.action-->Struts控制器-->struts.xml-->WelcomeAction

-->welcome.jsp

(Action请求可以是/welcome.action或者/welcome两种写法)

7、struts.xml基本配置

struts.xml放在src根目录下。

a) <struts>

根元素,可以包含多个<package>元素

b)<package>

<package name="***" namespace="/默认" extends="struts-default">

元素主要用于将Action分组定义。name属性用于指定包名;extends一般指 定为struts-default。struts-default这个包在struts-default.xml中定义,其中 包含了struts2运行所需的必要组件。

添加namespace属性的主要作用是避免在大项目中出现的命名冲突问题。

注意:

http://localhost:8080/struts01/netctoss/welcome

<package name="demo1" namespace="/netctosss"

extends="struts-default">

<action name="welcome" class="action.WelcomeAction">

<result name="success">/WEB-INF/jsp/Welcome.jsp</result>

</action>

namespace属性默认为“/”(即从应用名后的第一个"/"开始到最后一个“/”结束)。

eg:对于http://localhost:8080/struts01/netctoss/cost/showList.action

其中的namespace属性值应为”/netctoss/cost”。

eg:

如果不加namespace="/netctoss"那么

http://localhost:8080/struts01/netctoss/list.action便不会得到正确的匹配

一个<package>元素可以包含多个<action>..</action>主要用于定义请求

和Action组件的对应关系。name属性指定请求名;class属性指定Action的包

名.类名

c)<action>

<action name="***" method="execute默认" class="***">

一个<action>元素可以包含多个<result>...<result>主要用于定义视图响 应。name属性与Action.execute()返回值一致。

其中

(1).method属性可以省略,如果省略则默认调用Action中的execute()方法

(2.)如果不指定class属性,Struts会默认调用框架底层的ActionSupport

类处理(见下面:)。框架会默认为该<action>添加一个class,作用是

转发到对应

的<result  name="success">中指定的页面。当有nameform请求发

来时,struts不会调 用action(找不到)而是直接调用result中name属

性为success对应的页面。

注:name=”success”可以省略

<action name="nameform">

<!--<result name=”success”>/WEB-INF/jsp/Welcome.jsp</result>-->

<result>/WEB-INF/jsp/Welcome.jsp</result>

</action>

struts总结

--------ActionSupport类:---------

public String execute(){

return “success”;

}

d)<result>

<result name="success默认" type="dispatcher默认">

e:注意:

1.对于package、action、result,如果使用默认属性值,则可以省略属性名。

eg:<result name=”sucess” type=”dispatcher”>****</sesult>

如果使用默认属性值:则可以写成:

<result >****</sesult>

对于重复使用的result可以写成全局的result

<!-- 定义全局result -->

<global-results>

<!-- 错误处理 -->

<result name="error">/WEB-INF/jsp/error.html</result>

<!-- 拦截器登录处理 -->

<result name="login" type="redirectAction">showLogin</result>

</global-results>

2.page包中的各组件的放置顺序:

具体见struts-2.1.7dtd

package (result-types——> interceptors——>default-interceptor-ref——>

default-action-ref——> default-class-ref——> global-results——>

global-exception-mappings——> action*)>

拦截器配置放在global-results之前

3.当项目业务处理较多时如果将所有的配置都写在struts.xml一个文件中将很不方便,所以可以将不同的处理模块分别写在不同的xml文件中,最后在struts.xml中加载和模块配置文件,过程如下:

struts.xml:

<struts>

<!-- 加载各模块配置文件 -->

<include file="struts-cost.xml"/>

<include file="struts-account.xml"/>

...........

<package name="netctoss-default" extends="json-default">

<!-- 追加共通的Action,Interceptor组件 -->

拦截器、全局results....

</package>

</struts>

struts-cost.xml:

<!-- 资费模块配置文件 -->

<struts>

<package name="cost" extends="netctoss-default">

........

</package>

</struts>

struts-account.xml:

<!-- 资费模块配置文件 -->

<struts>

<package name="account" extends="netctoss-default">

........

</package>

</struts>

.............................

浏览器访问地址:

http://localhost:8080/应用名/namespace/action

http://localhost:8080/struts03_2/list/costList.action?page=4

以上的namespace默认为’’/’,本例为list

8、如何解决用户绕过ActionServlet,直接访问jsp文件的问题。

将所有jsp文件拷贝到WEB-INF目录下。因为WEB-INF目录中的内容不能直接访问,但能转发过来。

当然也可以用之前的session技术(太麻烦)。

对于struts中WebRoot文件夹下的.jsp页面仍可以直接输入地址访问。

9、Struts2提供的方便之处:

a.数据的自动的封装

根据页面组件的name属性,自动封装到Action中对应的name属性中。

在Jsp页面<input name=”name” type=”text”/>

在action中会自动给属性private String name 赋值。但是注意要有name对应的getter和setter方法。

b.数据的自动的传递

Action中的属性在jsp页面可以直接用EL表达式拿到

eg:

Action中属性private String name;

在jsp页面上可以直接${name}的到对应的值

按理说,EL表达式取数据的对象只有pageContext,request,session,application四类,不应该从Action对象中取name属性值,但struts框架重新包装了request,getAttribute()方法被改写(request的其他方法没被改写),如果从request对象中调用getAttribute()方法没获取到值(null),那么会自动从action中取,这样,struts中EL表达式就可以直接获取到Action属性中的值了。

上面介绍的采用了包装模式:(相当于手机加壳案例和线程池案例(其中的close方法特殊)。参考如下:

public class StrutsRequestWrapper extends HttpServletRequestWrapper{

//重写

public Object getAttribute(String key){

//寻找原request信息

Object obj = super.getAttribute(key);

if(obj == null){

//寻找valuestack信息

obj = valuestack.findValue(key);

//Ognl.getValue(key,context,root);

} struts总结

return obj;

}

}

${name} -->request.getAttribute("name")

-->Ognl.getValue("name",context,root)

10.项目示例(资费列表显示)

a.显示默认主页面

index.action-->struts控制器-->index.html

b.资费列表显示

feeList.action-->struts控制器

-->FeeListAction-->FeeDAO-->COST

-->fee_list.jsp

1)编写COST对应的Entity实体类

2)编写DAO,DBUtil

--引入oracle驱动包

3)编写Action

4)配置Action

5)编写JSP

--引入jstl.jar,standard.jar

11.OGNL技术的使用

1)什么是OGNL

OGNL是Object-Graphic Navigation Language(对象图导航语言)的缩写,

是一种功能强大的表达式语言(与EL表达式类似)。OGNL可以让我们用非常

简单的表达式访问对象层(访问对象的数据和方法),它用一个独立的lib形

式出现(封装于ognl.jar工具包中),方便我们使用或者构建自己的框架。

OGNL区别于EL表达式,OGNL可以在.java文件中通过getValue()方法访问对

象,而EL表达式不可以在.java文件中使用;EL表达式在.jsp文件中可以直接

输出数据,而OGNL不可以,OGNL在.jsp文件中只能当做struts标签中的属性

值,通过struts标签访问数据。

2)OGNL基本原理

OGNL工具主要由3部分构成,具体如下

a.OGNL引擎

负责解析ONGL表达式,定位数据

b.Root根存储区(Object类型)

负责存储要访问的目标对象(一个)。

c.Context变量存储区(Map类型)

负责存放多个要访问的目标对象。

*3)OGNL基本语法

a.访问Root区域对象基本语法

Ognl.getValue("OGNL表达式", "Map存储器内容","根存储器内容");

Ognl.getValue("OGNL表达式", "根存储器内容");

--访问简单数据:"属性" 例如"name"

int id = (Integer)Ognl.getValue("id", foo);

String name = (String)Ognl.getValue("name", foo);

--访问数组或List集合:"属性[0]"

例如"arr[1]"

String arrVal = (String)Ognl.getValue("arr[1]", foo);

String  listVal = (String)Ognl.getValue("list[2]", foo);

--访问map集合元素:"属性['key']"或"属性.key"

例如"map.c"或"map[‘two’]"

注:”map[‘a’]”不可用(‘a’结果为整数)

String mapVal = (String)Ognl.getValue("map.b", foo);

String mapval2 = (String)Ognl.getValue("map['user.name']",foo);

--访问方法:"属性值.方法()",

例如"list.size()"

System.out.println(Ognl.getValue("map['two'].toUpperCase()", foo));

System.out.println(Ognl.getValue("list.size()", foo));

--访问构造方法:"new 包名.构造方法"

例如"new java.util.Date()"

Object obj =

Ognl.getValue("new org.tarena.entity.Foo('TOM')", foo);

--访问静态成员:"@包名.类名@成员"

例如"@java.lang.Math@PI"

Ognl.getValue("@java.lang.Math@abs(-1)", foo);

Ognl.getValue("@java.lang.Math@PI", foo);

--创建List对象:"{元素1,元素2}"

Object obj1 = Ognl.getValue("{'struts','hibernate','spring'}",foo);

--创建Map对象:

"#{key1:value1,key2:value2}"

Object obj2 = Ognl.getValue("#{1:'tom',2:'jack',3:'rose'}", foo);

public static void main(String[] args) throws Exception {

Foo foo = new Foo();

foo.setId(100);

foo.setName("张三");

foo.setArr(new String[] { "A", "B", "C" });

foo.setList(Arrays.asList("芙蓉", "凤姐", "春哥"));

Map<String, String> map = new HashMap<String, String>();

map.put("one", "Java");

map.put("two", "JavaWeb");

map.put("three", "Struts2");

map.put("user.name", "Scott");

foo.setMap(map);

//测试OGNL访问foo目标对象

//Ognl.getValue("OGNL表达式", "Map存储器内容","根存储器内容");

//Ognl.getValue(expression, root);

Map context = new HashMap();

//访问root基本的属性值

int id = (Integer)Ognl.getValue("id", foo);

System.out.println(id);

String name = (String)Ognl.getValue("name", foo);

System.out.println(name);

System.out.println(Ognl.getValue("user.name", foo));

//访问root数组和集合元素

String arrVal = (String)Ognl.getValue("arr[1]", foo);

System.out.println(arrVal);

String  listVal = (String)Ognl.getValue("list[2]", foo);

System.out.println(listVal);

//访问root对象的map集合元素

String mapVal = (String)Ognl.getValue("map.b", foo);

System.out.println(mapVal);

String mapval2 = (String)Ognl.getValue("map['user.name']",foo);

System.out.println(mapval2);

//支持运算符

System.out.println(Ognl.getValue("id+1",foo));

//System.out.println((Integer)Ognl.getValue("id",foo)+1);

System.out.println(Ognl.getValue("\"姓名:\"+name", foo));

System.out.println(Ognl.getValue("id > 200",foo));

//方法调用

System.out.println(Ognl.getValue("map['two'].toUpperCase()", foo));

System.out.println(Ognl.getValue("list.size()", foo));

//构造方法的调用

Object obj = Ognl.getValue("new org.tarena.entity.Foo('TOM')", foo);

System.out.println(obj);

System.out.println(Ognl.getValue("name", obj));

//静态方法和常量的调用

System.out.println(Ognl.getValue("@java.lang.Math@abs(-1)", foo));

System.out.println(Ognl.getValue("@java.lang.Math@PI", foo));

//创建一个list集合

Object obj1 = Ognl.getValue("{'struts','hibernate','spring'}",foo);

System.out.println(obj1.getClass().getName());

//创建一个map集合

Object obj2 = Ognl.getValue("#{1:'tom',2:'jack',3:'rose'}", foo);

System.out.println(obj2.getClass().getName());

}

12、OGNL技术在Struts的使用

在Struts2中有一个ValueStack(本质就是存放数据的集合)数据对象,该对象存储了请求相关的所有数据信息。例如request,session,application,action等.

Struts2采用OGNL工具对ValueStack进行操作。

1)xwork对OGNL进行了部分改造

在xwork中将原来OGNL标准结构中的Root存储区改造成了一个栈结构

(CompoundRoot)以前只能存放一个对象,现在进行了扩容,可以存放

多个对象

当利用"属性"表达式访问时,优先去栈顶对象寻找,没有再去次栈顶寻找。

2)ValueStack结构(OgnlValueStack)

ValueStack就是一个容器(Map集合)(存放东西的不是Tomcat容器)

(参考valuestack.jpg)

3)Struts2标签的使用

在JSP中,利用Struts2标签显示数据,需要为标签指定OGNL表达式,标签利用表达式定位ValueStack中的数据,进行相应操作。

a) debug标签:显示valuestack状态

<s:debug></s:debug>

b) iterator标签:循环集合元素

value属性:指定ognl

var属性:指定循环变量,会被存放到ValueStack的context区域。

status属性:指定循环状态变量,会被存放到ValueStack的context区域.该

变量有count属性表示一共循环了多少个元素。

index属性表示当前循环元素的索引。

<s:iterator value="new int[totalPages]" status="i">

<s:if test="#i.count==page">

<a class="current_page"href="costList.action?page=${i.count }">

<s:property value="#i.count"/>

</a>

</s:if>

<s:else>

<a href="costList.action?page=${i.count }">

<s:property value="#i.count"/>

</a>

</s:else>

</s:iterator>

c) if...else...标签:判断分支

test属性:指定ognl判断表达式

<s:if test="page < totalPages" >

<a href="costList?page=${page+1 }">下一页</a>

</s:if>

<s:else>

下一页

</s:else>

d) property标签:显示数据

value属性:指定ognl表达式

<s:iterator value="costList" var="cost">

<tr><td><s:property value="#cost.id"/></td></tr>

</s:iterator>

e) date标签:将date数据格式化输出

name属性:指定ognl表达式

format属性:指定日期模板

<td>

<s:date name="#cost.createTime" format="yyyy-MM-dd HH:mm:ss"/>

</td>

13、Action组件的相关使用

1)Action组件的原理

--客户发出action请求给struts控制器

--前端控制器截获请求并根据配置信息调用对应的action

--struts控制器会创建valuestack对象

--struts控制器根据请求创建Action对象并将Action压入valuestack的root

栈顶(Action线性安全,不用考虑并发问题,struts会为每一个请求 创

建一个Action对象,区别于Servlet)

--struts控制器调用一系列拦截器做一些辅助性的工作(一般都是

valuestack的操作),如通过parmaeterInterceptor将表单中的数据赋值

给action中的对象;还有将请求相关request,session对象放入到

valuestack的context区域,同时将ValueStack对象存入到request中。

存储的key为”struts.valueStack”。(这样,当一次请求结束后,容器

会销毁request,request销毁了,其中的valuestack对象也就销毁了)

--控制器调用Action,执行业务方法处理(根据输入算输出并返回结果)

--控制器根据Action返回值调用result视图组件处理。

--请求处理完毕,销毁valuestack和Action对象。

一次请求,一个valuestack和action对象

2)Struts中写Action过程:

定输入、定输出、根据输入算输出、返回结果

)Action中如何使用session,request

(1).利用ActionContext和ServletActionContext工具类(不推荐)

a.ActionContext返回是Struts框架封装成Map之后的

request,session,application.

eg:

//将用户信息写入Session

ActionContext ac = ActionContext.getContext();

Map<String,Object> session = ac.getSession();

session.put("user", adminCode);

Map<String,Object> application = ac.getApplication();

Map<String,Object> request = (Map)ac.get("request");

b.ServletActionContext返回的是Servlet中使用的request, session,

application原有类型。

(使用建议:存值取值建议用Map结构API,如果有特殊需求再采用

Servlet原有类型(如获取客户端IP))

eg:

HttpServletRequest request = ServletActionContext.getRequest();

HttpSession session = httpRequest.getSession();

HttpServletResponse response = ServletActionContext.getResponse();

ServletContext application = ServletActionContext.getServletContext()

ActionContext工具类中的方法getSession()如何将HttpSession对

象封装成Map对象的说明:

Map----impements--->AbstructMap---extends-->SessionMap(重

写了Map中的put和get方法)

----如何将原有HttpSession封装成Map------

public class SessionMap extends AbstractMap{

private HttpSession session;

public SessionMap(HttpSession session){

this.session = session;

}

public void put(Object key,Object val){

session.setAttribute(key,val);

}

public Object get(Object key){

session.getAttribute(key);

}

}

不推荐使用ActionContext访问Session的方式,因为这种方式的“侵入性”较强。ActionContext是Struts2的API, 如果使用其他框架代替目前的Struts2框架,而我们实际项目中的Action的数量非常庞大,每个类都修改的话,会非常麻烦。

(2).利用Aware接口方式注入(推荐)

将Action实现Aware接口,由框架底层将对象注入给Action中相应的变量

当action实例化时候,struts框架就会自动将session对象(在valuestack中)赋值给实现了SessionAware接口的类中的变量(就是注入)。

(即session,ruquest,response,application)

RequestAware 对应的是Map结构的Request

SessionAware 对应的是Map结构的Session

ApplicationAware 对应的是Map结构的Application

ServletRequestAware对应的HttpServletRequest

ServletResponseAware对应的HttpServeltResponse

ServletContextAware对应的ServletContext

eg:

public class LoginAction implements SessionAware{

protected Map<String,Object> session;

...............

public void setSession(Map<String, Object> session) {

this.session = session;

}

public String execute(){

if(("admin".equals(adminCode)) && ("1234".equals(passWord))){

session.put("user", adminCode);

return "success";

}else{

return "error";

}

}

}

(3)、使用工具类(ActionContext、ServletActionContext)还是

Aware接口?

Action组件内部用Aware接口、Action组件之外(比如后面的拦截器)用ActionContext、ServletActionContext

)Action属性注入

作用:在创建Action对象时指定属性值

在<action>配置中为Action组件的属性指定一个初始值,该值在创建

Action对象时注入。可以将一些变化的参数值,利用该方法指定。例如

pageSize,管理员用户名,dir存储路径等。

在<action>配置中,为Action对象的属性指定初始值。使用格式如下:

<action name="feeList" class="org.action.FeeListAction">

<!--创建Action对象时给属性指定一个值-->

<param name="属性名">属性值</param>

<result></result>

</action>

eg:

public class ListAction{

private Stirng param1;

private String param2;

.....

public String getParam1(){

return param1;

}

..... struts总结

public setParam1(Stirng param1){

this.param1 = param1;

}

.......

}

struts.xml:

<action name="feeList" class="org.action.FeeListAction">

<param name="param1">admin</param>

<param name="param2">1234</param>

<result>........</result>

</action>

)Action通配符配置

Action通配符可以将多个具有相同属性的Action整合为一个Action。

在<action>配置时,name请求名可以使用若干个*符号。然后再其他属

性中通过使用{1},{2}引用第一个*号,第二个*号所代表的字符串。

<!-- 通配符配置 -->

<action name="*_*" method="{2}"class="com.tarena.action.{1}">

<result name="success">/index.jsp</result>

</action>

eg:

CostAction.java:

public class CostAction {

//属性定义--省略

public String add(){

System.out.println("资费添加操作");

return "success";

}

public String update(){

System.out.println("资费更新操作");

return "success";

}

}

struts.xml:

<action name="cost_*" method="{1}"

class="com.tarena.action.CostAction">

<result name="success">/index.jsp</result>

</action>

14、Result组件的相关使用

1)Result组件原理

a.Result组件的作用

Result组件负责生成响应视图内容。将ValueStack中的数据做不同形式

的输出。

Struts2框架提供了多种不同的Result组件类型,用于做不同形式响应。

例如json数据响应,流数据响应,jsp响应等。

b.Result组件相关配置

--Result声明定义

<package>

<result-types>

<result-type name="result类型" class="Result组件实现类"/>

</result-types>

</package>

--Result使用定义

<action>

<result name="标示符" type="result类型"></result>

</action>

c.编写一个转发功能的Result组件

定义的类类必须实现Result接口(Result组件),并且将约定的execute方法实现在该方法中编写了生成响应输出的逻辑代码。

public class MyDispatcherResult implements Result{

private String location;

//setter和getter方法

................

//约定方法

public void execute(){

HttpServletRequest request = ServletActionContext.getRequest();

HttpServletResponse response =ServletActionContext.getResponse();

RequestDispatcher rd = request.getRequestDispatcher(location);

rd.forward(request,response);

}

}

*2)掌握经常使用的Result组件

a. JSP视图

--dispatcher(默认):以转发方式调用JSP

--redirect:以重定向方式调用JSP

<result name="" type="dispatcher(默认)/redirect">

jsp页面

</result>

b.Action视图

--chain:以转发方式调用下一个Action

--redirectAction:以重定向方式调用下一个Action

c:

stream:以字节流方式响应,Action中的InputStream类型的属性以

字节流方式输出。

eg:由服务器端生成验证码图片并以流的方式发送给浏览器。

在struts.xml端的配置如下:

<!--验证码处理 -->

<action name="image" class="org.tarena.netctoss.action.ImageAction">

<result type="stream"  name="success">

<param name="inputName">imageStream</param>

</result>

<result name="fail">/WEB-INF/jsp/login.jsp</result>

</action>

注:其中的<param name="inputName">imageStream</param>区别于Action

属性注入,其作用为:给result对象指定参数值

d:

json:以json字符串响应,将Action中指定的属性拼成一个json字符串输

出。

注:

其中,a、b、c中的result组件在’struts-defaulg”包下,d中的result组件

在”json-default”,struts-core.jar中的默认包

<package name="struts-default" abstract="true">如下:

<package name="struts-default" abstract="true">

<result-types>

<result-type name="chain" class="*****"/>

<result-type name="dispatcher" class="*****"/>

<result-type name="freemarker" class="*****"/>

<result-type name="httpheader" class="*****"/>

<result-type name="redirect" class="*****"/>

<result-type name="redirectAction" class="*****"/>

<result-type name="stream" class="class="*****"/>

<result-type name="velocity" class="class="*****"/>

<result-type name="xslt" class="*****"/>

<result-type name="plainText" class="*****"/>

</result-types>

</package>

相同命名空间调用:

<result type="redirectAction">

请求名

</result>

跨命名空间调用

<result type="redirectAction">

<param name="actionName">请求名</param>

<param name="namespace">/</param>

</result>

======资费删除流程=====

fee_delete.action-->FeeDeleteAction-->FeeDAO

-->FeeListAction-->fee_list.jsp

============练习=============

完成课上项目任务。

扩展任务:完成资费的添加,更新处理,查看,启用等。

16、json Result组件

主要负责将Action的属性以json字符串格式输出。

json Result的使用步骤:

a.引入struts2-json-plugin.jar

b.将<package>元素的extends属性改为继承"json-default"(json-default包

的范围比原struts-default包大,所以更改后仍可以使用以前包中的组件)

c.<result>使用配置

//只返回Action中一个属性值

<result type="json">

<param name="root">属性名</param>

</result>

//返回Action中多个属性值

<result type="json">

<param name="includeProperties">

属性名1,属性名2,属性名3

</param>

</result>

//返回Action中所有属性值

<result type="json">

</result>

因为使用name属性默认值,所以name=”success”可以省略。

17、Struts2表单标签

1.什么是标签

struts标签封装了界面显示逻辑,用于简化JSP。

jstl标签用来代替jsp页面中的java代码,struts标签不但可以代替jsp页面中的

java代码,还可以代替jsp页面中html标记

2.struts常用标签:

textfield,password,hidden,textarea

radio,checkboxlist,select

checkbox,form

a) textfield

以输入框方式显示属性值.

name属性指定ognl表达式,表示输入框中的值

<input type="text" class="readonly" name=”cost.id” value=${cost.id}

readonly />

相当于:

<s:textfield name="cost.id" cssClass="readonly" readonly="true">

</s:textfield>

注:规定输入字段为只读(内容不可被更改)。在html中input标签readonly属性

直接写,在struts标签中要写成:readonly=”true”。类似的的还有disabled要写成

disabled=”true”

b) textarea

以文本域方式显示属性值.

name属性指定ognl表达式,表示文本域中的值

<textarea class="width300 height70">${cost.descr}</textarea>

<s:textarea name="cost.descr" cssClass="width300 height70"></s:textarea>

c)password:

以文本框方式显示密码

name属性指定ognl表达式,,表示输入框中的值

注:默认情况下,文本框内不会显示密码,如果要显示密码则需要设置showPassword属性。

密码:<s:password name="password" showPassword="true"></s:password>

d) radio:

以一组单选框方式显示,并可以根据属性值决定哪个选项选中。

list属性指定集合ognl,用于生成若干radio选项。

name属性指定ognl,用于决定哪个raido选中。

<s:radio name="cost.costType" list="#{'1':'包月','2':'套餐','3':'计时'}">

</s:radio>

e)checkbox:

以单选框方式显示选中状态

name属性指定ognl表达式,name属性值为true时,单选框默认会被选中

eg:

婚姻状况:<s:checkbox name="marry""></s:checkbox>已婚

f)checkboxlist:

以复选框方式显示选中状态

name属性指定ognl表达式,用来决定哪些复选框默认被选中。

list属性为map<key,value>集合

listKey属性为map集合中的key

listValue属性为map集合中的value,为在界面显示的内容

参考struts05_1中的form.jsp

eg1:

爱好:<s:checkboxlist name="chk" list="#session.favors" listKey="id"

listValue="name"></s:checkboxlist>

eg2:

<s:checkboxlist name=”” list=”costList’” listKey="id"

listValue="name"></s:checkboxlist>

g)select:

以下拉列表的方式显示数据:

name属性指定ognl表达式,用来决定哪个option默认被选中。

eg1:

<s:select name="status" cssClass="select_search"

’:’暂停’,'1':'开通','2':'暂停','3':'删除'}">

</s:select>

相当于

<select class="select_search" >

<option value="2">全部</option>

<option value="1">开通</option>

<option value="0">暂停</option>

<option value="-1">删除</option>

</select>

eg2:

<s:select list=”costList” name=”” listKey=”id” listValue=”name”></s:select>

注:对于上面的struts标签中的name属性,不但可以指定ognl表达式获取相关的数据,还可以将action中的属性名设置为name的属性值,这样就可以实现表单数据的自动提交。

h)form:

theme属性:表示主题,可选项有xhtml和simple;如果不写,默认为xhtml 。

theme属性如果为默认值(xhtml),那么在使用struts表单标

签时候会自动添加样式(自动添加tr、tr,让显示更美观),

这样就会破坏当前页面的布局和样式。

如果在用struts表单标签时,没有用struts中的form标签而是

使用html中的form标签,那么在使用struts表单标签时候也

会自动添加样式

<s:form action="update" namespace="/" theme="simple">

.............

</s:form>

通用属性(所有标记都具备的属性):

label

labelpostion

required

tooltip

tooltipIconPath

cssClass(html中的class)

cssStyle(html中的style)

name

value

18、拦截器组件

2)什么是拦截器:

一般利用拦截器封装一些通用性处理功能,便于重复利用。例如请求参

数给action属性赋值、日志记录、权限检查、文件上传、事务处理等。拦截

器通过配置方式调用,因此使用方法比较灵活,便于维护或扩展。

Struts2框架提供了大量的拦截器组件,如果不能满足开发者需要,可以

进行自定义。

eg:

<interceptor name="params"

class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>

其中ParametersInterceptor类用于在创建Action对象时将表单中的参数

赋值给Action中的相关属性。

具体见:

ReferencedLibraries/struts2-core-2.1.8.jar/struts-default.xml

/<interceptors>标记

2)拦截器完整工作流程:

上图中的FilterDispatcher为前端控制器

a.客户发送一个Action请求,请求交给控制器

b.控制器创建一个ValueStack、Action对象,并将Action压入ValueStack栈顶

c.控制器调用ActionInvocation组件执行请求处理

d.ActionInvocation组件调用请求相关的拦截器组件--前部分处理.

e.然后再调用Action组件业务方法

f.然后再调用Result组件处理方法

g.最后执行拦截器组件--后部分处理.

h.将响应信息输出,为客户端响应

3)拦截器作用

拦截器可以在Action和Result组件调用之前执行,也可以在Action和Result

组件之后执行。

4)自定义拦截器

a.编写拦截器组件实现类(两种方法):

1.编写拦截器组件实现类实现Interceptor接口的interceptor方法。

public class MyInterceptor implements Interceptor{

public String intercept (ActionInvocation in){

//拦截器的前期处理逻辑

in.invoke();//执行Action和Result

//in.invokeActionOnly();//仅执行Action

//拦截器的后期处理逻辑

}

}

eg:

public class CheckLoginInterceptor implements Interceptor{

public void destroy() {

// TODO Auto-generated method stub

}

public void init() {

// TODO Auto-generated method stub

}

public String intercept(ActionInvocation in) throws Exception {

System.out.println("(前期处理)自定义拦截器被调用。。。");

ActionContext ac = ActionContext.getContext();

//ActionContext ac = in.getInvocationContext();

Map<String,Object> session = ac.getSession();

//登录检查

if(session.get("user") == null){

//为登录

return "login";//进入登录页面

}

in.invoke();//执行Action、DAO和Result--->jsp

System.out.println("(后期处理)自定义拦截器被调用。。。");

return null;//invoke()方法执行之后,后面的返回值都无效(即不会返回),因为执行in.invoke(),也即执行Action和Result调用Jsp后,返回的值没有任何意义。

}

}

2.所有拦截器组件实现类也可以通过继承AbstractInterceptor类并实现

inteceptor方法。

eg:

public class Interceptor2 extends AbstractInterceptor {

public String intercept(ActionInvocation in) throws Exception {

System.out.println("(前期处理)自定义拦截器被调用。。。");

// ActionContext ac = ActionContext.getContext();

ActionContext ac = in.getInvocationContext();

Map<String, Object> session = ac.getSession();

// 登录检查

if (session.get("user") == null) {

// 未登录

return "login";// 进入登录页面

}

in.invoke();// 执行Action和Result

System.out.println("(后期处理)自定义拦截器被调用。。。");

return null;//invoke()方法执行之后,后面的返回值都无效(即不会返回),写着只是好看一点

}

}

注意:当执行了invoke()方法后,invoke()方法后面的返回值无效(即不会返回),写着只是好看一点。如果没有执行invoke(),返回值有效。控制器会根据该返回值调用一个Result生成响应信息

b.注册拦截器(将拦截器注册给struts2框架)

(1).方法一:

<package>

<interceptors>

<interceptor name="拦截器名"class="拦截器实现类"/>

<interceptor name="" class=""/>

</interceptors>

</package>

eg:

<!-- 定义拦截器 -->

<interceptors>

<interceptor name="checklogin"

class="org.tarena.netctoss.interceptor.CheckLoginInterceptor2"/>

</interceptors>

<!-- 使用拦截器 -->

<action name="costDelete" class=”org.tarena.netctos.CostDeleteAction”>

<interceptor-ref name="checklogin"/>

<interceptor-ref name="defaultStack"/>//调用默认拦截器栈中的拦截器

<result name=”cuccess”>/WEB-INF/jsp/cost/cost_delete.jsp</result>

</action>

struts总结

(1).方法二

创建拦截器栈(<interceptor-stack name="loginStack">),将多个拦截器放在拦截器栈中,这样就可以在需要的地方直接引入拦截器栈就行了(<interceptor-ref name="loginStack"/>)

eg:

<!-- 定义拦截器 -->

<interceptors>

<interceptor name="checklogin"

class="org.tarena.netctoss.interceptor.CheckLoginInterceptor2"/>

<interceptor-stack name="loginStack">

<interceptor-ref name="checklogin"/>

<interceptor-ref name="defaultStack"/>

</interceptor-stack>

</interceptors>

<!-- 使用拦截器 -->

<action name="costDelete" class=”org.tarena.netctos.CostDeleteAction”>

<interceptor-ref name="loginStack"/>

<result name=”cuccess”>/WEB-INF/jsp/cost/cost_delete.jsp</result>

</action>

方法二中的定义拦截器的方法实际上是先定义一个checklogin拦截器,然后定义一个拦截器栈(用于存放多个拦截器),把定义的checklogin拦截器和struts默认的拦截器放在拦截器栈里面。在使用拦截器时候,直接引入拦截器栈就可以了(相当于引入了checklogin拦截器和struts默认拦截器)。

c.使用拦截器组件

(1).为所有Action指定默认使用配置,这样,拦截器便对该包中的所有Action

起拦截作用

<package ******>

<default-interceptor-ref  name="拦截器名"/>

</package>

--(2).为某一个Action指定使用配置

<action>

<interceptor-ref name="拦截器名"/>

</action>

eg:

<action name="showAddCost">

<interceptor-ref name="loginStack"/>

<interceptor-ref name="defaultStack"/>

<result>/WEB-INF/jsp/cost/cost_add.jsp</result>

</action>

注意:如果为某个Action指定了拦截器配置,不会再调用指定的默认拦截器.所以一般会加上<interceptor-ref name="defaultStack"/>。

)fileUpload内置拦截器的使用

a)fileUpload拦截器功能

用于实现文件上传功能。

fileUpload拦截器处理流程:

客户端发送上传文件请求

首先,struts控制器收到请求后调用fileUpload拦截器,fileUpload拦截器调用commons-file-upload.jar上传组件对请求提交

的表单信息进行解析。

然后将解析后的文件保存到服务器临时目录下,并将临时目录下的文件

对象赋值给Action的File属性。

执行Action,在Actin业务中,需要做文件复制,将临时文件转移到目标

目录中。

当Action和Result调用完毕后,清除临时目录下的文件,因此在Actin业务中,需要做文件复制,将临时文件转移到目标目录中。

b)上传示例

注意事项:

--需要引入commons-io.jar)

--form表单method必须为post;enctype必须为multipart/form-data

--Action组件按下面规则接收表单信息

<input type="file" name="xxx">

Action属性如下:

private File xxx;// 临时目录下的文件

private String xxxFileName;// 源文件名

private String xxxContentType;// 源文件类型

---struts默认允许上传的文件所占最大内存为2097152字节(不同计算机可

能略有不同)。如果要更改默认设置,可以参考如下“更改struts中的默

认设置”

更改struts中的默认设置(即修改如下配置文件):

ReferencedLibraries/struts2-core-2.1.8.jar/org-apache.struts2/default.properties

18、更改strts中的默认配置:

1.更改对客服端发送过来的参数进行解码的方式:

<constant name="struts.i18n.encoding" value="gbk"/>(默认为utf-8)

2.更该允许客户端上传的最大文件大小值:

”/>

(默认大小为:2097152字节,约2M)

19、全局异常处理:

<!--全局的异常处理,当异常从Action中抛出时,会自动进入全局异常处理模块-->

<global-results>

<!-- 错误处理 -->

<result name="error">/WEB-INF/jsp/error.html</result>

</global-results>

<global-exception-mappings>

<exception-mapping exception="java.lang.Exception" result="error">

</exception-mapping>

</global-exception-mappings>

20、用户输入不存在请求资源路径(及action不存在)处理:

<!-- 指定一个默认响应的Action,当遇到例外的action请求,该项配置启作用 -->

<default-action-ref name="defaultAction"/>

<!-- 采用重定向方式调用toLogin -->

<action name="defaultAction">

<result type="redirectAction">

<param name="namespace">/</param>

<param name="actionName">toLogin</param>

</result>

</action>

<!-- 显示登录页面 -->

<action name="toLogin">

<result>/WEB-INF/jsp/login.jsp</result>

</action>

通过此配置后,用户输入非法请求资源路径时便不会出现“404”错误提示了,而是友好地跳转到登录页面。

======NETCTOSS项目========

1)项目描述(一期工程)

实现电信计费系统的账号管理,业务管理,资费管理,管理员和角色管理的功能。

2)项目技术架构

主要采用Struts2,JDBC,Ajax,jQuery技术。

采用MVC结构分层思想开发。

表现层(V):JSP,Ajax,jQuery

控制层(C):Struts2控制器Filter+Action

业务层(M):JavaBean,Bean组件

数据访问层(M):DAO+JDBC

3)项目工程结构

a.开发包引入

--Struts2开发包(5个核心+1个json响应包)

--Oracle驱动包

b.src源码

org.tarena.netctoss.action

org.tarena.netctoss.action.fee

org.tarena.netctoss.action.account

org.tarena.netctoss.service

org.tarena.netctoss.dao

org.tarena.netctoss.pojo

org.tarena.netctoss.util

org.tarena.netctoss.test

c.配置文件

web.xml : 配置struts2控制器

struts.xml:struts2框架主配置

--struts-fee.xml : 资费模块配置

--struts-account.xml:账号模块配置

d.WebRoot

WebRoot/WEB-INFO/jsp/fee/资费页面

WebRoot/styles/样式文件

WebRoot/js/脚本文件

WebRoot/images/页面图片

=========记录检索=========

search.action-->SearchAction-->DAO

1.项目评审

1)自我简介,项目需求描述,功能演示

2)典型功能实现讲解

2.共通问题处理

1)表单校验处理(参考“jQuery表单校验插件”目录的资料)

可以利用jQuery编写校验函数,

也可以基于现有的jQuery扩展插件来实现

例如validate和formvalidate等插件都可以

2)Struts2全局异常处理

当异常抛出Action的业务方法时,可以利用全局异常处理方式解决(在struts.xml追加配置)。

3)将页眉导航部分提取成一个head.jsp,

通过include方式引入各个页面。

4)设置一个默认响应Action。

遇到不能识别的Action请求,或找不到请求对应的Action时,调用该默认Action做响应

以上的“struts总结“是本人在学习期间自己总结出来的,今天,把她晒出来,希望能够和大家分享下!

struts总结的更多相关文章

  1. 菜鸟学Struts2——Struts工作原理

    在完成Struts2的HelloWorld后,对Struts2的工作原理进行学习.Struts2框架可以按照模块来划分为Servlet Filters,Struts核心模块,拦截器和用户实现部分,其中 ...

  2. Struts的拦截器

    Struts的拦截器 1.什么是拦截器 Struts的拦截器和Servlet过滤器类似,在执行Action的execute方法之前,Struts会首先执行Struts.xml中引用的拦截器,在执行完所 ...

  3. Struts框架的核心业务

    Struts的核心业务 Struts核心业务有很多,这里主要介绍了比较简单一些的: 请求数据的处理,和数据自动封装,类型自动转换 1.Struts中数据处理 1.1.方式1:直接过去servletap ...

  4. Struts的文件上传下载

    Struts的文件上传下载 1.文件上传 Struts2的文件上传也是使用fileUpload的组件,这个组默认是集合在框架里面的.且是使用拦截器:<interceptor name=" ...

  5. 配置hibernate,Struts。文件

    hibernate文件配置 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernat ...

  6. hibernate与Struts框架结合编写简单针对修改练习

    失败页面fail.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" ...

  7. 3. 解析 struts.xml 文件

    1. struts.xml 文件基本配置: 主要放在资源路径下,配置 sturts2相关的 Action , 拦截器等配置 <struts> <!-- 设置常量 --> < ...

  8. Struts+Spring+Hibernate项目的启动线程

    在Java Web项目中,经常要在项目开始运行时启动一个线程,每隔一定的时间就运行一定的代码,比如扫描数据库的变化等等.要实现这个功能,可以现在web.xml文件中定义一个Listener,然后在这个 ...

  9. Struts 原理

    今天开始接触公司的框架,叫YNA,三个字母应该是雅马哈的缩写,这个框架听公司前辈说功能很强大,但实际上我看不懂.哈哈...... 其中整合了SSH框架,接下来我说下Struts的一些原理 其实这张图就 ...

  10. axis2+struts拦截地址冲突问题

    axis2和struts在整合过程中,struts会把axis的地址也拦截了,默认当成一个action处理, 会因为找不到action而报错: <!-- struts配置 --> < ...

随机推荐

  1. pptpvpn记录用户登录和流量信息

    这个问题困扰了我很久,终于在pppd的man文档里,发现了踪迹.在man中的SCRIPTS下有一系列的参数,其中PEERNAME就是登陆的用户名,并且在/etc/ppp/ip-up和/etc/ppp/ ...

  2. C#变成数据导入Excel和导出Excel

    excel 基础 •整个excel 表格叫工作表:workbook:工作表包含的叫页:sheet:行:row:单元格:cell. •excel 中的电话号码问题,看起来像数字的字符串以半角单引号开头就 ...

  3. Seven Python Tools All Data Scientists Should Know How to Use

    Seven Python Tools All Data Scientists Should Know How to Use If you’re an aspiring data scientist, ...

  4. [状压dp]POJ1185 炮兵阵地

    中文题 题意不再赘述 对于中间这个“P” 根据dp的无后效性 我们只需考虑前面的 就变成了 只需考虑: 也就是状压前两行 具体与HDOJ的4539类似: 看HDOJ 4539 仅仅是共存状态的判断不同 ...

  5. 166. Fraction to Recurring Decimal

    题目: Given two integers representing the numerator and denominator of a fraction, return the fraction ...

  6. div+css实现导航示意箭头

    1.Div的宽高为100 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <h ...

  7. Visual Studio Solution Configuration

    https://msdn.microsoft.com/en-us/library/bb166577.aspx Solution configurations store solution-level ...

  8. 国内的一些开源镜像站汇总,EPEL源

    国内的一些开源软件的镜像站 汇总 CentOS6.5安装 EPEL 源 国内高校的开源镜像站 中国科学技术大学(debian.ustc.edu.cn)    上海交通大学(ftp.stju.edu.c ...

  9. BZOJ_1096_[ZJOI2007]_仓库建设_(斜率优化动态规划+单调队列+特殊的前缀和技巧)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1096 有\(n\)个工厂,给出第\(i\)个工厂的到1号工厂的距离\(x[i]\),货物数量\ ...

  10. 巧架个人BT服务器

    BT的流行比之当年的江湖,传奇等的流行有过之而无不及.现在我们常说的话题是:“今天你BT了吗?”哇K!兄弟们你们怎么吐了?!假如你还不知道BT是什么,那似乎证明你已经到了归隐Internet的时候了, ...