用spring开发非web应用的时候spring osgi web开发MVC怎么运用

  今年我一直在思考web开发里的前后端分离的问题,到了现在也颇有点心得了,随着这个问题的深入,再加以现在公司很多web项目的控制层的技术框架由struts2迁移到springMVC,我突然有了一个新的疑问无法得到正确的解释,为什么我们现在做java的web开发,会选择struts2或者springMVC这样的框架,而不是使用servlet加jsp这样的技术呢?特别是现在我们web的前端页面都是使用velocity这样的模板语言进行开发,抛弃了jsp,这样的选择又会给我们java的web开发带来什么样的好处,延着这个问题的思路,我又发现新的疑问,为什么现在很多java企业级开发都会去选择spring框架,spring框架给我们开发的应用带来了什么?这么一想还真是问倒我了,我似乎很难找到一串能让人完全信服的答案,最终我发现,这些我认为我很熟悉很常用的技术,其实还有很多让我陌生不解的地方,这些陌生和不解的地方也正是我是否能更高层次使用它们的关键,今天这篇文章我就来讲讲这些问题,不过struts2,spring这样的技术经过这么多年的积累已经是相当庞大和复杂,它们的面很广,本人虽然已经用了它们多年,还是有很多技术不熟悉和不清楚,所以本文不是全面对我题目做出解答的文章,而是根据我现有知识结构来理解这个问题。
  软件里有很多优秀的框架,有一种类型的框架,它的特点是建立在一个现有技术的基础上,提供和现有技术一样业务功能的技术框架,这个新的技术框架比原技术更加易用,更加健壮同时功能更加强大,例如:jQuery,以及本文所要谈到的struts2和springMVC,深究这些框架都是相当之复杂,但是它们的优点其实只有一个:就是让使用者只关心核心业务的开发,框架帮你屏蔽原有技术跟业务开发无关的各类技术问题。像jQuery,struts2或springMVC这类框架之所以优秀,就是它们在这点上做的太好了,以至于很多使用它的程序员都已经不清楚原有技术的真实面目,因此我们要将struts2理解的更好,使用的更加熟练和深入,这里我们就要跳出struts2的技术,到struts2技术的源头servlet,仔细研究下servlet的特点,只有这样我们才能把struts2框架学的更好。
  Servlet的作用是接收浏览器传给服务端的请求(request),并将服务端处理完的响应(response)返回给用户的浏览器,浏览器和服务端之间通过http协议进行沟通,其过程是浏览器根据用户的选择将相关信息按http协议报文的规范组装请求的http报文,报文通过网络传输到指定的服务器,服务器通过特定的web容器接收这个报文信息,例如:tomcat,jetty,jboss这样的web容器,web容器会将http报文解析出来,如果是用户请求,最终解析出来的报文信息会用一个request对象存储起来,服务端使用这个request做完相应的处理后,服务端程序将结果信息封装到response对象里,然后将response对象交给web容器,web容器则把这个response对象转变为http协议的报文,并将报文回传给浏览器,浏览器最后解析这个响应报文,将最终结果展示给用户。
  Web容器创造了servlet接口,servlet接口就是开发人员自己实现业务逻辑的地方,程序员开发servlet就好比做填空题,而填空题的语境或者说上下文提示就是由request和response对象,但是javaEE规范里的servlet接口很简单,就三个方法init,service和destory,但是这个接口太笼统,所以规范里还提供了一个HttpServlet类,这个类根据http请求类型提供了doGet,doPost等方法,servlet接口最大的特点就是根据http协议的特点进行定义,因此做servlet开发时候如果使用者对http协议特点不是特别熟悉,都会碰到或多或少令人迷惑的问题,特别是碰到一些复杂特殊的请求时候:例如文件上传,返回特殊的文件格式到浏览器,这时候使用servlet开发就不是很方便了,servlet开发还有个问题可能大家常常被忽视,就是请求的数据的类型转化,http协议传输都是文本形式,到了web容器解析后也是文本类型,如果碰到货币,数字,日期这样的类型需要我们根据实际情况进行转化,如果页面传送的信息非常多,我们就不得不做大量类型转化,这种工作没有什么技术含量,是个体力活而且很容易导致程序错误。同时java的企业开发都是围绕javabean进行,类型转化好的数据还要封装到对应的javabean里,这种转来转去的事情对于项目开发绝对不是什么好事情,所以古老的struts1为这种问题找到了一种解决方案,就是定义了一个DTO对象(数据传输对象),专门负责做这样的事情,不过到了struts2,整个替代servlet的action本身就是一个javabean。
  Java的企业开发一个技术特点就是使用javabean进行的,struts2的特点之一就是它替代servlet的操作类就是一个典型的javabean,首先struts2框架将页面传输的数据进行类型转化和封装后将请求信息封装到了这个javabean的属性里,这样我们开发web程序时候就省去了烦心的类型转化和封装的问题,前面我讲到传统的servlet是根据http协议进行定义的,它会按你请求方式(post还是get方式)来处理用户的请求,但是对于一名程序开发人员而言,一个请求,具体到一个url,其实对于服务端而言就是服务端对外提供的一个功能,或者说是服务端对外的一个动作,如果我们使用servlet开发程序我们就得把http的动作转化为具体的业务动作,这就让程序开发变得繁琐,增强了开发的难度,所以struts2替代servlet的javabean就屏蔽了servlet里http的请求方式和具体业务动作转化的问题,javabean里的每一个方法都可以和每一个url请求一一对应,这必然减轻了开发的难度问题。
