springmvc的简单配置

1.首先需要在web.xml中配置DispatcherServlet,这个类是springmvc的核心类,所以的操作都是由这里开始,并且大部分都是在这里面实现的,比如各种视图的解析,视图的

映射等等。配置文件:

    <servlet>
<servlet-name>springServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup></load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

既然是和spring一套的,那肯定是有配置文件的,但是我们却没有配置文件路径,文件的默认路径是可以修改的,如果我们的这个文件没有配置路径的话,默认的路径是

/WEB-INF/springServlet-servlet.xml //  默认的路径就是:/WEB-INF/[servlet的名称]-servlet.xml 

但是我们是可以自己设置属性的,除了文件路径,还可以设置一下的几个属性:

contextClass:实现WebApplicationContext接口的类,当前的servlet用它来创建上下文。如果这个参数没有指定, 默认使用XmlWebApplicationContext。
contextConfigLocation:传给上下文实例(由contextClass指定)的字符串,用来指定上下文的位置。这个字符串可以被分成多个字符串(使用逗号作为分隔符) 来支持多个上下文(在多上下文的情况下,如果同一个bean被定义两次,后面一个优先)。
namespace:WebApplicationContext命名空间。默认值是[server-name]-servlet。

文件既可以放在WEB-INF下面,也可以放在classpath下面,比如:

<servlet>
<servlet-name>springServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup></load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

注意一点的是,这个classpath指的是编译后的位置,刚开始学习框架的时候,总会犯这样的错误,找不到配置文件,就是因为classpath的问题。

对于web项目,还有一种通用的写法,就是放在ContextLoaderListener下面:

restful风格的

  <context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/spring-context*.xml</param-value>
</context-param>

支持多文件的:

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:spring-common-config.xml,
classpath:spring-budget-config.xml
</param-value>
</context-param>

这样子,springmvc基本上是配置好了,这里没有讲spring的配置。

上面配置好了简单的web.xml以后,我们来讲一下DispatcherServlet.

从上面我们应该就明白了,其实它就是一个servlet,既然是servlet,那么理解起来就简单多了。

DispathcherServlet最主要的就是下面几个方法,下面一一来简单看看:

/**
* Initialize the strategy objects that this servlet uses.
* <p>May be overridden in subclasses in order to initialize further strategy objects.
*/
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}

这个方法是初始化各种解析器,适配等等的方法,这个方法是在其父类的初始化方法中调用的,没记错的话,其实就是相当于Servlet的init方法执行时调用。首先一起了解下上面每一个方法初始化的都是什么:

1.MultipartResolver指的是文件上传解析类,对于文件上传的时候,需要使用到,我们看他的方法:
private void initMultipartResolver(ApplicationContext context) {
try {
        //这里获取bean 注意这个常量在前面的是定义的:MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";
        //所以我们配置的时候 bean的名称必须是上面的这个 不然是不能识别的哦 注意咯
this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);
if (logger.isDebugEnabled()) {
logger.debug("Using MultipartResolver [" + this.multipartResolver + "]");
}
}
catch (NoSuchBeanDefinitionException ex) {
// Default is no multipart resolver.
this.multipartResolver = null;
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate MultipartResolver with name '" + MULTIPART_RESOLVER_BEAN_NAME +
"': no multipart request handling provided");
}
}
}

如果没有配置  那么默认就是没有文件上传解析的。这个时候,如果上传,那么会出一些问题的。

2.LocaleResolver这个是本地化解析,也就是做国际化的,如果没有设置,那么会默认为我们设置一个

3.ThemeResolver 看名字也知道,就是风格和主题解析类,默认也会有为我们设置一个

4.HandlerMappings :请求到处理器的映射,如果映射成功返回一个HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象;如BeanNameUrlHandlerMapping将URL与Bean名字映射,映射成功的Bean就是此处的处理器;从下面的代码中可以看出

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    //请求到处理器的映射,如果映射成功返回一个HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器对象);
//如BeanNameUrlHandlerMapping将URL与Bean名字映射,映射成功的Bean就是此处的处理器,注意这里处理器值得是handler,而不是handlerMapping,形象的将
     //就是handlerMapping是一个模板,处理器handler就是根据你的bean刻出的成型产品。
