思惟导图学习 | 第十篇:java学习中级篇(框架),让Spring再也不难懂(mvc篇)

写在前面

生活就像海洋,只有意志坚强的人才能到达彼岸。php

已经好久没有发文章了呀,想必你们都挂念我了,哈哈。html

温故而知新,今天一块儿来复习一下spring mvc的内容吧。前端

首先咱们看下一个MVC的完整的思惟导图

完整Spring MVC思惟导图

spring mvc简介与运行原理

Spring的模型-视图-控制器(MVC)框架是围绕一个DispatcherServlet来设计的,这个Servlet会把请求分发给各个处理器,并支持可配置的处理器映射、视图渲染、本地化、时区与主题渲染等,甚至还能支持文件上传。java

Spring MVC流程

  • (1) Http请求:客户端请求提交到DispatcherServletpython

  • (2) 寻找处理器:由DispatcherServlet控制器查询一个或多个HandlerMapping,找处处理请求的Controllergit

  • (3) 调用处理器:DispatcherServlet将请求提交到Controller程序员

  • (4)(5)调用业务处理和返回结果:Controller调用业务逻辑处理后,返回ModelAndViewweb

  • (6)(7)处理视图映射并返回模型: DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图。面试

  • (8) Http响应:视图负责将结果显示到客户端。spring

主要注解

spring mvc注解

ContextLoaderListener

在讲ContextLoaderListener以前,首先来了解一下web.xml的做用。

  • 一个web中能够没有web.xml文件,也就是说,web.xml文件并非web工程必须的。web.xml文件是用来初始化配置信息:好比Welcome页面、servletservlet-mappingfilterlistener、启动加载级别等。当你的web工程没用到这些时,你能够不用web.xml文件来配置你的Application

  • 当要启动某个web项目时,服务器软件或容器如(tomcat)会第一步加载项目中的web.xml文件,经过其中的各类配置来启动项目,只有其中配置的各项均无误时,项目才能正确启动。web.xml有多项标签,在其加载的过程当中顺序依次为:context-param >> listener >> fileter >> servlet。(同类多个节点以出现顺序依次加载)

web.xml加载过程

spring mvc启动过程大体分为两个过程:

  • ContextLoaderListener初始化,实例化IoC容器,并将此容器实例注册到ServletContext中。

  • DispatcherServlet初始化。

web.xml配置

其中ContextLoaderListener监听器它实现了ServletContextListener这个接口,在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。在ContextLoaderListener中关联了ContextLoader这个类,因此整个加载配置过程由ContextLoader来完成。

  • ContextLoaderListenerweb.xml中的配置
<pre class="hljs xml" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 13px; padding: 15px; margin-top: 0px; margin-bottom: 20px; line-height: 1.42857; word-wrap: normal; color: rgb(101, 123, 131); background-color: rgb(246, 246, 246); border: 1px solid rgb(204, 204, 204); border-radius: 0px; text-size-adjust: none; word-break: break-word !important;">
<!-- 配置contextConfigLocation初始化参数 -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value></context-param>
<!-- 配置ContextLoaderListerner -->
<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</pre>

ServletContextListener 接口有两个方法:contextInitialized,contextDestroyed

DispatcherServlet

Spring MVC框架,与其余不少webMVC框架同样:请求驱动;全部设计都围绕着一个中央Servlet来展开,它负责把全部请求分发到控制器;同时提供其余web应用开发所须要的功能。不过Spring的中央处理器,DispatcherServlet,能作的比这更多。

下图展现了Spring Web MVCDispatcherServlet处理请求的工做流。熟悉设计模式的朋友会发现,DispatcherServlet应用的其实就是一个“前端控制器”的设计模式(其余不少优秀的web框架也都使用了这个设计模式)。

  • 流程图

spring mvc处理请求的流程

  • web.xml中的配置
<pre class="hljs xml" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 13px; padding: 15px; margin-top: 0px; margin-bottom: 20px; line-height: 1.42857; word-wrap: normal; color: rgb(101, 123, 131); background-color: rgb(246, 246, 246); border: 1px solid rgb(204, 204, 204); border-radius: 0px; text-size-adjust: none; word-break: break-word !important;">
<!-- servlet定义 -->
<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
    <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>
</pre>

其中

  • load-on-startup:表示启动容器时初始化该Servlet

  • url-pattern:表示哪些请求交给Spring Web MVC处理, “/” 是用来定义默认servlet映射的。也能够如“*.html”表示拦截全部以html为扩展名的请求。

Spring MVC中,每一个DispatcherServlet都持有一个本身的上下文对象WebApplicationContext,它又继承了根(root)WebApplicationContext对象中已经定义的全部bean。这些继承的bean能够在具体的Servlet实例中被重载,在每一个Servlet实例中你也能够定义其scope下的新bean

