Spring MVC是Spring提供的一个强大而灵活的web框架。借助于注解,Spring MVC提供了几乎是POJO的开发模式,使得控制器的开发和测试更加简单。这些控制器一般不直接处理请求,而是将其委托给Spring上下文中的其他bean,通过Spring的依赖注入功能,这些bean被注入到控制器中。
Spring MVC主要由DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图组成。他的两个核心是两个核心:
处理器映射:选择使用哪个控制器来处理请求
视图解析器:选择结果应该如何渲染
通过以上两点,Spring MVC保证了如何选择控制处理请求和如何选择视图展现输出之间的松耦合。
(1) Http请求:客户端请求提交到DispatcherServlet。
(2) 寻找处理器:由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller。
(3) 调用处理器:DispatcherServlet将请求提交到Controller。
(4)(5)调用业务处理和返回结果:Controller调用业务逻辑处理后,返回ModelAndView。
(6)(7)处理视图映射并返回模型: DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图。
(8) Http响应:视图负责将结果显示到客户端。
(1)DispatcherServlet接口:
Spring提供的前端控制器,所有的请求都有经过它来统一分发。在DispatcherServlet将请求分发给Spring Controller之前,需要借助于Spring提供的HandlerMapping定位到具体的Controller。
(2)HandlerMapping接口:
能够完成客户请求到Controller映射。
(3)Controller接口:
需要为并发用户处理上述请求,因此实现Controller接口时,必须保证线程安全并且可重用。
Controller将处理用户请求,这和Struts Action扮演的角色是一致的。一旦Controller处理完用户请求,则返回ModelAndView对象给DispatcherServlet前端控制器,ModelAndView中包含了模型(Model)和视图(View)。
从宏观角度考虑,DispatcherServlet是整个Web应用的控制器;从微观考虑,Controller是单个Http请求处理过程中的控制器,而ModelAndView是Http请求过程中返回的模型(Model)和视图(View)。
(4)ViewResolver接口:
Spring提供的视图解析器(ViewResolver)在Web应用中查找View对象,从而将相应结果渲染给客户。
是整个Spring MVC的核心。它负责接收HTTP请求组织协调Spring MVC的各个组成部分。其主要工作有以下三项:
(1)截获符合特定格式的URL请求。
(2)初始化DispatcherServlet上下文对应WebApplicationContext,并将其与业务层、持久化层的WebApplicationContext建立关联。
(3)初始化Spring MVC的各个组成组件,并装配到DispatcherServlet中。
Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。Spring的核心是控制反转(IoC)和面向切面(AOP)。
简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。
①、方便解耦,简化开发
通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
②、AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。
③、声明式事务的支持
在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
④、方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便的测试Spring程序。
⑤、方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。
⑥、降低Java EE API的使用难度
Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低。
⑦、Java 源码是经典学习范例
Spring的源码设计精妙、结构清晰、匠心独运,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。Spring框架源码无疑是Java技术的最佳实践范例。如果想在短时间内迅速提高自己的Java技术水平和应用开发水平,学习和研究Spring源码将会使你收到意想不到的效果。
1、核心容器:核心容器提供 Spring 框架的基本功能(Spring Core)。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转(IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
2、Spring 上下文:Spring 上下文是一个配置文件,向 Spring框架提供上下文信息。Spring 上下文包括企业服务,例如JNDI、EJB、电子邮件、国际化、校验和调度功能。
3、Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向切面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
4、Spring DAO:JDBCDAO抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
5、Spring ORM:Spring 框架插入了若干个ORM框架,从而提供了 ORM 的对象关系工具,其中包括JDO、Hibernate和iBatisSQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
6、Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
7、Spring MVC 框架:MVC框架是一个全功能的构建 Web应用程序的 MVC 实现。通过策略接口,MVC框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。模型由javabean构成,存放于Map;视图是一个接口,负责显示模型;控制器表示逻辑代码,是Controller的实现。Spring框架的功能可以用在任何J2EE服务器中,大多数功能也适用于不受管理的环境。Spring 的核心要点是:支持不绑定到特定 J2EE服务的可重用业务和数据访问对象。毫无疑问,这样的对象可以在不同J2EE 环境(Web 或EJB)、独立应用程序、测试环境之间重用。
轻量——从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。
控制反转——Spring通过一种称作控制反转(IoC)的技术促进了低耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。
面向切面——Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。
框架——Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。
1.低侵入式设计,代码污染极低
2.独立于各种应用服务器,基于Spring框架的应用,可以真正实现Write Once,Run Anywhere的承诺
3.Spring的DI机制降低了业务对象替换的复杂性,提高了组件之间的解耦
4.Spring的AOP支持允许将一些通用任务如安全、事务、日志等进行集中式管理,从而提供了更好的复用
5.Spring的ORM和DAO提供了与第三方持久层框架的良好整合,并简化了底层的数据库访问
6.Spring并不强制应用完全依赖于Spring,开发者可自由选用Spring框架的部分或全部
spring两大核心技术
IOC/DI:控制反转/依赖注入,一个意思
AOP:面向切面编程
什么是依赖?什么是注入?
(1)依赖就是某个类必须依托另外一个类完成工作,那么就说这个类依赖于另外一个类。
例如:Colleage类里面有一个Student类型的属性,那么Colleage就依赖于Student,Student就是Colleage的一个依赖。
(2)注入就是某个类在需要某个依赖的时候,由容器创建这个依赖并给这个宿主类使用,不需要宿主类自己new这个依赖了。
什么是控制反转?
控制反转跟依赖注入说的是一回事儿,例如原来Colleage控制着Student的生成或者不生成,现在反了,Colleage不控制了,由Spring容器去
控制Student的生成。
容器
spring容器也成为DI容器或者IOC容器,就好比tomcat是servlet容器一样,spring容器"存放"的
是bean对象。
安装spring插件
springsource-tool-suite-3.4.0.zip
使用Spring IoC的步骤
第一,导入jar包
注意版本冲突、不要把xml这些放到path路径中
第二,配置spring文件
1、set方法注入
注意:
(1)id值可以随便取一个合法名称,但是必须保证唯一
(2)class是完全限定名
(3)property中的name值是对应的public setXXX方法名称
(4)value就是要注入给id指定的对象的属性值,如果值里面有特殊符号例如&<等可以用
(5)如果没有指定用constructor-arg构造方法注入,则该类必须有无参构造方法
(6)指定属性的数据类型,例如
(7)注入null值—
(8)单例情况bean.xml中的配置顺序会决定对象的创建顺序,多例情况只有在getBean时才创建,无所谓顺序
如果有关系依赖的话,例如A的创建依赖B的创建,把B配置在A的后面也是可以的,不会影响A的创建。
2、构造器注入
(1)多参构造方法用索引指定参数顺序
(2)还可继续使用property为其他属性赋值
注意:
(1)如果配置的构造方法产生了歧义,可以为属性指定type属性以示区分
3、命名空间注入
(1)xml必须引入p名称空间
(2)直接为属性赋值,例如:p:city="北京"
(3)引用另外一个bean为属性赋值,例如p:hellolist-ref="bigList"
4、静态工厂注入
(1)要求静态工厂里面有一个静态属性
(2)在static代码块中将上面的静态属性初始化
(3)要求工厂方法必须是static类型的
(4)配置xml文件,用factory-method指向工厂方法的名称,如果工厂方法需要传入参数则用constructor-arg来配置参数
(5)ctx.getBean(id)返回的不是工厂类,而是静态方法的返回类型
5、FactoryBean接口注入
(1)为什么我们自己的bean要借助FactoryBean接口?
因为某些bean初始化可能很复杂,跟业务相关,我们可以通过该接口提供的getObject方法去处理这些业务,然后返回一个我们想要的bean
(2)需要我们自己的bean实现FactoryBean接口
(3)要重写getObject()方法,重写的目的就是返回我想要的bean,注意getObject()无参数
(4)配置xml文件
注意:
(1)需要我们自己的类实现FactoryBean接口
(2)需要重写getObject方法
(3)ctx.getBean(id)返回值不是XXXFactoryBean对象,而是getObject方法返回的对象
(4)如果GradeFactoryBean中没有属性,xml中就不用配置property标签
(5)默认创建时带T泛型,可以不用泛型
(6)如果需要得到XXXFactoryBean对象该怎么办呢?在id前加“&”即可,例如ct.getBean("&factorybean");
6、静态工厂注入、FactoryBean接口注入的总结
(1)两者返回的对象都不是class类本身
(2)静态工厂注入返回的对象是静态工厂方法返回的对象
(3)FactoryBean接口注入返回的是getObject()方法返回的对象
(4)静态工厂注入,在xml配置上,需要用factory-method属性指明工厂静态方法
(5)FactoryBean接口注入,xml配置上跟普通配置一样,但是要求class类实现FactoryBean接口
7、bean的作用域scope
作用域—单例或多例:scope="prototype/singleton"
singleton: 单例的.默认值,每次调用getBean方法都会返回同一个bean.且在IOC容器初始化时即创建bean的实例
prototype: 原型的.每次调用getBean方法都会返回一个新的bean,且在第一次调用getBean方法时才创建实例
这点儿跟tomcat管理filter,listener道理一样,单例的对象都是在启动的时候创建且只创建一次
8、延迟加载
(1)
意思是当lazy-init的值为default时,lazy-init的值就是default-lazy-init的指定的值。其中default为false。
(2)
当值为default时,就是default-lazy-init指定的值。
(3)延迟加载只对单例bean有效,即是否打开延迟加载对多例bean无效,他们始终是在用的时候才初始化。
(4)延迟加载的bean第一次调用或者说使用时才被实例化,例如getBean(id),或者其他bean实例化时依赖了它
(5)如果一个设置了立即加载的beanA引用了一个设置了延迟加载的beanB,那么A在容器启动时就被实例化了,由于B被A
引用,所以B也被实例化了,这也符合(4)的规则
(6)懒加载带来的好处,加快服务器启动速度,尤其处理复杂bean的时候
注意:default-lazy-init是用来设置lazy-init默认值的,从另外一个角度看,它也是个总开关,例如default-lazy-init="true"
那么下面的bean在不设置lazy-init的情况下默认都是打开懒加载了。
9、引用
有3种引用方式:ref、value-ref、p:属性名-ref
这些标签或属性用来引用一个bean。
10、util标签
定义一个list,map或者其他数据类型,以便被其他bean引用,例如:
11、内部bean
通过一个内部bean为property赋值,例如:
12、注入list值
(1)使用
(2)使用
例如:
13、注入数组值
(1)同list
14、注入set
(1)同list
15、注入map值
16、注入null值
使用
17、注入特殊字符
使用
18、继承parent
(1)部分继承
(2)全部继承,包括class,scope,init-method....
把对方的配置信息拿来使用,不是真正意义上的继承,自身个性化的信息单独制定,可以
理解为重写,但不是重写
19、bean的生命周期
bean的生命周期:
(1)单例或多例均可设置生命周期属性,但是容器不会调用多例的destroy方法,由程序员管理
(2)执行顺序:构造方法——init——业务方法——容器退出——调用destroy方法
(3)init是执行完构造方法后执行,不是IOC容器初始化执行
(3)destroy是IOC容器销毁时执行
20、自动装配autowire
自动装配的条件:
(1)autowire="byName"或者autowire="byType"
(2)dashuju.spring.auto.Car里面的属性名称必须和要引用的bean的id值一样,即属性必须叫glass, light
(3)自动装配会自动装所有的属性,不能一部分指定成自动一部分非自动
21、使用外部properties文件
(1)引入context命名空间
(2)
(3)在需要的地方是用${property_key}
(4)也可以读取非properties文件,只要满足 key=value格式即可
22、使用SpEL表达式
(1)引用常量,例如9,'9','admin',false,true
(2)引用变量,例如age
(3)引用其他的bean
(4)引用其他的bean的属性和方法(之前普通方式办不到的)
(5)运算符的使用+,-,*,/,>,<,==,!=,%,eq(==),lt(<),gt(>),and,or,not,!,?:
(6)语法格式:#{...}
(7)T()运算符返回一个类对象,例如
23、注解注入
(1)配置bean的注解(即定义bean)
@Component 定义spring的通用组件,它可以用在任何一个类或者接口上,为了使得我们的系统更有层次、功能更分名,又引出了如下3个注解
@Repository 用在持久层,负责增删改查,它不知道也不关心业务如何,让它删谁它就删谁
@Service 专门处理业务关系,负责业务调用,告诉持久层该把谁删了,该查谁
@Controller 控制层,它就像一个交通警察,根据业务层处理的结果把页面导向正确的地址
@Scope 指明bean的范围,即单例或多例,可取的值有singleton,prototype,request,session
a.用在类上,注解就是装配当前类的,当spring容器在初始化的时候会扫描这些组件,一旦发现有这些注解的类,就会把这些类纳入到spring容器去管理
b.可以默认生成id,默认生成的id就是类名第一个字母小写.也可以自定义一个id,例如@Component或者@Component("annotation")
c.@Repository,@Service,@Controller可以看做是@Component的延伸,他们在功能上一模一样
注意:
a.如果类名开头连续多个大写,则创建的bean名称是类名,例如:AAnnotation
b.以上注解都是用在类或者接口上的
(2)配置bean之间的关系(即给bean属性注入值)
@Autowired 它是spring官方给出的注解,它默认是按照类型装配,如果有多个相同类型的bean则会报错,需要配合@Qualifier(id)指明注入哪个。注:@Autowired本身没有指定id的功能
@Resource 它是JDK官方给出的注解,它默认是按照名称装配,即属性名要跟注入的bean对象名一致,如果不一致可以用@Resource(name="stcopy")或者配合@Qualifier(id)指明名称
@Qualifier 结合@Autowired或者@Resource使用,用它来指明注入哪个bean,例如@Qualifier("zhangxiaoming")
@value 用在属性上,为属性注入值,例如@Value("张小明")String name; 还可以结合
注意:
a.使用了@Autowired或@Resource的属性可以不用再生成set/get方法
b.如果在IOC容器中找不到@Autowired注入的对象,则会报异常,可以使用@Autowired(required=false)声明为非必须的
c.@Autowired还可以用在方法上、方法的参数上
b.以上注解都是用在类的属性上
(3)注解的使用步骤
a.在类上标注注解
b.在spring配置文件中增加扫包标签
c.创建IOC容器,进行业务编程
(4)其他注解
延迟加载:@Lazy 默认值true
(5)知识扩展
B/S:brower-server,即浏览器-服务器端。
C/S:client-server,即客户端-服务器端。需要安装的软件,运行的客户机上。
富客户端:指的是js,css,h5,ajax
9、关键接口和类
FactoryBean 接口
BeanFactory 接口
ApplicationContext 接口
ClassPathXmlApplicationContext 实现类
10、IOC的注入方式
(1)set注入:必须有无参构造(如果被有参构造"覆盖"了,需要手动声明)、必须提供get/set方法
(2)构造注入:可以不提供无参构造,因为在这里应指定了要调用的构造方法
(3)p命名空间注入:配置文件必须引入p命名空间
(4)静态工厂注入:必须提供一个静态方法,在xml配置中也要通过factory-method属性指明这个静态方法.如果要给静态方法传参,可以通过
(5)FactoryBean注入:需要我们自己的类实现FactoryBean这个接口,并且要重写getObject方法,spring就是这个方法中获取返回的对象,它只认这个方法。如果要传参,可以通过为XXXFactoryBean定义属性的方式注入。
(6)注解注入:必须引入Conext命名空间、必须扫包
11、总结
(1)IOC学习,就是学习配置bean以及配置bean之间的关系,这也正是springIOC容器所管理的内容。例题:机器人组装
(2)注意单例、多例的合理运用。例题:多人模拟过独木桥
MyBatis是一个实现了JPA规范的用来连接数据库并对其进行增删改查操作的开源框架(就和传统的JDBC一样,就是个连接数据库的东西),其实,它底层就是一个JDBC封装的组件。MyBatis的前身是Ibatis,Ibatis创建与2002年最初为Apache下面的一个开源项目,2010迁移到google code下面并改名为MyBatis。
MyBatis虽然实现了JPA但是它并不是一个完完全全的ORM组件,而是一个基于SQL开发的半ORM组件。
而Hibernate是一个完完全全的ORM组件,它是完全基于对象来操作数据库中的记录,并不和MyBatis一样是一个假把式。
Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
评论私聊发面试题