for (HandlerMapping hm : this.handlerMappings) {
if (logger.isTraceEnabled()) {
logger.trace(
"Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
}
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}

5.HandlerAdapters:看到适配器了吧,对各种处理器包装成适配器,这样就能支持多种类型的处理器了。

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());//将处理器进行包装,后面的操作都是都是由适配器进行工作

6HandlerExceptionResolvers:一场解析器,就比如出现错误的时候,可能统一调到某一个页面。默认也有实现,这个需求有太多中解决方案了,没什么好讲

7.RequestToViewNameTranslator:当处理器没有返回逻辑视图名等相关信息时,自动将请求URL映射为逻辑视图名;

8ViewResolvers:视图解析器。我们的配置中都会一般都会配置一个视图,就像这样:

        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="suffix" value=".jsp"></property>
<property name="prefix" value="/WEB-INF/views/module/"></property>
</bean>

视图解析器就是将上面的进行解析。超类只有一个方法

View resolveViewName(String viewName, Locale locale) throws Exception;
9.FlashMapManager值得是redirect的时候保存数据的一个相当于map分装的一个容器吧,但是官方是说在程序中一般不会使用的,比如在controller,就经常是用RedirectAttributes 来传输数据

讲完了几个比较重要的属性,然后将主要的几个放大,既然是servlet,那么我们就来看看service方法吧,这里的service是这样的:

protected void doService(HttpServletRequest request, HttpServletResponse response) 

里面有一个这样的依据代码需要引起重视,其他的代码都是配置一些属性什么的

try {
doDispatch(request, response);
}

这个方法其实就是DispatchServlet的核心,我们前面讲到的解析器,适配器等等都是在这里操作的:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;

     HandlerExecutionChain mappedHandler = null;//前面讲过。handlerMapping映射成功,都会返回这个东西,其中包括处理器和拦截器
boolean multipartRequestParsed = false; WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try {
ModelAndView mv = null;
Exception dispatchException = null; try {
          //查看请求是否是Multipart(如文件上传)
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request); // Determine handler for the current request.
        
         //映射
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
          //进行适配器的包装
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
}
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
return;
}
} if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
} // Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); if (asyncManager.isConcurrentHandlingStarted()) {
return;
}
         //
applyDefaultViewName(request, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
catch (Exception ex) {
dispatchException = ex;
}
      
       //解析视图 最终会调用view.render(mv.getModelInternal(), request, response);将model传进去
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
     //后面都是编译以后的一些操作了
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
}
catch (Error err) {
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
}
finally {
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
}
}
else {
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
}
}
}
}

上面也就简单的了解了一下springmvc的入口,接下来几天在研究一下springmvc其他的一些功能。好多东西都是自己理解的,不知道对不对==。

