思维导图IT技术篇

思维导图学习 | 第十篇:java学习中级篇(框架),让Spri

2019-04-25  本文已影响5人  程序员手札

写在前面

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

已经很久没有发文章了呀,想必大家都挂念我了,哈哈。

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

首先我们看下一个MVC的完整的思维导图

完整Spring MVC思维导图

spring mvc简介与运行原理

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

Spring MVC流程

主要注解

spring mvc注解

ContextLoaderListener

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

web.xml加载过程

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

web.xml配置

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

<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处理请求的流程
<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>

其中

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)很相像,不过它比后者提供了更灵活的方式。比如它能提供异常被抛出时正在执行的是哪个处理器这样的信息。

<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>
<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>
<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>

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

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面试资源
上一篇 下一篇

猜你喜欢

热点阅读