Spring初体验

来源:互联网 发布:加入中国籍难吗 知乎 编辑:程序博客网 时间:2024/06/05 04:28

一、简介

  Spring 是一个开源框架,是为了解决企业应用程序开发复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。

 二、框架

Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式,如图 1 所示。


图 1. Spring 框架的 7 个模块
Spring 框架图示 

组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:

  • 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
  • Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
  • Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
  • Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
  • Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
  • Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
  • Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。

Spring 框架的功能可以用在任何 J2EE 服务器中,大多数功能也适用于不受管理的环境。Spring 的核心要点是:支持不绑定到特定 J2EE 服务的可重用业务和数据访问对象。毫无疑问,这样的对象可以在不同 J2EE 环境 (Web 或 EJB)、独立应用程序、测试环境之间重用。

三、核心思想

  Spring的核心思想是IoC和AOP。

   1.Ioc

     Ioc全称Inversion of Control,也可以称为控制反转

     –所谓控制反转就是应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的,样控制权就由应用转移到了外部容器,控制权的转移就是所谓反转
    说到Ioc,还要提一个概念DI,全称Dependency Injection,也可以称为依赖注入
所谓依赖注入就是指:在运行期,由外部容器动态地将依赖对象注入到组件中
     具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在Spring里,创建被调用者的工作不再由调用者来完成,因此称为控制反转;创建被调用者 实例的工作通常由Spring容器来完成,然后注入调用者,因此也称为依赖注入。
由此可以看出,DI和IoC其实是指同一个概念。
Spring依赖注入有两种实现方式,一是通过构造方法,二是通过setter方法。
方式一:


方式二:


2.AOP
AOP是Aspect Oriented Programming的缩写,也可以称为面向切面编程(也叫面向方面编程),是对OOP(面向方面编程)的有益补充。
AOP将应用系统分为两部分,核心业务逻辑及横向的通用逻辑,也就是所谓的方面,借住这一思想可以通过减少代码重复模块从而帮助开放人员提供工作效率。
AOP相关概念
Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面横切性关注点的抽象
joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring,这些点指的是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器)
Pointcut(切入点):所谓切入点是指我们要对那些joinpoint进行拦截的定义.
Advice(通知):所谓通知是指拦截到joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知
Target(目标对象):代理的目标对象即被代理的对象
Weave(织入):指将aspects应用到target对象并导致proxy对象创建的过程称为织入
Introduction(引入):在不修改类代码的前提下,Introduction可以在运行期为类动态地添加一些方法或Field.
Advice类型:
前置通知(Before advice
某连接点(joinpoint)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)
返回后通知(After returning advice
某连接点(joinpoint)正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。
抛出异常后通知(After throwing advice
 在方法抛出异常退出时执行的通知。 
后通知(After (finally) advice
当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
-环绕通知(Around Advice: 包围一个连接点(joinpoint)的通知,如方法调用。这是最强大的一种通知类型。环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。
Spring默认使用JDK动态代理实现AOP代理。这使得任何接口或 接口的集合能够被代理
Spring也可以用CGLIB代理。这是代理类,而不是接口。如果业务对象没有实现一个接口,CGLIB被默认使用
Spring AOP编程的切面可以采用以下两种声明方式
基于xml的声明方式
基于@Aspectj注解的声明方式
下面以xml方式的为例,

配置文件如下:

四、Spring Context
context 的基础是 ApplicationContext 接口,它继承 BeanFactory 接口,并提供BeanFactory 所有的功能。
Spring中的几种容器都支持使用xml装配bean,包括: 
    XmlBeanFactory , 
    ClassPathXmlApplicationContext , 
    FileSystemXmlApplicationContext , 
    XmlWebApplicationContext 
加载这些容器的配置文件的xml有一下几种常见的方法: 
1:引用资源 用XmlBeanFactory(不能实现多个文件相互引用)   
Resource resource = new ClassPathResource("appcontext.xml"); 
      BeanFactory factory = new XmlBeanFactory(resource); 
 从factory中获取相应资源文件中的bean,但是这种bean读不到引用了其他文件中的bean!
2:引用应用上下文 用ClassPathXmlApplicationContext       
ClassPathXmlApplicationContext从类路径中的XML文件载入上下文定义信息,把上下文定义文件当成类路径资. 
 ApplicationContext factory=new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); 
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");//加载单个配置文件   
3:用文件系统的路径引用应用上下文 用FileSystemXmlApplicationContext  
 FileSystemXmlApplicationContext从文件系统中的XML文件载入上下文定义的信息.
 ApplicationContext factory=new FileSystemXmlApplicationContext("src/applicationContext.xml");      
ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml"); //加载单个配置文件 
4:Web工程定制的加载方法 XmlWebApplicationContext
XmlWebApplicationContext从WEB系统中的XML文件中载入上下文定义的信息   
ServletContext servletContext = request.getSession().getServletContext();    
ApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext ); 
五、SpringMVC
 1、简介
Spring的Web模型-视图-控制器(MVC)框架是围绕DispatcherServlet设计的,它把分派请求处理程序,可配置的处理程序映射、视图解析、本地语言和主
解析以及支持上传文件。默认的处理程序是基于@ controller和@RequestMapping注释,提供一个广泛的灵活的处理方法。通过引入Spring 3.0的
controller机制还允许您创建RESTful Web站点和应用程序,通过@PathVariable注释和其他特性。
2、核心类和接口

DispatcherServlet   -- 前置控制器

 

HandlerMapping接口 -- 处理请求的映射

HandlerMapping接口的实现类:

SimpleUrlHandlerMapping  通过配置文件,把一个URL映射到Controller

DefaultAnnotationHandlerMapping  通过注解,把一个URL映射到Controller类上

 

HandlerAdapter接口 -- 处理请求的映射

AnnotationMethodHandlerAdapter类,通过注解,把一个URL映射到Controller类的方法上

 

Controller接口 -- 控制器

由于我们使用了@Controller注解,添加了@Controller注解注解的类就可以担任控制器(Action)的职责,

所以我们并没有用到这个接口。

 

 

 

HandlerInterceptor 接口--拦截器

无图,我们自己实现这个接口,来完成拦截的器的工作。

 

 

ViewResolver接口的实现类

UrlBasedViewResolver类 通过配置文件,把一个视图名交给到一个View来处理

InternalResourceViewResolver类,比上面的类,加入了JSTL的支持

 

View接口

JstlView类

 

LocalResolver接口

 

HandlerExceptionResolver接口 --异常处理

SimpleMappingExceptionResolver实现类

 

 

ModelAndView类

无图。

3、流程图

本图是我个人画的,有不严谨的地方,大家对付看吧。总比没的看强。

 

4.DispatcherServlet说明

使用Spring MVC,配置DispatcherServlet是第一步。

DispatcherServlet是一个Servlet,所以可以配置多个DispatcherServlet。

DispatcherServlet是前置控制器,配置在web.xml文件中的。拦截匹配的请求,Servlet拦截匹配规则要自已定义,把拦截下来请求,依据某某规则分发到目标Controller(我们写的Action)来处理。

 

“某某规则”:是根据你使用了哪个HandlerMapping接口的实现类的不同而不同。

先来看一个例子:

Xml代码  
  1. <web-app>  
  2.     <servlet>  
  3.         <servlet-name>example</servlet-name>  
  4.         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>  
  5.         <load-on-startup>1</load-on-startup>  
  6.     </servlet>  
  7.     <servlet-mapping>  
  8.         <servlet-name>example</servlet-name>  
  9.         <url-pattern>*.form</url-pattern>  
  10.     </servlet-mapping>  
  11. </web-app>  

 <load-on-startup>1</load-on-startup>是启动顺序,让这个Servlet随Servletp容器一起启动。

 <url-pattern>*.form</url-pattern> 会拦截*.form结尾的请求。

 

 <servlet-name>example</servlet-name>这个Servlet的名字是example,可以有多个DispatcherServlet,是通过名字来区分的。每一个DispatcherServlet有自己的WebApplicationContext上下文对象。同时保存的ServletContext中和Request对象中,关于key,以后说明。

 

在DispatcherServlet的初始化过程中,框架会在web应用的 WEB-INF文件夹下寻找名为[servlet-name]-servlet.xml 的配置文件,生成文件中定义的bean。

Servlet拦截匹配规则可以自已定义,拦截哪种URL合适? 

当映射为@RequestMapping("/user/add")时,为例:

1、拦截*.do、*.htm, 例如:/user/add.do

这是最传统的方式,最简单也最实用。不会导致静态文件(jpg,js,css)被拦截。

2、拦截/,例如:/user/add

可以实现现在很流行的REST风格。很多互联网类型的应用很喜欢这种风格的URL。

弊端:会导致静态文件(jpg,js,css)被拦截后不能正常显示。想实现REST风格,事情就是麻烦一些。后面有解决办法还算简单。

 

3、拦截/*,这是一个错误的方式,请求可以走到Action中,但转到jsp时再次被拦截,不能访问到jsp。

如何访问到静态的文件,如jpg,js,css?

如何你的DispatcherServlet拦截"*.do"这样的有后缀的URL,就不存在访问不到静态资源的问题。

如果你的DispatcherServlet拦截"/",为了实现REST风格,拦截了所有的请求,那么同时对*.js,*.jpg等静态文件的访问也就被拦截了。

我们要解决这个问题。

 目的:可以正常访问静态文件,不可以找不到静态文件报404。


方案一:激活Tomcat的defaultServlet来处理静态文件

Xml代码  收藏代码
  1. <servlet-mapping>   
  2.     <servlet-name>default</servlet-name>  
  3.     <url-pattern>*.jpg</url-pattern>     
  4. </servlet-mapping>    
  5. <servlet-mapping>       
  6.     <servlet-name>default</servlet-name>    
  7.     <url-pattern>*.js</url-pattern>    
  8. </servlet-mapping>    
  9. <servlet-mapping>        
  10.     <servlet-name>default</servlet-name>       
  11.     <url-pattern>*.css</url-pattern>      
  12. </servlet-mapping>    
  13. 要配置多个,每种文件配置一个   

要写在DispatcherServlet的前面, 让 defaultServlet先拦截请求,这样请求就不会进入Spring了,我想性能是最好的吧。

方案二: 在spring3.0.4以后版本提供了mvc:resources ,  使用方法:

代码:

X  
  1. <!-- 对静态资源文件的访问 -->    
  2. <mvc:resources mapping="/images/**" location="/images/" />  

  /images/**映射到ResourceHttpRequestHandler进行处理,location指定静态资源的位置.可以是web application根目录下、jar包里面,这

样可以把静态资源压缩到jar包中。

如果出现下面的错误,可能是没有配置<mvc:annotation-driven />的原因。 

报错WARNING: No mapping found for HTTP request with URI [/mvc/user/findUser/lisi/770] in DispatcherServlet with name 'springMVC'

 

使用<mvc:resources/>元素,把mapping的URI注册到SimpleUrlHandlerMapping的urlMap中,

key为mapping的URI pattern值,而value为ResourceHttpRequestHandler,

这样就巧妙的把对静态资源的访问由HandlerMapping转到ResourceHttpRequestHandler处理并返回,所以就支持classpath目录,jar包内静态资源的访问.

另外需要注意的一点是,不要对SimpleUrlHandlerMapping设置defaultHandler.因为对static uri的defaultHandler就是ResourceHttpRequestHandler,

否则无法处理static resources request.

 
原创粉丝点击