springmvc(1)DispatcherServlet源码简单解析的更多相关文章

  1. springmvc(2)Controller源码简单解析

    前面简单的分析了一下DispatcherServlet,接下来分析一下Controller,在web的MVC中,Controller就是其中的C,启动的一些页面逻辑处理,页面映射的功能: 首先看看超类 ...

  2. node-pre-gyp以及node-gyp的源码简单解析(以安装sqlite3为例)

    title: node-pre-gyp以及node-gyp的源码简单解析(以安装sqlite3为例) date: 2020-11-27 tags: node native sqlite3 前言 简单来 ...

  3. Okhttp源码简单解析(一)

    业余时间把源码clone下来大致溜了一遍,并且也参阅了其余大神的博客,在这里把自己的心得记录下来共享之,如有不当的地方欢迎批评指正.本文是Okttp源码解析系列的第一篇,不会深入写太多的东西,本篇只是 ...

  4. ForkJoinPool源码简单解析

    ForkJoin框架之ForkJoinTask  java  阅读约 62 分钟 前言 在前面的文章"CompletableFuture和响应式编程"中提到了ForkJoinTas ...

  5. StringBudiler源码简单解析

    StringBudiler源码 继承关系树 底层实现 默认容量() 特别的添加方法(append) 1.继承关系树 继承自AbstractStringBuilder与StringBuffer同族 2. ...

  6. springmvc的DispatcherServlet源码——doDispatch方法解析

    DispatcherServlet的doDispatch方法主要用作职责调度工作,本身主要用于控制流程,主要职责如下: 1.文件上传解析,如果请求类型是multipart将通过MultipartRes ...

  7. 源码深度解析SpringMvc请求运行机制(转)

    源码深度解析SpringMvc请求运行机制 本文依赖的是springmvc4.0.5.RELEASE,通过源码深度解析了解springMvc的请求运行机制.通过源码我们可以知道从客户端发送一个URL请 ...

  8. SpringMVC 源码深度解析&lt;context:component-scan&gt;(扫描和注冊的注解Bean)

    我们在SpringMVC开发项目中,有的用注解和XML配置Bean,这两种都各有自己的优势,数据源配置比較经经常使用XML配置.控制层依赖的service比較经经常使用注解等(在部署时比較不会改变的) ...

  9. FFmpeg的HEVC解码器源码简单分析:解析器(Parser)部分

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

随机推荐

  1. lua实现深度拷贝table表

    lua当变量作为函数的参数进行传递时,类似的也是boolean,string,number类型的变量进行值传递.而table,function,userdata类型的变量进行引用传递.故而当table ...

  2. Atitti usrQBf1801 翻页控件规范  v2

    Atitti usrQBf1801 翻页控件规范  v2 1. 参考api  参考easyui ,.net系列的1 1.1. 翻页流程  初始化翻页控件,以及绑定新页面event onSelectPa ...

  3. Atitit 图像处理30大经典算法attilax总结

    Atitit 图像处理30大经典算法attilax总结 1. 识别模糊图片算法2 2. 相似度识别算法(ahash,phash,dhash)2 3. 分辨率太小图片2 4. 横条薯条广告2 5. 图像 ...

  4. Unity3D大风暴之入门篇(海量教学视频版)

    智画互动开发团队 编   ISBN 978-7-121-22242-9 2014年2月出版 定价:79.00元 328页 16开 编辑推荐 长达800分钟的高清教学视频,手把手教会初学者 数个开发案例 ...

  5. 在同一台电脑上同时安装Python2和Python3

    目前Python的两个版本Python2和Python3同时存在,且这两个版本同时在更新与维护. 到底是选择Python2还是选择Python3,取决于当前要使用的库.框架支持哪个版本. 例如:HTM ...

  6. How Google TestsSoftware - Part One

    This is the firstin a series of posts on this topic.The one question I get morethan any other is &qu ...

  7. unity生成WP工程后ExtendedSplashImage显示不正确的问题

    这个bug我已经彻底无语了,居然这么久都没有fix. 解决方法如下: <SwapChainPanel x:Name="DXSwapChainPanel"> <Gr ...

  8. 初次使用IDEA的相关技巧

    前言:由于初次使用IDEA,所以很多配置都不是非常熟悉,经过一下午慢慢熟悉和同事的帮助,终于有所斩获,现在我把这个总结写出来,希望能够帮助初次使用的java工程师. 1:下载和安装 下载地址:http ...

  9. 解决h5的video标签,android、ipad客户端播放正常,iphone客户端无法播放

    在做html5时插入一个视频播放标签video后,测试时android.ipad客户端播放正常,唯独iphone自带浏览器无法播放. 解决办法: 判断用户所使用客户端访问h5页面时是iphone时,点 ...

  10. C#预处理器指令 ,你造吗??? (●'◡'●)

    什么是c#预处理指令?? 用于在 C# 源代码中嵌入的编译器命令. C#预处理器指令有哪些?? ↓↓↓这些就是预处理器指令啦 下面我们一一道来(●'◡'●) 1.#if ,#elif,#else,en ...