Servlet另一个作用就是构造response对象,让页面获得正确的响应,其实现代的浏览器是一个多媒体工具,文字,图片,视屏等等东西都可以在浏览器里显示,资源的不同就会导致http响应报文的差别,如果我们使用servlet开发就要根据资源的不同在java程序里用硬编码的形式处理,这样的程序很难复用,而且如果程序员对某种资源的处理理解不到位,就会导致问题的出现,struts2通过配置文件的形式将这样的逻辑从java程序里剥离出来,使用配置的方式进行统一管理,这个做法和spring的AOP方式类似,这样就让结果处理方式更加统一,更加利于管理,同时也提升了程序的健壮性以及降低了开发的难度。
  Servlet在MVC开发模式里就是其中C层即控制层,控制层就像俄罗斯的双头鹰(一个头向东看一个头向西看)一样,一个头向M层模型层看,一个头向V层视图层看,模型层也是用java编写的,控制层也属于服务端语言开发,所以M层和C层的沟通没有天然的障碍,但是和V层视图层就不一样了,这是一个跨语言的沟通,对于浏览器,它只懂得html,javascript和css,浏览器是理解不了java这种语言的东西,但是要让服务端的东西能被浏览器理解接受,我们就必须得把服务端的响应信息放到页面里,因此就需要一个技术把java的信息转化到html页面里,这就是javaEE规范里提供了jsp技术,jsp其实是一种服务端技术而非客户端技术,不过它看起来似乎更像html技术,最早的jsp开发里都是直接将java代码写到页面里,这种坏处谁都知道,之后javaEE规范提供了自定义标签技术,使用一种类似html标签的方式来解析java代码,struts2框架提供了一整套完整的自定义标签技术,这似乎听起来不算啥,但是它的作用非凡,因为自定义标签之所以叫自定义就是每个人都可以自己来定义,如果没有一个规范必然产生混乱,而且一套完善的自定义标签是个系统工程,一套完整的自定义标签相当于我们在自己定义一套新的开发语言,做程序的人听到这个一定就会明白开发一套完整的自定义标签的工作量和开发难度都是难以想象的,而且自定义标签都是和控制层紧密相连,其难度又会增加一个维度,所以struts2提供的自定义标签对于业务开发带来的将是质的飞越。
  Servlet里还有两个重要的技术:监听器和过滤器,对于监听器在web开发里使用的场景比较少,都是一些十分特别的情况才会使用,大部分web开发里可以忽略它的使用,我们用的最多的监听器可能就是对ServletContext创建和销毁的监听器,ServletContext是整个web应用的全局对象,它和Web应用的生命周期绑定在一起,因此使用这个监听器对Web应用的全局信息进行初始化和销毁操作,例如spring容器的初始化操作。比较有意思的是过滤器,在struts2里有个拦截器,它们的作用相同都是用来拦截请求的,因为拦截器是struts2的特有功能,在struts2里使用拦截器自然比使用过滤器更顺手,其实拦截器所用的技术比过滤器更加先进,因为拦截器使用了反射技术,因此拦截器拦截的面更大,控制请求的能力更强,它能完成的任务也会更加的丰富多彩。
  在我第一次接触struts2时候,有人告诉我struts设计的一个目的就是想屏蔽在控制层里操作request和response对象,因为这两个http协议的儿子会造成web开发里思路的混乱,但是我在实际开发里却经常不自觉的使用这两个对象。而且本人做前端开发非常喜欢使用ajax,使用ajax技术时候我就很讨厌struts2的自定义标签,我更加喜欢在页面里用javascript技术处理各种信息,最终struts2在我眼里就是一个servlet的变体,因此曾经有段时间我常常在想是不是可以抛弃struts2,直接用servlet,因为struts2里用到了太多反射机制,特别是使用注解做配置(注解是用反射实现的),在java里反射的执行效率是非常低的,直接使用servlet一定能提升web应用的执行效率。其实这个倒很难做到,因为当时我没法在servlet里灵活的运用spring技术。
  下面我要谈谈spring了。
  spring技术可以说是java企业开发里最重要的技术,不过真的理解spring的作用和意义还真是一件麻烦的事情,很多人对spring理解其实都是停留在使用阶段(例如:声明式事务很好用等等),当今的spring技术生态环境里可谓是蔚为壮观,spring已经包罗万象,它的内容之多完全不亚于它的本源java语言了,而spring这么大的框都是建立在ioc和aop技术之上,只有深入理解了这两个技术我们才能明白为什么spring这个框能装的下那么多东西了。
  首先是ioc,ioc技术第一个解释叫做控制反转,它还有个解释就是依赖注入,这两个名字很难从字面理解,但是当你理解它的原理后就会发现它们的描述是何等准确。Ioc技术的本质就是构建对象的技术换句话说就是将一个类实例化成对象的技术,在java里实例化类通过new关键字进行的,每次new一个类都会产生一个新的实例对象,这么做视乎很浪费,有时这种浪费还挺危险,因为在程序开发时候我们常常只需要某个类永远只能产生一个的实例对象这个时候就得使用单例模式,此外在设计模式里还可以通过工厂方式产生对象,使用过spring的人看到上面的文字就知道了,spring里bean的定义就和上面的内容一一对应,scope属性single产生单例对象,prototype产生新对象,bean还可以通过工厂方式产生对象,可以说spring的bean就是制造对象的工具。面向对象编程里对象相当于显示生活中的一个实体,例如我们有个对象作用是完成打猎的操作,那么打猎这个对象内部包含两个辅助对象:人和枪,只有人和枪赋予了打猎这个对象,那么打猎对象才能完成打猎的操作,但是构建一个人和枪的对象并不是看起来那么简单,这里以枪为例,要创造一把枪我们需要金属,需要机床,需要子弹,而机床和子弹又是两个新对象,这些对象一个个相互嵌套相互关联,大伙试想下如果我们在java代码里构建一个枪的对象那是何其的复杂,假如我们要构造的不是简单的枪对象而是更加复杂的航空母舰,那么构造这个对象的成本之高是让人难以想象的,怎么来消除这种对象相互嵌套相互依赖的关系了?spring提供了一种方式,这种方式就是spring提供一个容器,我们在xml文件里定义各个对象的依赖关系,由容器完成对象的构建,当我们java代码里需要使用某个实例的时候就可以从容器里获取,那么对象的构建操作就被spring容器接管,所以它被称为控制反转,控制反转的意思就是本来属于java程序里构建对象的功能交由容器接管,依赖注入就是当程序要使用某个对象时候,容器会把它注入到程序里,这就叫做依赖注入。在java开发里我们想使用某个类提供的功能,有两种方式,一种就是构造一个新的类,新的类继承该类,另一种方式则是将某个类定义在新类里,那么两个类之间就建立一种关联关系,spring的ioc容器就是实现了这种关联关系(记住不是继承关系哦),那么某个类要被赋予到新类有哪些办法了?一般只有两种:一种就是通过构造函数,一种就是通过setXXX方式,这也是spring容器使用到了两种标准的注入方式。
  不管是上面说的继承方式,还是关联方式其实都是增强目标对象能力的开发手段,在设计模式里有一种代理模式,代理模式将继承模式和关联模式结合在一起使用,代理模式就是继承模式和关联模式的综合体,不过这个综合体的作用倒不是解决对象注入的问题,而是为具体操作对象找到一个保姆或者是秘书,这就和小说里的二号首长一样,这个二号首长对外代表了具体的实例对象,实例对象的入口和出口都是通过这个二号首长,因为具体的实例对象是一号首长,一号首长是要干大事的,所以一些事务性,重复性的工作例如泡茶,安排车子,这样的工作是不用劳烦一号首长的大驾,而是二号首长帮忙解决的,这就是aop的思想,aop解决程序开发里事务性,和核心业务无关的问题,但这些问题对于业务场景的实现是很有必要的,在实际开发里aop也是节省代码的一种方式。
  Spring的核心技术的作用本质就是一个 沟通机制,spring总是尽全力的让沟通的双方信息畅通,同时降低双方的沟通成本,在现实机构里一个善于沟通的人肯定是该公司的领导,很会沟通的领导能调动起各种资源的积极性,善于沟通的领导就会做到海纳百川,让各种不同人追随他,所以当今的spring就是一个大框,什么都可以往里装。
  Spring很像银行,它不能直接创造物质财富,但是一切资源都要通过它进行流通,它能控制经济发展的走向,回到程序的世界,spring的作用是被标榜为程序之间的解耦,spring能降低不同模块之间的耦合度,原因就是在程序开发里不同模块之间信息的沟通是通过对象传递完成的,而对象能否顺利传递就是要合理的构建好对象,而管理好对象的构建方式就能管理好对象传递,这就是spring给系统架构设计带来的好处。