WebApplicationContext继承自ApplicationContext,它提供了一些web应用常常须要用到的特性。它与普通的ApplicationContext不一样的地方在于,它支持主题的解析,而且知道它关联到的是哪一个servlet(它持有一个该ServletContext的引用)

DispatcherServlet继承结构

spring mvc同时提供了不少特殊的注解,用于处理请求和渲染视图等。DispatcherServlet初始化的过程当中会默认使用这些特殊bean进行配置。若是你想指定使用哪一个特定的bean,你能够在web应用上下文WebApplicationContext中简单地配置它们。

特殊bean

其中,经常使用的ViewResolver的配置。以jsp做为视图为例

<pre class="hljs xml" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 13px; padding: 15px; margin-top: 0px; margin-bottom: 20px; line-height: 1.42857; word-wrap: normal; color: rgb(101, 123, 131); background-color: rgb(246, 246, 246); border: 1px solid rgb(204, 204, 204); border-radius: 0px; text-size-adjust: none; word-break: break-word !important;">
<!-- 对模型视图名称的解析,即在模型视图名称添加先后缀 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" /></bean>
</pre>

配置上传文件限制MultipartResolver

<pre class="hljs xml" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 13px; padding: 15px; margin-top: 0px; margin-bottom: 20px; line-height: 1.42857; word-wrap: normal; color: rgb(101, 123, 131); background-color: rgb(246, 246, 246); border: 1px solid rgb(204, 204, 204); border-radius: 0px; text-size-adjust: none; word-break: break-word !important;">
<!-- 上传限制 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
     <!-- 上传文件大小限制为31M,31*1024*1024 -->
     <property name="maxUploadSize" value="32505856"/></bean>
</pre>

applicationContext.xml中的标签

applicationContext.xml配置文件标签

文件上传

前面说到DispatcherServlet中有个特殊的Bean叫MultipartResolver,可用于限制文件的上传大小等。当解析器MultipartResolver完成处理时,请求便会像其余请求同样被正常流程处理。

  • 表单
<pre class="hljs xml" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 13px; padding: 15px; margin-top: 0px; margin-bottom: 20px; line-height: 1.42857; word-wrap: normal; color: rgb(101, 123, 131); background-color: rgb(246, 246, 246); border: 1px solid rgb(204, 204, 204); border-radius: 0px; text-size-adjust: none; word-break: break-word !important;">
<form method="post" action="/form" enctype="multipart/form-data">
     <input type="text" name="name"/>
     <input type="file" name="file"/>
     <input type="submit"/></form>
</pre>
  • 控制器
<pre class="hljs java" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 13px; padding: 15px; margin-top: 0px; margin-bottom: 20px; line-height: 1.42857; word-wrap: normal; color: rgb(101, 123, 131); background-color: rgb(246, 246, 246); border: 1px solid rgb(204, 204, 204); border-radius: 0px; text-size-adjust: none; word-break: break-word !important;">
@RequestMapping(path = "/form", method = RequestMethod.POST) 
public String handleFormUpload(
            @RequestParam("name") String name, 
            @RequestParam("file") MultipartFile file) {   
   if (!file.isEmpty()){          
           byte[] bytes = file.getBytes();   // store the bytes somewhere
          return "redirect:uploadSuccess";
        }    
          return "redirect:uploadFailure";
}
</pre>

异常处理

先来讲下常见的异常处理有几种方式,以下图:

异常处理方式

Spring的处理器异常解析器HandlerExceptionResolver接口的实现负责处理各种控制器执行过程当中出现的异常。也是上面提到的,是DispatcherServlet中的特殊bean,能够自定义配置处理。

某种程度上讲,HandlerExceptionResolver与你在web应用描述符web.xml文件中能定义的异常映射(exception mapping)很相像,不过它比后者提供了更灵活的方式。好比它能提供异常被抛出时正在执行的是哪一个处理器这样的信息。

  • HandlerExceptionResolver 提供resolveException接口
<pre class="hljs java" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 13px; padding: 15px; margin-top: 0px; margin-bottom: 20px; line-height: 1.42857; word-wrap: normal; color: rgb(101, 123, 131); background-color: rgb(246, 246, 246); border: 1px solid rgb(204, 204, 204); border-radius: 0px; text-size-adjust: none; word-break: break-word !important;">
public interface HandlerExceptionResolver {  
    ModelAndView resolveException(  HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);  
}
</pre>
  • 在BaseController中使用 @ExceptionHandler注解处理异常
