<!--
@page { margin: 2cm }
P { margin-bottom: 0.21cm }
-->
因为在公司用的是内部开发的一套开发框架,虽然原理上和目前主流的框架思想上基本一致,但是用了一年多还是有些晦涩难懂,最近做个小系统玩,就重温一下久违了的struts2,spring2.5,ibatis框架
先介绍一下这个玩具系统的功能点,系统中有两个核心对象,开发者(Isv)和应用(App),开发者和应用之间是一个一对多的关联关系,而这个系统的核心作用就是让系统管理人员将应用和开发者信息录入到系统中进行管理,然后一个用户(User)登录功能,其实就是3个表增删改查操作
在这个以技术框架学习为目的的玩具系统里,我们尽量使用开源的框架,我采用的是Struts2+Spring2.5+Ibatis,Sitemesh做页面装饰器,Mysql5做后台数据库,Maven2做系统的构建工作,Junit3+Spring2.5
Test+DbUnit作为系统的单元测试框架,Jetty作为Web容器,好了,是时候动手吧这一坨的东西搞到一起来了
1.项目环境搭建过程
1.1新建Maven工程coreapp
Maven真是一个伟大的项目,有了他,一切都变得简单起来,在Eclipse中创建一个Maven项目--前提是Eclipse中安装了m2clipse插件,有了这个插件,工作起来如虎添异,如图
在下一步的页面中输入要创建应用的名称和工作保存路径,到下一步的时候进入选择Archetype页面,我们的框架用的是Struts,所以在Filter中输入struts关键字,与Struts相关的Archetype就都跑出来了,这里我们选择第一个struts2-archetype-starter,然后继续往下走,是项目的groupid和package设置,输入一下,点击一下完成,然后就是见证神奇的时刻--Maven自动给我们创建了一个简单的web程序,所有项目的目录都生成好了,包括Struts的配置文件,Spring的配置文件Struts2与Spring的集成,Struts2与Sitemesh的集成,与DWR的集成--框架都给我们生成出来了!--伟大的maven~,然后我们切换到命令行下运行一个mvn
jetty:run命令,maven就会自动打包部署启动jetty,启动完毕后,我我们通过url请球http://localhost:8080/coreapp就能看到Maven给我们的生成的框架Demo了
1.2Maven给我们的项目里自动搞进去一些神马东西?
1.2.1pom.xml文件
这个是Maven的核心文件,先从这里面去瞧瞧,可以看到Maven把Struts2的jar包依赖,Sitemesh的依赖,Spring的依赖,Junit的依赖,DWR的依赖都自动给我们添加进来了,那么生成的这个东西无非就是围绕这些东西展开的
1.2.2web.xml
web程序里的机关的入口,看这里面都搞了些什么东西。,
首先看的是几个filter,都是Struts2相关的,第一个是请求拦截的,统一struts2处理,第二个Filter是请求完毕后对当前请求上下文中的数据做清理
<filter>
<filter-name>action2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter>
<filter-name>action2-cleanup</filter-name>
<filter-class>org.apache.struts2.dispatcher.ActionContextCleanUp
</filter-class>
</filter>
这个是Sitemesh的过滤器,要用Sitemesh框架对页面装饰,就必须配置她
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>com.opensymphony.module.sitemesh.filter.PageFilter
</filter-class>
</filter>
看完了这个文件后马上有几个疑问出来了
Q1:Spring与Struts2是怎么集成的?
A1:其实Spring一个核心的功能就是依赖注入,在maven提供的空的框架中,也是来这么做的。Struts2的Action也可以当成一个bean交给Spring管理吗?可以的,我们来看一下具体是怎么配置实现的。
看一下Spring的bean配置文件applicationContext.xml—位于src/main/resources下,配置Action
Bean的一个Demo--登录响应Action为例
<bean
id="loginAction"
class="com.taobao.top.coreapp.web.action.LoginAction"
parent="baseAction"
scope="prototype">
</bean>
注意这个Action
Bean和我们熟悉的DAO或Manager的配置不太一样,有个bean的属性
scope='prototype',这是因为Spring默认所有的bean都是单例的(singleton),即初始化一次以后,以后所有的请求都会共享这一个实例,这个对于那些没有状态变化的对象是非常有效的,能大大减少对象创建的次数和开销,但是对于Struts2的Action,大家都知道,他的Action中是有成员变量的,这些成员变量将会被输出到页面上或从页面参数中直接装配值--这些对象的状态是变化的,如果和其他Bean都配置成一样单例,那么所有的请求都有可能更改这个共享对象的状态,所以这里必须采用prototype的方式来配置--每来一个请求Spring容器都会返回一个新的对象,这样多个请求之间的参数就不会被相互篡改了。
Q2:只要在Spring中配置一下就可以了吗?struts2有自己的那个struts.xml文件里不用配置了吗?
Spring配置文件中只是声明了这个bean,具体Struts2与spring
bean之间互通的机关还是要在struts.xml中配置的。看一下src/main/resources下的struts.xml文件,里面的内容一般包含以下几个元素(没有列出的元素文档的后方会提到)
<constant
name="struts.devMode"
value="true"
/>
<package
name="coreapp-common"
extends="struts-default"
namespace="/">
<action
name="login"
class="loginAction">
<result>/index.jsp</result>
<interceptor-ref
name="defaultStack"/>
</action>
</package>
先看一下<constant>这个元素,这个是做什么用的呢?他和struts.properties文件里的那些参数貌似key值是一样的嘛?
是的,struts2的系统级变量设置都是放在struts.properties这个文件中的,里面的配置项都是以key=value的a方式出现的,这个struts.properties文件一般也是放置在classpath下的,Struts2读取这些系统变量的顺序是这样的,现从struts自身的jar包中读取自带的默认配置(org.apache.struts2.default.properties),然后再到应用的classpath下查找struts.properties文件,如果有这个文件,则读取文件中配置项的值,覆盖jar包中的默认配置,如果没有这个文件还是用系统默认,找完struts.properties文件后,继续解析这个struts.xml文件中的constant变量,然后将constant元素的key,value覆盖默认配置,所以更改struts2系统配置项目放在properties文件或xml中还是有这么一点区别的。至于每个常量参数代表什么意思就不再阐述了,struts文档已经有很详细的注释了。
绕了一圈一直在说配置项的加载顺序问题了,看一下具体AAction的配置
<action
name="login"
class="loginAction">
这个Action元素的配置有些奇怪,那个class元素的值应该是指向一个具体的java类才对的啊,这个loginAction是从哪里蹦出来的呢?首先不是蹦出来的,是刚才在我们Q1里通过Spring配置出来的一个Bean的Id!是的,这个action的class要和在spring中为这个action配置的bean
ID保持一致
<bean
id="loginAction"
class="com.taobao.top.coreapp.web.action.LoginAction"
parent="baseAction"
scope="prototype">
</bean>
等等,那struts2又是怎么做到通过普通的acton配置能访问,然后直接写个spring
bean id也能找到的呢?
我们看一下,maven给我们自动生成的这个框架程序中添加了一个struts2-spring-plugin的依赖,是不是这个东西在搞怪呢?是的,这个jar包很简单,只有一个类和一个配置文件truts-plugin.xml,仔细看一下这个文件中的配置,这个文件中也有一个常量定义<constant
name="struts.objectFactory"
value="spring"
/>原来struts2自身也是一个小的容器,用来管理那些Action,Interceptor的创建和销毁,默认struts2使用自己的ObjectFactory来管理这些对象的,Spring与Struts集成插件对这个ObjectFactory类做了扩展,可以看到,在这个文件中还有个配置项
<bean
type="com.opensymphony.xwork2.ObjectFactory"
name="spring"
class="org.apache.struts2.spring.StrutsSpringObjectFactory"
/>
<contant>元素里的那个value=spring就是定位到这个
name=spring的bean上,这样通过扩展ObjectFactory的方式来达到将struts自身的bean与spring
bean打通的效果,通过一种很优雅的方式就将action的代理权交给了spring--针对接口编程的魅力,
Q2:Struts2是怎么用到Sitemesh达到装饰效果的?
网上可以搜到很多关于sitemesh的资料,在这个小项目里,用的也是很通用的方式,在web.xml中配置的sitemeshFilter对所有请求拦截,然后判断该请求是否满足被装饰的条件—WEB-INF/decoretor.xml文件中有配置<excludes>即不需要被装饰的页面在这里配置,支持正则表达式,然后判断当前请求满足哪个装饰器
<decorator
name="main"
page="main.jsp">
<pattern>/*</pattern>
</decorator>
然后到具体的装饰器页面main.jsp中,这个装饰页面定义了页面大的框架逻辑,如下图,一个页面header,footer,left,content几个部分组成,只有content是变化的,其他的都是固定的,就可以通过这个页面来定义好整个站点的规则
一个典型的装饰页面的代码实例
<htm>
<head>
<title><decorator:title
default="企业信息管理系统"
/></title>
<link
src=”main.css”/>
</head>
<body
<decorator:getProperty
property="body.onload"
writeEntireProperty="true"/>>
<div
id='header'>
这里是公共头的内容
</div>
<div
id=”left”>
这里是左侧菜单栏
</div>
<div
id=”content”>
<decorator:body/>这个是具体页面的body部分
</div>
<div
id=”footer”>
页脚部分
</div>
<body>
</htm>
<decorator:title>标签
用于获取被装饰页面<head>元素中<title>子元素的值,如果没有,则设置为默认值
default
<decorator:getProperty
property="body.onload"
writeEntireProperty="true"/>
在body上一般都会加上这行代码,因为具体子页面可能会为<body>元素添加onload时间,而装饰页面必须获取这个事件脚本
<decorator:body/>这个元素的作用就是获取被装饰页面的body部分内容
Sitemesh是怎样处理这些页面然后输出最终的结果的呢?
装修页面提供一个打的html框架,然后分别解析被装饰页面的head,通过<decorator:head>元素读取出来,然后添加到框架的head元素后面,然后通过<decorator:title>读取页面名字,通过<decorator:body>元素读取被装饰页面的body部分,然后sitemesh把各个部分解析后的html组装成最终的html大字符串,输出到页面,可以看出,这种处理方式对于大请求的应用还是有性能问题的,这么大个一坨字符串处理起来可不是个小的开销
简单总结一下,到目前这个阶段一切还是比较顺利的,很大部分归功与maven的自动化,对一堆的框架各自的职责和运行机制有所了解,接下来的几篇文章将后介绍在实际开发过程中遇到的一些问题和解决思路
分享到:
相关推荐
**微信小程序项目源码-校友林微信小程序+SSM框架+论文.rar 功能介绍** 校友林微信小程序是一个专为高校打造的互动交流平台,旨在促进校友间的联系与回忆。结合SSM框架(Spring、SpringMVC、MyBatis)的强大后端支持...
专题研究:重温“信贷脉冲”-0217-浙商证券-11页.pdf
本文不作为一篇严谨的理论推导文章,仅为博主学习时的随手小记,个人的主观认知为主,以求日后能在较快时间内理清思路,找到当下的学习状态。文章中会尽量避免出现过多公式及推导,如果能有幸给其他朋友带来一些帮助...
经典重温C#开发------------------------------------------------------------------------------------------------------------------------------------------------
重温老三篇心得体会精选13篇.doc
因为第Spring_2501_Registration_3到Spring_3301_Registration_11需要使用SSh整合的jar包组合,我把这个jar包组合抽出来放到lib目录中了。用的时候需要把这个jar包组合复制到WebRoot\WEB-INF\lib下面。没办法,这里...
重温微积分 - 齐民友
---Day01SpringBoot基础重温篇.mp4 ---Day02SpringBoot核心原理篇.mp4 ---Day03SpringBoot完美收官篇.mp4 优秀作业名单 ---Day01优秀作业名单(排名不分先后).txt ---Day02优秀作业名单(排名不分先后).txt 源码和软件...
重温计算机的发展史-多图展示历史上各种各样的电脑.pdf
重温老三篇心得体会六篇.doc
齐民优经典微积分教程,打开新世界的大门!!相对于枯燥无味的高数教材,这本书能带来不一样的启发和更为深入地理解
八年级历史上册 第11课 重温长征路教案 华东师大版-华东师大版初中八年级上册历史教案.doc
在 C#中的委托和事件 一文的后半部分,我向大家讲述了Observer(观察者)模式,并使用委托和事件实现了这个模式。实际上,不使用委托和事件,一样可以实现Observer模式。在本文中,我将使用GOF的经典方式,再次实现一...
(1)本项目使用场景: 在Web前端开发中,可以使用这个项目来练习和巩固HTML5、CSS3和JavaScript等前端技术。同时,也可以将这个项目作为游戏开发的入门实践,了解游戏开发的基本流程和技能要求。 (2)游戏介绍: ...
20190407-国泰君安-通信设备及服务行业:重温传统视频会议的三生三世,揭示云视频行业的十里桃花.pdf
NULL 博文链接:https://i8i8i8.iteye.com/blog/445946
本文不作为一篇严谨的理论推导文章,仅为博主学习时的随手小记,个人的主观认知为主,以求日后能在较快时间内理清思路,找到当下的学习状态。文章中会尽量避免出现过多公式及推导,如果能有幸给其他朋友带来一些帮助...
恐龙来袭-重温侏罗纪.ppt
PPT模板-重温春夏秋冬(动态.dpt