阅读(...) 评论()使用Spring MVC构建REST风格WEB应用
- Fancy的原创博客 - ITeye技术网站
对于运行在网络上的MIS系统而言,处理数据的是整个系统的主要任务,翻开程序我们可以看到,80%以上的代码都在处理数据的CRUD操作。采用一种什么样的框架结构,能够使得处理数据的操作变得简单且易理解,这是大部分开发者尤其是架构设计者一直以来思考的一个问题。
REST(Representational State Transfer)是一种编程风格,特别是针对网络应用的设计和开发,采用REST可以显著降低开发的复杂性,提高系统的可伸缩性。
REST是一种独特的编程风格,与MVC强调的角色分层概念不同,REST强调使用统一的规则来规范对资源的操作,两者互为补充,相符相成,使用
MVC架构搭配REST编程风格构建基于网络的MIS系统将在不远的为未成为主流。本文着重介绍REST编程风格的核心规则,并且结合Spring
MVC描述REST在实际应用中的代码形态。
使用REST风格开发WEB应用程序强调以下几点规则:
网络上的所有事物都被抽象为资源(resource);
每个资源对应一个唯一的资源标识(resource identifier);
通过通用的连接器接口(generic connector interface)对资源进行操作;
对资源的各种操作不会改变资源标识;
所有的操作都是无状态的(stateless)。
首先,在笔者看来,REST定义中的资源即应用程序所处理的数据。以订单管理系统为例,订单信息就是数据,同样客户信息和产品信息也是数据,在REST看来这些数据都是资源。
REST强调资源必须有具有唯一名称和ID,名称用来区分不同资源,ID用来定位同类资源中唯一的一条数据。在REST中,这些规则都是通过URI
来描述的。还是以上面的订单系统为例,我们将订单信息名称设定为order,客户信息为customer,货物信息为product,那么就存在几下的几
种URI设计:
&!--标识所有的订单信息--&
/rest/order
&!--标识所有的客户信息--&
/rest/customer
&!--标识ID为1的货物信息--&
/rest/product/1
我们可以看出REST风格URI设计的特点:http://host/context/资源名称/[资源ID]。其中资源名称是必选项,资源ID可省略,省略资源ID用来标识一类资源的所有数据。
有了资源和用来标识资源的URI后,REST用连接器来标识对资源的操作。在这里,对资源的操作分为查询/获取、创建、删除、修改四种。在网络编程环境下,REST用HTTP协议作为连接器,用HTTP Method(请求方法)标识操作类型:
HTTP GET:查询和获取资源;
HTTP POST:创建资源;
HTTP PUT: 修改资源;
HTTP DELETE: 删除资源。
在完成资源和连接器两个核心概念的定义后,我们已经可以大体勾勒出REST风格编程的基本思路:
抽象和定义系统中的资源;
使用REST风格的URI将请求与资源进行绑定;
使用HTTP请求对资源进行操作;
还用上面提到的订单系统为例,请看下面的例子:
&!--查询类别为服装的货物信息--&
GET /rest/product HTTP/1.1
productType 服装
&!--查询ID为1的订单信息--&
GET /rest/order/1 HTTP/1.1
&!--删除ID为1的货物信息--&
DELET /rest/product/1 HTTP/1.1
&!--创建一条订单信息--&
POST /rest/order HTTP/1.1
field1 value1
field2 value2
简单的说,URI加上HTTP METHOD构成了REST处理数据的核心规则:URI确定了操作的对象,HTTP METHOD则确定了操作的方式。
与传统处理数据的方式不同,如果不使用REST,那么操作的对象和操作方式将混合在URL设计中,正如首次提出REST概念的Roy T.
Fielding博士所说的:“REST允许我们通过url设计系统”。事实上Roy也是Web协议的主要设计者,正是在他的参与下完成了HTTP1.1
规范的制定。
站在另一个角度,REST强调资源(数据)的概念,一切操作围绕特定资源展开,离开了资源,REST就失去了存在的意义。在这一点上,REST所倡导的思想与时下流行的Ajax的编程风格有着异曲同工之妙。
Ajax强调数据与展现分离,后台应用程序致力于生产数据,前台使用脚本进行数据的展示。对于数据的组织与传输Ajax并没有内置的支持。而
REST强调通过URI将请求与资源进行绑定,如果将REST与Ajax技术进行结合,则可以形成有效的互补,我们不妨将上面提到的编程思路进行扩展,仍
然以获取ID为1的订单信息为例:
Ajax发起请求:/rest/order/1;
通过REST风格的URI设计将请求与后台实体进行绑定;
后台实体返回包含产品信息的JSON/XML数据;
前台使用脚本进行数据的展示。
我们用Spring MVC来实现上面描述的过程,作为主流的MVC产品,Spring MVC天然支持REST编程风格,所以使用Spring MVC来搭建REST风格的应用程序将变得异常简单。
Spring MVC使用特殊的标注对Handler对象进行修饰,使得Handler能够处理REST风格的请求,我们来看几个例子:
* 按ID值获取订单信息
* @param id
@ResponseBody
@RequestMapping(value = "/order/${id}", method = RequestMethod.GET)
public OrderEntity getOrder(@PathVariable int id) {
return orderManager.get(id);
* 按类型查询货物信息
* @param id
@ResponseBody
@RequestMapping(value = "/product", method = RequestMethod.GET)
public List&ProductEntity& getProductByType(String type) {
return productManager.queryByType(type);
* 创建订单信息
* @param id
@RequestMapping(value = "/order", method = RequestMethod.POST)
public void createOrder(OrderEntity entity) {
orderManager.create(entity);
* 修改订单信息
* @param id
@RequestMapping(value = "/order/${id}", method = RequestMethod.PUT)
public OrderEntity updateOrder(@PathVariable int id, OrderEntity entity) {
return orderManager.update(entity);
* 删除指定ID值的订单信息
* @param id
@RequestMapping(value = "/order/${id}", method = RequestMethod.DELETE)
public void deleteOrder(@PathVariable int id) {
orderManager.delete(id);
通过上面的例子可以看出,使用Spring MVC编写REST风格的应用程序是多么的简单。
需要我们注意的是,REST要求资源的标识是不变的,也就是说对于特定的资源,无论对这个资源作了什么样的操作,资源的ID不可以改变。之所以加入
这样的限制是为了保证URI的一致性。试想如果某个操作在处理过程中改变了资源的标识,那么为了保证规则的完整性,我们必须付出额外的代价去在其它的处理
中同步这些变化,这在REST中是不可接受的。
另一方面,REST要求针对资源的所有操作必须是无状态的,URI是确定资源的唯一途径。如果我们在处理数据的过程中融入了状态数据,那么针对同一资源的URI就会出现二义性,这将与REST的定义背道而驰。
更多精彩原创文章请关注笔者的原创博客:
浏览: 22492 次
来自: 大连
能否把依赖的jar包也一起共享下吗?
fancy888 写道宇宙浪子 写道请问有Spring Sec ...
宇宙浪子 写道请问有Spring Security版本对oAu ...
请问有Spring Security版本对oAuth2.0实现 ...
受教了。。。。1778人阅读
Spring(10)
转载请注明出处:
============
首先Spring MVC是基于三个层面来开发的,那三个层面呢?
M(model) - 模型层,控制器完成逻辑处理后,通常会产生一些信息,而这些信息需要返回给用户并在浏览器上显示的,我们把这些信息称为模型;
V(view) - 视图层,我们使用JSP作为视图层,通过视图能使这些模型数据渲染输出,并通过这个输出响应的对你传递给客户端;
C(controller) - 控制层,从用户提交请求开始,这些请求都会通过一个前端控制器Servlet,然后经过前端控制器Servlet的解析,再将用户请求指定到某一个特定的控制器,即控制层。
三个层的关系:用户提交请求,经前端控制器Servlet解析,再指定控制器,当控制器处理逻辑信息后,返回模型数据,然后再经指定的视图把模型数据渲染输出,终于呈现给客户端,即用户。
2.引入spring mvc jar包
因为我之前的文章介绍过Maven的使用(项目是用Maven搭建的),我们这里就使用Maven的依赖来关联下载spring的jar包吧。
如果不知道怎么来配置依赖的话,进入网址:&,这里提供jar包依赖的查询等。
首先,搜索需要的,如图:
下面还有一大堆相关的列表,找到我们需要的或者你可以输入命名搜索会更快
点击进去,选择版本
点击进去,把依赖复制出来到你的pom.xml中,即可
pom.xml配置:
&!-- 定义属性,供${propertieName}访问 --&
&properties&
&project.build.sourceEncoding&UTF-8&/project.build.sourceEncoding&
&spring.version&4.1.3.RELEASE&/spring.version&
&/properties&
&!-- 依赖关联 --&
&dependencies&
&dependency&
&groupId&org.springframework&/groupId&
&artifactId&spring-webmvc&/artifactId&
&version&${spring.version}&/version&
&/dependency&
&/dependencies&
&/project&
完之后,执行pom.xml update
看,相关联的jar都会下载到本地仓库,这就是使用Maven的好处!
3.配置一个前端控制器Servlet
Spring MVC中,所有的请求的必经之路为一个前端控制器Servlet,即DispatcherServlet,它是Spring MVC的核心。
DispatcherServlet必须在Web应用程序的web.xml文件中进行配置,配置如下:
&?xml version=&1.0& encoding=&UTF-8&?&
&web-app...&
&!-- spring mvc 前端控制器 --&
&servlet-name&wwo&/servlet-name&
&servlet-class&org.springframework.web.servlet.DispatcherServlet&/servlet-class&
&init-param&
&param-name&contextConfigLocation&/param-name&
&param-value&
classpath:conf/wwo-servlet.xml
&/param-value&
&/init-param&
&load-on-startup&1&/load-on-startup&
&/servlet&
&servlet-mapping&
&servlet-name&wwo&/servlet-name&
&url-pattern&/&/url-pattern&
&/servlet-mapping&
&/web-app&
DispatcherServlet的目的既是为了根据一个XML文件来加载其配置到Spring应用上下文中,xml文件的命名方式是默认通过&servlet-name&来指定的XML的文件名,即我们常见的${&servlet-name&}-servlet.xml,如上述例子xml文件命名为:wwo-servlet.xml(默认路径位于应用程序的WEB-INF目录下)。通常我们spring的配置文件可以分成多个XML文件,一个用于服务层,一个用于持久层还有一个用于数据源配置。那怎么办呢?
spring 为我提供了一个ContextLoaderListener,它是一个Servlet监听器,我们只需将ContextLoaderListener配置于web.xml文件里即可,配置如下:
&?xml version=&1.0& encoding=&UTF-8&?&
&web-app ...&
&!-- spring监听器 --&
&listener&
&listener-class&
org.springframework.web.context.ContextLoaderListener
&/listener-class&
&/listener&
&/web-app&但,一般这样配置监听器的话,它会默认去加载/WEB-INF/applicationContext.xml这个spring配置文件。
如果我们要指定spring配置文件的名字或加载多个spring xml配置文件的话,我们需要这样配置:
&?xml version=&1.0& encoding=&UTF-8&?&
&web-app ...&
&!-- spring监听器 --&
&listener&
&listener-class&
org.springframework.web.context.ContextLoaderListener
&/listener-class&
&/listener&
&!-- 指定监听器加载指定的spring xml配置文件 --&
&context-param&
&param-name&contextConfigLocation&/param-name&
&!-- 分别对应的是数据源、服务层、持久层、安全 --&
&param-value&
classpath:conf/dataSource-context.xml
classpath:conf/service-context.xml
classpath:conf/persistence-context.xml
/WEB-INF/wwo-security.xml
&/param-value&
&/context-param&
&/web-app&
好了,这样spring的xml配置文件就分得很清楚了!
但是,这里有个问题,就是所有的请求都经过这个监听器,包括对静态资源的请求,问题就在这。如果是静态资源,怎么办呢?
显示我们还要对所谓的静态资源进行处理,spring为我们提供了&mvc:resources&元素可以处理这个问题,service-context.xml文件配置如下:
&?xml version=&1.0& encoding=&UTF-8&?&
&beans xmlns=&http://www.springframework.org/schema/beans&
xmlns:xsi=&http://www.w3.org/2001/XMLSchema-instance&
xmlns:mvc=&http://www.springframework.org/schema/mvc&
xsi:schemaLocation=&
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd&&
&!-- 对静态资源的处理 --&
&mvc:resources
location=&/JScript/**&
mapping=&/JScript/& /&
这样就对URL包含/JScript/的请求,即对应位于/JScript/下的所以资源来进行特别处理!
注:关于DispatcherServlet与ContextLoaderListener解释请参阅:
4.配置注解驱动的Spring MVC
好了,不多说!现在spring已经大部分能使用注释来代替从前要在配置文件里所做的事,接下来我们大部分会使用注释方式来完成。
a.定义控制器
DispatcherServlet需要咨询一个或多个处理器来明确地将请求分发给那个控制器。Spring提供了许多处理器映射实现,那我们只需要DefaultAnnotationHandlerMapping来实现即可。
DefaultAnnotationHandlerMapping:将请求映射给使用@requestMapping注解的控制器和控制器方法。
首先要作用注解,你必需把注解的类及方法等加载到上下文应用中,即spring容器,才能使用!
我们需要在配置文件中加上以下配置,即可实现注解功能:
&!-- 扫描指定包下的注解 --&&/span&
&context:component-scan base-package=&com.blog&&
&!-- 配置组件过滤器 --&
&!-- 指定扫描的包 --&
&context:include-filter type=&annotation& expression=&com.blog.controller&/&
&!-- 指定不需要扫描的包 --&
&context:exclude-filter type=&annotation& expression=&com.blog.dao&/&
&/context:component-scan&
注:上面只是为了举例说明
下面配置基本也够用了,如果不是特别要求:
&!-- 扫描指定包下的注解 --&
&context:component-scan base-package=&com.blog&/&
&/beans&说明:
默认情况下,&context:component-scan&查找使用构造型注解所标注的类,这些特殊的注解如下:
@Component -- 通用的构造型注解,标识该类为Spring组件;
@Controller -- 标识将该类定义为Spring MVC controller;
@Repository -- 标识将该类定义为数据仓库;
@Service -- 标识将该类定义为服务;
使用@component标注的任意自定义注解。
一般为好区分某类属于控制、数据库访问和业务层,会分别使用对应的注解@Controller、@Repository和@Service,而尽量少用@Component,@Component是通用的!
接下来我们可以声明一个登录到主页面(或首页)的控制器:
先把 spring mvc切换到3.x版本的jar吧,之前用的是4.x以上的。
这是因为4.x的注解可能与3.x有点差别,而本例子注重的是3.x版本的开发。
切换配置:
&!-- 定义属性,供${propertieName}访问 --&
&properties&
&project.build.sourceEncoding&UTF-8&/project.build.sourceEncoding&
&spring.version&3.2.13.RELEASE&/spring.version&
&/properties&
&/project&
b.渲染视图
--通过上述的控制器去调用对应的业务层后,然后要将处理的结果告知用户时,我们需要对视图进行渲染,从而显示在客户端上即可!
wwo-servlet.xml文件中配置的代码如下:
原理:逻辑视图名通过添加前缀后缀来确定要视图路径
解析视图,因jsp视图使用了jstl标签,
所以需要通过设置viewClass属于来将InternalResourceViewResolver替换为JstlView --&
&bean class=&org.springframework.web.servlet.view.InternalResourceViewResolver&&
&property name=&viewClass& value=&org.springframework.web.servlet.view.JstlView&/&
&property name=&prefix& value=&/&/&
&property name=&suffix& value=&.jsp&/&
上面是我常用渲染视图的配置方法,但我们接下讲的是通过Apache Tiles布局管理器来渲染!
Apache Tiles:对于一般的web应用程序,InternalResourceViewResolver视图基本够用了。但对于一些复杂的web应用,就应该使用Apache Tiles布局管理器了,好处是它可以使一些通用的元素(或页面)被页面所共享,从而达到元素的重用。
官方网址:
wwo-servlet.xml文件中配置的代码如下:
Apache Tiles 代替 JstlView
要是希望一些通用的元素被页面共享,则可以使用Apache Tiles布局管理器。
通过Spring MVC配置解析Tiles的布局视图!
建立视图解析器:TilesViewResolver;
加载Tiles的定义:TilesConfigurer;
由TilesConfigurer加载tiles定义,并使用TilesViewResolver解析视图。
views.xml为tiles的定义文件,它们都分散在/WEB-INF/views/目录下;
/WEB-INF/views/**/views.xml:**,查找/WEB-INF/views/目录下的所以views.xml文件
&bean class=&org.springframework.web.servlet.view.tiles2.TilesViewResolver&/&
&bean class=&org.springframework.web.servlet.view.tiles2.TilesConfigurer&&
&property name=&definitions&&
&value&/WEB-INF/main-tiles/main-tiles.xml&/value&
&/property&
我们再来看看/WEB-INF/main-tiles/main-titles.xml文件的配置:
&?xml version=&1.0& encoding=&UTF-8&?&
&!DOCTYPE tiles-definitions PUBLIC
&-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN&
&http://tiles.apache.org/dtds/tiles-config_2_1.dtd&&
&tiles-definitions&
定义通用的布局
&definition name=&template& template=&/blog/main/main_template.jsp&&
&put-attribute name=&top& value=&/blog/main/title.jsp&/&
&/definition&
定义main的tiles
&definition name=&main& extends=&template&&
&put-attribute name=&content& value=&/blog/main/main.jsp&/&
&/definition&
&/tiles-definitions&
注:这里definition标签的属性name是对应控制层,return返回的逻辑视图名。
再下来,看在main_template.jsp中怎么来配置使用,来达到重用的目的的。
也就是说,main_template.jsp可以由若干个.jsp页面组成!
main_template.jsp文件:
&%@ page language=&java& contentType=&text/ charset=UTF-8&
pageEncoding=&UTF-8&%&
&%@ taglib prefix=&t& uri=&http://tiles.apache.org/tags-tiles& %&
&!DOCTYPE html PUBLIC &-//W3C//DTD HTML 4.01 Transitional//EN& &http://www.w3.org/TR/html4/loose.dtd&&
&meta http-equiv=&Content-Type& content=&text/ charset=UTF-8&&
&title&Insert title here&/title&
&style type=&text/css&&
background-color: rgb(95, 2, 2);
&t:insertAttribute name=&top&/&
&t:insertAttribute name=&content&/&
&/html&好了,我们可以看到要使用tags-tiles的标签库来达到目的!
main_template.jsp显示的页面:
title.jsp显示的页面:
main.jsp显示的页面:
好了,到此Spring MVC构架完成!
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:214018次
积分:4034
积分:4034
排名:第7204名
原创:173篇
转载:69篇
评论:52条
(3)(12)(13)(10)(5)(2)(2)(5)(8)(5)(5)(5)(3)(2)(1)(2)(3)(7)(15)(1)(9)(20)(34)(42)(20)(1)(2)(6)(4)}

我要回帖

更多关于 spring web模块化开发 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信