普通web--控制器就相似是一个调度员
观察者设计模式,在模型上注册视图,当模型更新时自动更新视图
用户发送请求给前端控制器,前端控制器接收请求,委托给模型进行业务处理,
前台控制器将数据返回给模型,而后选择用来展现数据的视图,将模型推送给视图,
视图展现数据,将响应返回给客户。
spring MVC
请求--响应模型
模型没法直接推送数据给视图,若是客户端但愿看见视图,须要再发一次请求。
前端控制器是DispatcherServlet
应用控制器其实拆为处理器映射器(Handler Mapping)进行处理器管理和视图解析器(View Resolver)进行视图管理
页面控制器/动做/处理器为Controller接口(仅包含ModelAndView handleRequest(request, response) 方法)的实现(也能够是任何的POJO类)
一、首先用户发送请求————>前端控制器,前端控制器根据请求信息(如URL)来决定选择哪个页面控制器进行处理并把请求委托给它,即之前的控制器的控制逻辑部分;图2-1中的一、2步骤;
二、页面控制器接收到请求后,进行功能处理,首先须要收集和绑定请求参数到一个对象,这个对象在Spring Web MVC中叫命令对象,并进行验证,而后将命令对象委托给业务对象进行处理;
处理完毕后返回一个ModelAndView(模型数据和逻辑视图名);图2-1中的三、四、5步骤;
三、前端控制器收回控制权,而后根据返回的逻辑视图名,选择相应的视图进行渲染,并把模型数据传入以便视图渲染;图2-1中的步骤六、7;
四、前端控制器再次收回控制权,将响应返回给用户,图2-1中的步骤8;至此整个结束。
核心架构的具体流程步骤以下:
一、 首先用户发送请求——>DispatcherServlet,前端控制器收到请求后本身不进行处理,而是委托给其余的解析器进行处理,做为统一访问点,进行全局的流程控制;
二、 DispatcherServlet——>HandlerMapping, HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象,
经过这种策略模式,很容易添加新的映射策略;
三、 DispatcherServlet——>HandlerAdapter,HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持不少类型的处理器;
四、 HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;html
并返回一个ModelAndView对象(包含模型数据、逻辑视图名);
五、 ModelAndView的逻辑视图名——> ViewResolver, ViewResolver将把逻辑视图名解析为具体的View,经过这种策略模式,很容易更换其余视图技术;
六、 View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,所以很容易支持其余视图技术;
七、 返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。
----------问题-------
一、 请求如何给前端控制器?这个应该在web.xml中进行部署描述,在HelloWorld中详细讲解。
二、 前端控制器如何根据请求信息选择页面控制器进行功能处理? 咱们须要配置HandlerMapping进行映射
三、 如何支持多种页面控制器呢?配置HandlerAdapter从而支持多种类型的页面控制器
四、 如何页面控制器如何使用业务对象?能够预料到,确定利用Spring IoC容器的依赖注入功能
五、 页面控制器如何返回模型数据?使用ModelAndView返回
六、 前端控制器如何根据页面控制器返回的逻辑视图名选择具体的视图进行渲染? 使用ViewResolver进行解析
七、 不一样的视图技术如何使用相应的模型数据? 由于Model是一个Map数据结构,很容易支持其余视图技术
-------------------------------------注解----------------------------------------------
@Service:用于标注业务层组件
@Controller:用于标注控制层组件(如struts中的action)
@Repository:用于标注数据访问组件,即DAO组件
@Component:泛指组件,当组件很差归类的时候,咱们可使用这个注解进行标注。
@Named:与@Component:存在细微的差距,基本上能够互相替换,习惯上不会使用。
@Controller:用于标识是处理器类;
@ComponentScan:启用组件扫描
1.component-scan标签默认状况下自动扫描指定路径下的包(含全部子包),将带有@Component、@Repository、@Service、@Controller标签的类自动注册到spring容器。
对标记了 Spring @Required、@Autowired、JSR250's @PostConstruct、@PreDestroy、@Resource、JAX-WS's
@WebServiceRef:EJB3's @EJB、JPA's @PersistenceContext、@PersistenceUnit等注解的类进行对应的操做使注解生效(包含了annotation-config标签的做用)。
@Autowired:自动装配---将组建扫描获得的bean和它们的依赖装配在一块儿--spring特有注解
@Inject--存在细微的差距,基本上能够互相替换--来源java依赖规范
@RequestMapping:请求处处理器功能方法的映射规则;
将 HTTP 请求映射到 MVC 和 REST 控制器的处理方法上。
Spring MVC 的 @RequestMapping 注解可以处理 HTTP 请求的方法, 好比 GET, PUT, POST, DELETE 以及 PATCH
@RequestParam:请求参数处处理器功能处理方法的方法参数上的绑定;
@RequestBody:请求的body体的绑定(经过HttpMessageConverter进行类型转换);
@ResponseBody:处理器功能处理方法的返回值做为响应体(经过HttpMessageConverter进行类型转换);
表示该方法的返回结果直接写入HTTP response body中,通常在异步获取数据时使用。
在使用@RequestMapping后,返回值一般解析为跳转路径。加上@responsebody后,返回结果直接写入HTTP response body中,不会被解析为跳转路径。
好比异步请求,但愿响应的结果是json数据,那么加上@responsebody后,就会直接返回json数据。
@Configuration:可理解为用spring的时候xml里面的<beans>标签:至关于把该类做为spring的xml配置文件中的<beans>,做用为:配置spring容器(应用上下文)
1.@Configuration不能够是final类型;
2.@Configuration不能够是匿名类;
3.嵌套的configuration必须是静态类。
@GetMapping:组合注解,是@RequestMapping(method = RequestMethod.GET)的缩写
@Bean:可理解为用spring的时候xml里面的<bean>标签--通知spring这个方法将返回一个对象,该对象要注册为spring应用上下文中的bean,方法体中包含了最终产生Bean实例的逻辑
@Import:注解支持导入普通的java类,并将其声明成一个bean--4.2以前只支持导入配置类
@ImportResource:经过locations属性加载对应的xml配置文件,同时须要配合@Configuration注解一块儿使用,定义为配置类;
@Profile:指定某个bean属于哪个profile--应用在类级别上--3.2开始也能够应用在方法上
@ActiveProfiles:指定测试时要激活哪一个profile
@Conditional:条件化bean,条件为true才会建立
@Primary:指定首选的bean,解决自动装配的歧义性
能够与@Component:组合用在组件扫描的bean上。
能够与@Bean:组合用在java配置的bean声明中。
自定义注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Log {
//事件描述
public String value() default "";
}
@Scope:spring bean的默认做用域是单利的(Singleton),若是要选择其余的做用域,须要使用scope注解。
能够与componant和bean注解一块儿使用
处理外部值的最简单方式就是声明属性源并经过Spring
的Environment来检索属性
@PropertySource引入源属性文件:xxx.xml
@PropertySource注解和Environment属性:
environment.getProperty("");
@SuppressWarnings("unchecked")
deprecation 使用了不同意使用的类或方法时的警告
unchecked 执行了未检查的转换时的警告,例如当使用集合时没有用泛型 (Generics) 来指定集合保存的类型。
fallthrough 当 Switch 程序块直接通往下一种状况而没有 Break 时的警告。
path 在类路径、源文件路径等中有不存在的路径时的警告。
serial 当在可序列化的类上缺乏 serialVersionUID 定义时的警告。
finally 任何 finally 子句不能正常完成时的警告。
all 关于以上全部状况的警告。
@ModelAttribute:请求参数到命令对象的绑定;
@SessionAttributes:用于声明session级别存储的属性,放置在处理器类上,一般列出模型属性(如@ModelAttribute)对应的名称
@InitBinder:自定义数据绑定注册支持,用于将请求参数转换到命令对象属性的对应类型;
Spring3.0引入RESTful架构风格支持(经过@PathVariable注解和一些其余特性支持),且又引入了更多的注解支持:
@CookieValue:cookie数据处处理器功能处理方法的方法参数上的绑定;
@RequestHeader:请求头(header)数据处处理器功能处理方法的方法参数上的绑定;
@ResponseStatus:定义处理器功能处理方法/异常处理器返回的状态码和缘由;
@ExceptionHandler:注解式声明异常处理器;
@PathVariable:请求URI中的模板变量部分处处理器功能处理方法的方法参数上的绑定,从而支持RESTful架构风格的URI;
@Controller和@RestController的区别?
知识点:@RestController注解至关于@ResponseBody + @Controller合在一块儿的做用。
1) 若是只是使用@RestController注解Controller,则Controller中的方法没法返回jsp页面,或者html,配置的视图解析器 InternalResourceViewResolver不起做用,返回的内容就是Return 里的内容。
2) 若是须要返回到指定页面,则须要用 @Controller配合视图解析器InternalResourceViewResolver才行。
若是须要返回JSON,XML或自定义mediaType内容到页面,则须要在对应的方法上加上@ResponseBody注解。
例如:
1.使用@Controller 注解,在对应的方法上,视图解析器能够解析return 的jsp,html页面,而且跳转到相应页面,若返回json等内容到页面,则须要加@ResponseBody注解
2.@RestController注解,至关于@Controller+@ResponseBody两个注解的结合,返回json数据不须要在方法前面加@ResponseBody注解了,但使用@RestController这个注解,就不能返回jsp,html页面,视图解析器没法解析jsp,html页面
**************************************************************************************************
若是返回到页面是map或者json或者list等,加上@ResponseBody准没错,
若是你想跳转到一个页面,那么千万别加@ResponseBody,由于这个注解会将你返回的东西放到response的body数据中去,
换句话说,你返回的页面将以字符串的形式写到页面上,而不是跳转到这个页面!
***************************************************************************************************
DispatcherServlet是前端控制器设计模式的实现,提供Spring Web MVC的集中访问点,并且负责职责的分派,并且与Spring IoC容器无缝集成。
DispatcherServlet主要用做职责调度工做,自己主要用于控制流程,主要职责以下:
一、文件上传解析,若是请求类型是multipart将经过MultipartResolver进行文件上传解析;
二、经过HandlerMapping,将请求映射处处理器(返回一个HandlerExecutionChain,它包括一个处理器、多个HandlerInterceptor拦截器);
三、经过HandlerAdapter支持多种类型的处理器(HandlerExecutionChain中的处理器);
四、经过ViewResolver解析逻辑视图名到具体视图实现;
五、本地化解析;
六、渲染具体的视图等;
七、若是执行过程当中遇到异常将交给HandlerExceptionResolver来解析。
-----DispatcherServlet中使用的特殊的Bean
-----DispatcherServlet默认使用WebApplicationContext做为上下文,所以咱们来看一下该上下文中有哪些特殊的Bean:
一、Controller:处理器/页面控制器,作的是MVC中的C的事情,但控制逻辑转移到前端控制器了,用于对请求进行处理;
二、HandlerMapping:请求处处理器的映射,若是映射成功返回一个HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象;如BeanNameUrlHandlerMapping将URL与Bean名字映射,映射成功的Bean就是此处的处理器;
三、HandlerAdapter:HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持不少类型的处理器;如SimpleControllerHandlerAdapter将对实现了Controller接口的Bean进行适配,而且掉处理器的handleRequest方法进行功能处理;
四、ViewResolver:ViewResolver将把逻辑视图名解析为具体的View,经过这种策略模式,很容易更换其余视图技术;如InternalResourceViewResolver将逻辑视图名映射为jsp视图;
五、LocalResover:本地化解析,由于Spring支持国际化,所以LocalResover解析客户端的Locale信息从而方便进行国际化;
六、ThemeResovler:主题解析,经过它来实现一个页面多套风格,即常见的相似于软件皮肤效果;
七、MultipartResolver:文件上传解析,用于支持文件上传;
八、HandlerExceptionResolver:处理器异常解析,能够将异常映射到相应的统一错误界面,从而显示用户友好的界面(而不是给用户看到具体的错误信息);
九、RequestToViewNameTranslator:当处理器没有返回逻辑视图名等相关信息时,自动将请求URL映射为逻辑视图名;
十、FlashMapManager:用于管理FlashMap的策略接口,FlashMap用于存储一个请求的输出,当进入另外一个请求时做为该请求的输入,一般用于重定向场景,后边会细述
-------------------------------------springmvc与struts2的区别
1)入口
springmvc的入口是一个servlet,即前端控制器,例如:*.action
struts2入口是一个filter过虑器,即前端过滤器,例如:
2)单例、多例
springmvc是基于方法开发,传递参数是经过方法形参,能够设计为单例
struts2是基于类开发,传递参数是经过类的属性,只能设计为多例
3)参数传递
springmvc经过参数解析器是将request对象内容进行解析成方法形参,将响应数据和页面封装成ModelAndView对象,最后又将模型数据经过request对象传输到页面
struts采用值栈存储请求和响应的数据,经过OGNL存取数据
-------------spring事物配置,声明式事务管理和基于@Transactional注解的使用
spring支持编程式事务管理和声明式事务管理两种方式。
编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。
声明式事务管理创建在AOP之上的。其本质是对方法先后进行拦截,而后在目标方法开始以前建立或者加入一个事务,在执行完目标方法以后根据执行状况提交或者回滚事务。
声明式事务最大的优势就是不须要经过编程的方式管理事务,这样就不须要在业务逻辑代码中掺琐事务管理的代码,只需在配置文件中作相关的事务规则声明(或经过基于@Transactional注解的方式),即可以将事务规则应用到业务逻辑中。
显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式。声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就能够得到彻底的事务支持。
和编程式事务相比,声明式事务惟一不足地方是,后者的最细粒度只能做用到“方法”级别,没法作到像编程式事务那样能够做用到代码块级别。可是即使有这样的需求,也存在不少变通的方法,
好比,能够将须要进行事务管理的代码块独立为方法等等。
声明式事务管理也有两种经常使用的方式,一种是基于tx和aop名字空间的xml配置文件,另外一种就是基于@Transactional注解。显然基于注解的方式更简单易用,更清爽。
spring事务特性
spring全部的事务管理策略类都继承自org.springframework.transaction.PlatformTransactionManager接口
其中TransactionDefinition接口定义如下特性:
事务隔离级别
隔离级别是指若干个并发的事务之间的隔离程度。TransactionDefinition 接口中定义了五个表示隔离级别的常量:
TransactionDefinition.ISOLATION_DEFAULT:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,一般这值就是TransactionDefinition.ISOLATION_READ_COMMITTED。
TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示一个事务能够读取另外一个事务修改但尚未提交的数据。该级别不能防止脏读,不可重复读和幻读,所以不多使用该隔离级别。好比PostgreSQL实际上并无此级别。
TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示一个事务只能读取另外一个事务已经提交的数据。该级别能够防止脏读,这也是大多数状况下的推荐值。
TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示一个事务在整个过程当中能够屡次重复执行某个查询,而且每次返回的记录都相同。该级别能够防止脏读和不可重复读。
TransactionDefinition.ISOLATION_SERIALIZABLE:全部的事务依次逐个执行,这样事务之间就彻底不可能产生干扰,也就是说,该级别能够防止脏读、不可重复读以及幻读。可是这将严重影响程序的性能。一般状况下也不会用到该级别。
事务传播行为
所谓事务的传播行为是指,若是在开始当前事务以前,一个事务上下文已经存在,此时有若干选项能够指定一个事务性方法的执行行为。在TransactionDefinition定义中包括了以下几个表示传播行为的常量:
TransactionDefinition.PROPAGATION_REQUIRED:若是当前存在事务,则加入该事务;若是当前没有事务,则建立一个新的事务。这是默认值。
TransactionDefinition.PROPAGATION_REQUIRES_NEW:建立一个新的事务,若是当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_SUPPORTS:若是当前存在事务,则加入该事务;若是当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,若是当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,若是当前存在事务,则抛出异常。
TransactionDefinition.PROPAGATION_MANDATORY:若是当前存在事务,则加入该事务;若是当前没有事务,则抛出异常。
TransactionDefinition.PROPAGATION_NESTED:若是当前存在事务,则建立一个事务做为当前事务的嵌套事务来运行;若是当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
事务超时
所谓事务超时,就是指一个事务所容许执行的最长时间,若是超过该时间限制但事务尚未完成,则自动回滚事务。在 TransactionDefinition 中以 int 的值来表示超时时间,其单位是秒。
默认设置为底层事务系统的超时值,若是底层数据库事务系统没有设置超时值,那么就是none,没有超时限制。
事务只读属性
只读事务用于客户代码只读但不修改数据的情形,只读事务用于特定情景下的优化,好比使用Hibernate的时候。
默认为读写事务。
“只读事务”并非一个强制选项,它只是一个“暗示”,提示数据库驱动程序和数据库系统,这个事务并不包含更改数据的操做,那么JDBC驱动程序和数据库就有可能根据这种状况对该事务进行一些特定的优化,比方说不安排相应的数据库锁,以减轻事务对数据库的压力,毕竟事务也是要消耗数据库的资源的。
可是你非要在“只读事务”里面修改数据,也并不是不能够,只不过对于数据一致性的保护不像“读写事务”那样保险而已。
所以,“只读事务”仅仅是一个性能优化的推荐配置而已,并不是强制你要这样作不可
spring事务回滚规则
指示spring事务管理器回滚一个事务的推荐方法是在当前事务的上下文内抛出异常。spring事务管理器会捕捉任何未处理的异常,而后依据规则决定是否回滚抛出异常的事务。
默认配置下,spring只有在抛出的异常为运行时unchecked异常时才回滚该事务,也就是抛出的异常为RuntimeException的子类(Errors也会致使事务回滚),而抛出checked异常则不会致使事务回滚。能够明确的配置在抛出那些异常时回滚事务,包括checked异常。也能够明肯定义那些异常抛出时不回滚事务。还能够编程性的经过setRollbackOnly()方法来指示一个事务必须回滚,在调用完setRollbackOnly()后你所能执行的惟一操做就是回滚。
myBatis为例 基于注解的声明式事务管理配置@Transactional前端