<pre class="hljs php" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 13px; padding: 15px; margin-top: 0px; margin-bottom: 20px; line-height: 1.42857; word-wrap: normal; color: rgb(101, 123, 131); background-color: rgb(246, 246, 246); border: 1px solid rgb(204, 204, 204); border-radius: 0px; text-size-adjust: none; word-break: break-word !important;">    @ExceptionHandler(Exception.class)    public Object exceptionHandler(Exception ex, HttpServletResponse response, 
              HttpServletRequest request) throws IOException {
        String url = "";
        String msg = ex.getMessage();
        Object resultModel = null;        try {            if (ex.getClass() == HttpRequestMethodNotSupportedException.class) {
                url = "admin/common/500";
                System.out.println("--------毛有找到对应方法---------");
            } else if (ex.getClass() == ParameterException.class) {//自定义的异常

            } else if (ex.getClass() == UnauthorizedException.class) {
                url = "admin/common/unauth";
                System.out.println("--------毛有权限---------");
            }

            String header = req.getHeader("X-Requested-With");
            boolean isAjax = "XMLHttpRequest".equalsIgnoreCase(header);
            String method = req.getMethod();
            boolean isPost = "POST".equalsIgnoreCase(method);            if (isAjax || isPost) {                return Message.error(msg);
            } else {
                ModelAndView view = new ModelAndView(url);
                view.addObject("error", msg);
                view.addObject("class", ex.getClass());
                view.addObject("method", request.getRequestURI());                return view;
            }
        } catch (Exception exception) {
            logger.error(exception.getMessage(), exception);            return resultModel;
        } finally {
            logger.error(msg, ex);
            ex.printStackTrace();
        }
    }</pre>
  • *在web.xml中处理异常 *
<pre class="hljs xml" style="box-sizing: border-box; overflow: auto; font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 13px; padding: 15px; margin-top: 0px; margin-bottom: 20px; line-height: 1.42857; word-wrap: normal; color: rgb(101, 123, 131); background-color: rgb(246, 246, 246); border: 1px solid rgb(204, 204, 204); border-radius: 0px; text-size-adjust: none; word-break: break-word !important;">
<!-- 默认的错误处理页面 -->
<error-page>
    <error-code>403</error-code>
    <location>/403.html</location></error-page><error-page>
    <error-code>404</error-code>
    <location>/404.html</location>
</error-page>
<!-- 仅仅在调试的时候注视掉,在正式部署的时候不能注释 --><!-- 这样配置也是能够的,表示发生500错误的时候,转到500.jsp页面处理。 -->
<error-page> 
    <error-code>500</error-code> 
    <location>/500.html</location> 
</error-page> 
<!-- 这样的配置表示若是jsp页面或者servlet发生java.lang.Exception类型(固然包含子类)的异常就会转到500.jsp页面处理。 -->
<error-page> 
    <exception-type>java.lang.Exception</exception-type> 
    <location>/500.jsp</location> </error-page> <error-page> 
    <exception-type>java.lang.Throwable</exception-type> 
    <location>/500.jsp</location>
</error-page>
<!-- 当error-code和exception-type都配置时,exception-type配置的页面优先级高及出现500错误,发生异常Exception时会跳转到500.jsp-->
</pre>
  • 来一个问题:HandlerExceptionResolver和web.xml中配置的error-page会有冲突吗?

解答:若是resolveException返回了ModelAndView,会优先根据返回值中的页面来显示。不过,resolveException能够返回null,此时则展现web.xml中的error-page500状态码配置的页面。 当web.xml中有相应的error-page配置,则能够在实现resolveException方法时返回nullAPI文档中对返回值的解释:

return a corresponding ModelAndView to forward to, or null for default processing.

配套Ximnd学习导图下载地址

java思惟导图:https://gitee.com/1341541819.com/java_xmind/tree/master

写在最后

欢迎关注喜欢、和点赞后续将推出更多的思惟导图教程,敬请期待。 欢迎关注个人微信公众号免费获取更多更全的学习资源,视频资料,技术干货! 欢迎扫码关注 资源领取方式

公众号回复“学习”,拉你进程序员技术讨论群干货资源第一时间分享。

公众号回复“视频”,领取800GJava视频学习资源。 java学习全套 820G资源

公众号回复“全栈”,领取1T前端Java产品经理微信小程序Python等资源合集大放送。 全栈资料 java python 机器学习 产品经理 接近1T资源

公众号回复“慕课”,领取1T慕课实战学习资源。 慕课实战大全 php python 测试 后端 前端 前端 微信 1061G资源

公众号回复“实战”,领取750G项目实战学习资源。 先后端实战项目 750实战资源

公众号回复“面试”,领取8G面试实战学习资源。 JAVA面试实战视频 传智面试讲解 8G面试资源

相关文章
相关标签/搜索