【Spring】30、Spring,SpringMVC用法汇总
SpringMVC的工作原理图:
springMVC中的几个组件:
前端控制器(DispatcherServlet):接收请求,响应结果,相当于电脑的CPU。
处理器映射器(HandlerMapping):根据URL去查找处理器
处理器(Handler):(需要程序员去写代码处理逻辑的)
处理器适配器(HandlerAdapter):会把处理器包装成适配器,这样就可以支持多种类型的处理器,类比笔记本的适配器(适配器模式的应用)
视图解析器(ViewResovler):进行视图解析,多返回的字符串,进行处理,可以解析成对应的页面
1、前端控制器DispatcherServlet(不需要工程师开发),由框架提供
作用:接收请求,响应结果,相当于转发器,中央处理器。有了dispatcherServlet减少了其它组件之间的耦合度。
用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。
2、处理器映射器HandlerMapping(不需要工程师开发),由框架提供
作用:根据请求的url查找Handler
HandlerMapping负责根据用户请求找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
3、处理器适配器HandlerAdapter
作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。
4、处理器Handler(需要工程师开发)
注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler
Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。
由于Handler涉及到具体的用户业务请求,所以一般情况需要工程师根据业务需求开发Handler。
5、视图解析器View resolver(不需要工程师开发),由框架提供
作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)
View Resolver负责将处理结果生成View视图,View Resolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。 springmvc框架提供了很多的View视图类型,包括:jstlView、freemarkerView、pdfView等。
一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由工程师根据业务需求开发具体的页面。
6、视图View(需要工程师开发jsp...)
View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf...)
核心架构的具体流程步骤如下:
第一步:用户发起请求到前端控制器(DispatcherServlet)
第二步:前端控制器请求处理器映射器(HandlerMappering)去查找处理器(Handle):通过xml配置或者注解进行查找
第三步:找到以后处理器映射器(HandlerMappering)像前端控制器返回执行链(HandlerExecutionChain)
第四步:前端控制器(DispatcherServlet)调用处理器适配器(HandlerAdapter)去执行处理器(Handler)
第五步:处理器适配器去执行Handler
第六步:Handler执行完给处理器适配器返回ModelAndView
第七步:处理器适配器向前端控制器返回ModelAndView
第八步:前端控制器请求视图解析器(ViewResolver)去进行视图解析
第九步:视图解析器像前端控制器返回View
第十步:前端控制器对视图进行渲染
第十一步:前端控制器向用户响应结果
filter过滤器
过滤器放在web资源之前,可以在请求抵达它所应用的web资源(可以是一个Servlet、一个Jsp页面,甚至是一个HTML页面)之前截获进入的请求,并且在它返回到客户之前截获输出请求。Filter:用来拦截请求,处于客户端与被请求资源之间,目的是重用代码。Filter链,在web.xml中哪个先配置,哪个就先调用。在filter中也可以配置一些初始化参数。
Filter 有如下几个用处:
- 在HttpServletRequest 到达Servlet 之前,拦截客户的HttpServletRequest 。
- 根据需要检查HttpServletRequest ,也可以修改HttpServletRequest 头和数据。
- 在HttpServletResponse 到达客户端之前,拦截HttpServletResponse 。
- 根据需要检查HttpServletResponse ,可以修改HttpServletResponse 头和数据。
自定义数据绑定---HandlerMethodArgumentResolver:
自定义一个CurrentUserHandlerMethodArgumentResolver实现HandlerMethodArgumentResolver
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
CommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor;
Object arg = null;
String[] paramValues = webRequest.getParameterValues(parameter.getParameterName());
if (paramValues != null) {
arg = paramValues.length >= 1 ? paramValues[0] : null;
} ParamCheck paramCheck = parameter.getParameterAnnotation(ParamCheck.class);
if(null != paramCheck){
try {
this.doCheck(arg, paramCheck, parameter.getParameterName(),parameter.getParameterType().getSimpleName());
} catch (RuntimeException e) {
LOGGER.error(e);
}
return arg;
} EntityCheck entityCheck = parameter.getParameterAnnotation(EntityCheck.class);
if(null != entityCheck){
arg = this.buildEntityFromParam(parameter, webRequest);
try {
this.doCheck(arg, entityCheck, parameter,webRequest);
} catch (RuntimeException e) {
LOGGER.error(e);
}
return arg;
}
return arg;
}
controller中接收参数,加上自定义注解 @EntityCheck
@RequestMapping(value = "/test")
@ResponseBody
public ModelMap test(@EntityCheck String str) {
ModelMap mm = new ModelMap();
try {
mm.addAttribute("message", "success");
mm.addAttribute("status", "0");
} catch (Exception e) {
e.printStackTrace();
mm.addAttribute("message", "failure");
mm.addAttribute("status", "1");
}
return mm;
}
springMVC对异常处理的支持
处理优先级,当发生异常的时候,SpringMVC会如下处理:
(1)SpringMVC会先从配置文件找异常解析器HandlerExceptionResolver
(2)如果找到了异常异常解析器,那么接下来就会判断该异常解析器能否处理当前发生的异常
(3)如果可以处理的话,那么就进行处理,然后给前台返回对应的异常视图
(4)如果没有找到对应的异常解析器或者是找到的异常解析器不能处理当前的异常的时候,就看当前的Controller中有没有提供对应的异常处理器,如果提供了就由Controller自己进行处理并返回对应的视图
(5)如果配置文件里面没有定义对应的异常解析器,而当前Controller中也没有定义的话,那么该异常就会被抛出来。
<!--错误处理器-->
<bean id="exceptionHandler" class="wangzhongqiu.spring.springmvc.resolver.MobileExceptionHandler"/>
public class MobileExceptionHandler implements HandlerExceptionResolver { private static Log logger = LogFactory.getLog(MobileExceptionHandler.class); private static final Log LOGGER = LogFactory.getLog(MobileExceptionHandler.class);
private static final int DEFAULT_STATUS_CODE = 1000;
private static final int UPLOAD_SIZE_EXCEEDED = 300601;
private static final String SPLIT = ""; @Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
ex.printStackTrace();
ModelAndView mav = new ModelAndView();
Map<String, Object> model = new HashMap();
// 默认异常信息 “请求失败,请稍后再试”
int status = DEFAULT_STATUS_CODE;
MappingJackson2JsonView view = new MappingJackson2JsonView();
try {
// 必选参数丢失
if (ex instanceof MissingServletRequestParameterException
|| ex instanceof HttpRequestMethodNotSupportedException || ex instanceof TypeMismatchException) {
status = 1001;
} else if (ex instanceof MaxUploadSizeExceededException) {
LOGGER.error("上传头像图片大小超过系统限制", ex);
status = UPLOAD_SIZE_EXCEEDED;
}
model.put("message", "错误");
model.put("status", status);
view.setAttributesMap(model);
mav.setView(view);
} catch (Exception e) {
LOGGER.error(e);
}
return mav;
}
}
使用BeanNameAutoProxyCreator创建代理
BeanNameAutoProxyCreator是自动代理创建器的三种(BeanNameAutoProxyCreator,DefaultAdvisorAutoProxyCreator,AbstractAdvisorAutoProxyCreator)之一.
它是根据拦截器和设置的Bean的名称表达式做匹配来创建代理.
<bean id="exposerProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="interceptorNames">
<list>
<value>databaseInterceptor</value>
<value>suspendAutoRepayInterceptor</value>
</list>
</property>
<property name="beanNames">
<list>
<value>*Controller</value>
</list>
</property>
<property name="proxyTargetClass" value="true"/>
</bean>
<bean id="databaseInterceptor" class="wangzhongqiu.spring.springmvc.interceptor.DatabaseInterceptor"/>
<bean id="suspendAutoRepayInterceptor" class="wangzhongqiu.spring.springmvc.interceptor.SuspendAutoRepayInterceptor"/>
public class DatabaseInterceptor implements MethodInterceptor {
private static final Logger DB_INC_LOG = LoggerFactory.getLogger(DatabaseInterceptor.class); @Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
try {
Method method = methodInvocation.getMethod();
if (method != null && method.getAnnotation(ReadOnlyDataSource.class) != null) {
DataSourceProvider.setDataSource(AvailableDataSources.READ);
DB_INC_LOG.info("The method 【" + method.getName() + "】 will use read-only datasource.");
}
return methodInvocation.proceed();
} finally {
DataSourceProvider.clearDataSource();
}
}
}
BeanNameAutoProxyCreator是一个BeanPostProcessor.它在Bean实例化随后,调用回调org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization进行后期处理来完成代理的创建.
BeanPostProcessor是在spring容器加载了bean的定义文件并且实例化bean之后执行的。BeanPostProcessor的执行顺序是在BeanFactoryPostProcessor之后。
BeanFactory是个 Factory ,实际上是实例化,配置和管理众多bean的容器, FactoryBean 是个 Bean 。在 Spring 中,所有的 Bean 都是由 BeanFactory( 也就是 IOC 容器 ) 来进行管理的。但对 FactoryBean 而言,这个 Bean 不是简单的 Bean ,而是一个能生产或者修饰对象生成的工厂 Bean, 它的实现与设计模式中的工厂模式和修饰器模式类似。
如果一个类实现了FactoryBean接口,那么getBean得到的不是他本身了,而是它所产生的对象,如果我们希望得到它本身,只需要加上&符号即可。
public class PersonFactoryBean implements FactoryBean<Person>{ private String personInfo; public Person getObject() throws Exception {
Person person = new Person () ;
String [] infos = personInfo.split ( "," ) ;
person.setName(infos[0]);
person.setAddress(infos[1]);
person.setAge(Integer.parseInt(infos[2]));
return person;
} public Class<Person> getObjectType() {
return Person.class;
} public boolean isSingleton() {
return true;
}
}
<bean id="personFactory" class="com.hik.MavenTest.PersonFactory">
<property name="personInfo" value="gh2,address2,22"></property>
</bean>
context包增加了ApplicationContext,它以一种更加面向框架的方式增强了BeanFactory的功能。多数用户可以以一种完全的声明式方式来使用ApplicationContext,甚至不用去手工创建它
Context包的基础是位于org.springframework.context包中的ApplicationContext接口。它是由BeanFactory接口集成而来,提供BeanFactory所有的功能。
====================相关文章=============================
Spring ContextLoaderListener与DispatcherServlet所加载的applicationContext的区别
ApplicationContext ,ApplicationContextAware,Listener,Event 的关系解读
<load-on-startup>0</load-on-startup>配置
========================================================
spring MVC 拦截器和<mvc:annotation-driven />的详解
Spring MVC handlerMapping和handlerAdapter
Spring MVC HandlerInterceptorAdapter的使用
Spring MVC 自定义数据绑定---HandlerMethodArgumentResolver
========================================================
spring aop 使用BeanNameAutoProxyCreator创建代理
Spring的BeanFactoryPostProcessor和BeanPostProcessor
Spring代理。BeanNameAutoProxyCreator 与 ProxyFactoryBean
========================================================
BeanFactory 和 ApplicationContext的区别
========================================================
Java的位运算符详解实例——与(&)、非(~)、或(|)、异或...
===================未完成================================
ProxyFactoryBean
ServletContextAware
【Spring】30、Spring,SpringMVC用法汇总的更多相关文章
- Spring 定时器Quartz的用法
Spring定时器Quartz的用法也很简单,需要引入quartz-all-1.5.2.jar java代码如下: package com.coalmine.desktop; import java. ...
- Spring Data Jpa+SpringMVC+Jquery.pagination.js实现分页
本博客介绍基于Spring Data这款orm框架加上Jquery.pagination插件实现的分页功能. 介绍一下Spring Data框架 spring Data : Spring 的一个子项目 ...
- 【Spring学习】SpringMVC demo搭建
前言:今天会通过IDEA建立一个SpringMVC的demo项目,在其中会涉及到一些基础模块和相关知识,然后结合这个具体的知识点,理解清楚SpringMVC的框架原理(以图的形式展示),顺藤摸瓜分析源 ...
- Spring MVC的WebMvcConfigurerAdapter用法收集(零配置,无XML配置)
原理先不了解,只记录常用方法 用法: @EnableWebMvc 开启MVC配置,相当于 <?xml version="1.0" encoding="UTF-8&q ...
- 阿里P7终于讲完了JDK+Spring+mybatis+Dubbo+SpringMvc+Netty源码
前言 这里普及一下,每个公司都有职别定级系统,阿里也是,技术岗以 P 定级,一般校招 P5, 社招 P6 起.其实阅读源码也是有很多诀窍的,这里分享几点心得: 首先要会用.你要知道这个库是干什么的,掌 ...
- Spring MVC RedirectAttributes的用法解决办法
Spring MVC RedirectAttributes的用法很久没发过技术贴了,今天对于一个问题纠结了2小时,遂放弃研究用另一种方法解决,奈何心中一直存在纠结,发帖求解 我先解释下什么是Redir ...
- spring整合mybatis,springMVC的0配置文件方式
0配置文件的形式主要是采用spring3.0提供的@configuration注解和spring容器在启动的时候会加载实现了WebApplicationInitializer的类,并调用其onStar ...
- spring容器和springmvc容器,以及web容器的关系
说到spring和springmvc,其实有很多人分不清他们有什么区别,认为它俩是一样的,如果你问他项目里用的什么MVC技术,他会说我们用的spring和mybatis,或者spring和hibern ...
- spring(一)--spring/springmvc/spring+hibernate(mybatis)配置文件
这篇文章用来总结一下spring,springmvc,spring+mybatis,spring+hibernate的配置文件 1.web.xml 要使用spring,必须在web.xml中定义分发器 ...
随机推荐
- python_day1 条件语句
一 流程控制 1.if....else 语句 用法: if 条件: 满足条件执行代码 else: if 条件不满足执行此部分代码 例: a = 10 b = 20 if a>b : pri ...
- cf 20C Dijkstra?
带队列 dijkstra #include <iostream> #include <cstdio> #include <queue> #include < ...
- 项目Alpha冲刺(团队3/10)
项目Alpha冲刺(团队3/10) 团队名称: 云打印 作业要求: 项目Alpha冲刺(团队) 作业目标: 完成项目Alpha版本 团队队员 队员学号 队员姓名 个人博客地址 备注 221600412 ...
- python 使用unittest进行单元测试
import unittest import HTMLTestRunner """ Python中有一个自带的单元测试框架是unittest模块,用它来做单元测试,它里面 ...
- Spring,为内部方法新起一个事务,此处应有坑。
事务的作用,使我们操作能够连贯起来.而spring则是提供了一个更简单的方法,只要使用 @Transactional 一个注解,就可以保证操作的连贯性了. 普通用法,稍后再说,这里要说的是: 在最外面 ...
- 可以用软连接的方式解决linux内存空间不足的问题
突然提示说/var空间满了,然后接着系统卡死,最后彻底没辙,重启试试,没想到提示什么系统错误,请联系管理员之类的提示语,也进不去登陆界面啥了.之后用其他电脑连接SSH用root账号访问. # cd / ...
- EasyNetQ中使用自定义的ISerializer
最近在使用EasyNetQ时,遇到一个问题:c++项目组发送的消息数据不是Json数据,而是自定义的数据格式(各字段+‘|’连接成一个字符串),EasyNetQ中消费消息接收的都是强类型,没办法直接消 ...
- 判断URL中的中文参数是GB2312还是Utf-8编码
如两个URL字符串: &q=%E8%A3%99%E5%AD%90&style=grid&seller_type=taobao &q=%CE%D0%C2%D6%D4%F6 ...
- h5端呼起摄像头扫描二维码并解析
2016年6月29日补充: 最近做了一些与表单相关的项目,使用了h5的input控件,在使用过程中遇到了很多的坑.也包括与这篇文章相关的. 首先我们应该知道使用h5新提供的属性getUserMedia ...
- redis的安装使用以及在python中操作redis
一.Redis介绍: Redis可以看作是一个key-value的存储系统,它为我们提供了丰富的数据结构,包括lists,sets,ordered sets和hashes.还包括了对这些数据结构的丰富 ...