springmvc的简单配置

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

映射等等。配置文件:

  1. <servlet>
  2. <servlet-name>springServlet</servlet-name>
  3. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  4. <load-on-startup></load-on-startup>
  5. </servlet>
  6. <servlet-mapping>
  7. <servlet-name>springServlet</servlet-name>
  8. <url-pattern>/</url-pattern>
  9. </servlet-mapping>

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

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

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

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

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

  1. <servlet>
  2. <servlet-name>springServlet</servlet-name>
  3. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  4. <init-param>
  5. <param-name>contextConfigLocation</param-name>
  6. <param-value>classpath:springmvc.xml</param-value>
  7. </init-param>
  8. <load-on-startup></load-on-startup>
  9. </servlet>
  10. <servlet-mapping>
  11. <servlet-name>springServlet</servlet-name>
  12. <url-pattern>/</url-pattern>
  13. </servlet-mapping>

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

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

restful风格的

  1. <context-param>
  2. <param-name>contextConfigLocation</param-name>
  3. <param-value>classpath*:/spring-context*.xml</param-value>
  4. </context-param>

支持多文件的:

  1. <context-param>
  2. <param-name>contextConfigLocation</param-name>
  3. <param-value>
  4. classpath:spring-common-config.xml,
  5. classpath:spring-budget-config.xml
  6. </param-value>
  7. </context-param>

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

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

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

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

  1. /**
  2. * Initialize the strategy objects that this servlet uses.
  3. * <p>May be overridden in subclasses in order to initialize further strategy objects.
  4. */
  5. protected void initStrategies(ApplicationContext context) {
  6. initMultipartResolver(context);
  7. initLocaleResolver(context);
  8. initThemeResolver(context);
  9. initHandlerMappings(context);
  10. initHandlerAdapters(context);
  11. initHandlerExceptionResolvers(context);
  12. initRequestToViewNameTranslator(context);
  13. initViewResolvers(context);
  14. initFlashMapManager(context);
  15. }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  1. protected void doService(HttpServletRequest request, HttpServletResponse response)

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

  1. try {
  2. doDispatch(request, response);
  3. }

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

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

  3.      HandlerExecutionChain mappedHandler = null;//前面讲过。handlerMapping映射成功,都会返回这个东西,其中包括处理器和拦截器
  4. boolean multipartRequestParsed = false;
  5.  
  6. WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
  7.  
  8. try {
  9. ModelAndView mv = null;
  10. Exception dispatchException = null;
  11.  
  12. try {
              //查看请求是否是Multipart(如文件上传)
  13. processedRequest = checkMultipart(request);
  14. multipartRequestParsed = (processedRequest != request);
  15.  
  16. // Determine handler for the current request.
            
             //映射
  17. mappedHandler = getHandler(processedRequest);
  18. if (mappedHandler == null || mappedHandler.getHandler() == null) {
  19. noHandlerFound(processedRequest, response);
  20. return;
  21. }
  22.           //进行适配器的包装
  23. // Determine handler adapter for the current request.
  24. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
  25.  
  26. // Process last-modified header, if supported by the handler.
  27. String method = request.getMethod();
  28. boolean isGet = "GET".equals(method);
  29. if (isGet || "HEAD".equals(method)) {
  30. long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
  31. if (logger.isDebugEnabled()) {
  32. logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
  33. }
  34. if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
  35. return;
  36. }
  37. }
  38.  
  39. if (!mappedHandler.applyPreHandle(processedRequest, response)) {
  40. return;
  41. }
  42.  
  43. // Actually invoke the handler.
  44. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
  45.  
  46. if (asyncManager.isConcurrentHandlingStarted()) {
  47. return;
  48. }
  49.          //
  50. applyDefaultViewName(request, mv);
  51. mappedHandler.applyPostHandle(processedRequest, response, mv);
  52. }
  53. catch (Exception ex) {
  54. dispatchException = ex;
  55. }
          
           //解析视图 最终会调用view.render(mv.getModelInternal(), request, response);将model传进去
  56. processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
  57. }
         //后面都是编译以后的一些操作了
  58. catch (Exception ex) {
  59. triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
  60. }
  61. catch (Error err) {
  62. triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
  63. }
  64. finally {
  65. if (asyncManager.isConcurrentHandlingStarted()) {
  66. // Instead of postHandle and afterCompletion
  67. if (mappedHandler != null) {
  68. mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
  69. }
  70. }
  71. else {
  72. // Clean up any resources used by a multipart request.
  73. if (multipartRequestParsed) {
  74. cleanupMultipart(processedRequest);
  75. }
  76. }
  77. }
  78. }

上面也就简单的了解了一下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. 230行实现一个简单的MVVM

    作者:mirone链接:https://zhuanlan.zhihu.com/p/24451202来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. MVVM这两年在前端届 ...

  2. 基础才是重中之重~ConcurrentDictionary让你的多线程代码更优美

    回到目录 ConcurrentDictionary是.net4.0推出的一套线程安全集合里的其中一个,和它一起被发行的还有ConcurrentStack,ConcurrentQueue等类型,它们的单 ...

  3. JS原生第一篇 (帅哥)

    "流程控制语句":if.for. 1.1 if 选择语句,给程序添加了多种执行路线. 1 if(){ 2  语句1 3 }else if(){ 4  语句2 5 }else if( ...

  4. ObjectOutputStream和ObjectInputStream

    官方解释: ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream.可以使用 ObjectInputStream 读取(重构)对象.通过使用流中的文 ...

  5. poj1273Drainage Ditches

    #include<iostream> /* 题意:就是寻找从源点到汇点的最大流! 要注意的是每两个点的流量可能有多个,也就是说有重边,所以要把两个点的所有的流量都加起来 就是这两个点之间的 ...

  6. uva 10801 - Lift Hopping(最短路Dijkstra)

    /* 题目大意: 就是一幢大厦中有0-99的楼层, 然后有1-5个电梯!每个电梯有一定的上升或下降速度和楼层的停止的位置! 问从第0层楼到第k层最少经过多长时间到达! 思路:明显的Dijkstra , ...

  7. Shell最多可以输入多少个参数?

    在脚本编写过程中,通常会涉及到参数的输入.譬如,sh 1.sh 10 20,在执行1.sh这个脚本中,10即为第一个参数,20即为第二个参数.有时,就会有这个疑惑,即shell脚本最多可以支持多少个变 ...

  8. selenium处理select标签的下拉框

    有时候我们会碰到<select></select>标签的下拉框.直接点击下拉框中的选项不一定可行.Selenium专门提供了Select类来处理下拉框. <select  ...

  9. Docker - Docker国内镜像的配置及使用

    Docker国内镜像 DaoCloud - Docker加速器 阿里云 - 开发者平台 微镜像 - 希云cSphere 镜像广场 - 时速云 灵雀云 网易蜂巢 阿里云的Docker加速器 阿里云 - ...

  10. 在Spring Boot中使用Https

    本文介绍如何在Spring Boot中,使用Https提供服务,并将Http请求自动重定向到Https. Https证书 巧妇难为无米之炊,开始的开始,要先取得Https证书.你可以向证书机构申请证书 ...