SpringMVC

作者: Roct | 来源:发表于2019-08-13 23:11 被阅读0次

    SpringMVC概述

    什么是MVC设计

    • Controller: 负责接收并处理请求, 响应客户端
    • Model: 模型数据, 业务逻辑
    • View: 呈现模型, 与用户进行交互
    MVC设计模式

    SpringMVC

    • 目前最好的实现MVC设计模式的框架
    • Spring框架的一个后续产品
    • Spring框架的一个子模块, 二者可以很好的结合使用, 不需要整合

    详解

    SpringMVC核心组件

    • DispatcherServlet: 前置控制器
    • Handler: 处理器, 完成具体的业务逻辑
    • HandlerMapping: 将请求映射到Handler
    • HandlerInterceptor: 处理器拦截器
    • HandlerExecutionChain: 处理器执行链
    • HandlerAdapter: 处理器适配器
    • ModelAndView: 装载模型数据和视图信息
    • ViewResolver: 视图解析器

    SpringMVC的实现流程/原理

    • 客户端请求被DispatcherServlet接收
    • DispatcherServlet将请求映射到Handler
    • 生成Handler以及HandlerInterceptor
    • 返回HandlerExecutionChain(Handler + HandlerInterceptor)
    • DispatcherServlet通过HandlerAdapter执行Handler
    • 返回一个ModelAndView
    • DispatcherServlet通过ViewResolver进行解析
    • 返回填充了模型数据的View, 响应给客户端
    SpringMVC的实现流程/原理

    SpringMVC的使用

    基于XML配置的使用

    • SpringMVC基础配置
    • XML配置Controller, HandlerMapping组件映射
    • XML配置ViewResolver组件映射
    • 具体代码实现
      • 配置pom.xml
      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.11</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>4.0.0.RELEASE</version>
        </dependency>
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
          <version>2.5</version>
        </dependency>
      </dependencies>
      
      • 设置web.xml
        <web-app>
          <display-name>Archetype Created Web Application</display-name>
          <servlet>
            <servlet-name>SpringMVC</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>
          </servlet>
          <servlet-mapping>
            <servlet-name>SpringMVC</servlet-name>
            <url-pattern>/</url-pattern>
          </servlet-mapping>
        </web-app>
      
      • 设置SpringMVC
        <?xml version="1.0" encoding="UTF-8"?>
        <beans xmlns="http://www.springframework.org/schema/beans"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        
            <!--配置HandlerMapping, 将url请求映射到Handler-->
            <bean id="handlerMapping"
                  class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
                <!--配置mapping-->
                <property name="mappings">
                    <props>
                        <!--配置test请求对应的handler-->
                        <prop key="/test">testHandler</prop>
                    </props>
                </property>
            </bean>
            <!--配置Handler-->
            <bean id="testHandler" class="com.rui.handler.MyHandler">
        
            </bean>
            <!--配置视图解析器, 将逻辑视图解析为UI视图-->
            <bean
                    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <!--配置前缀-->
                <property name="prefix" value="/" />
                <!--配置后缀-->
                <property name="suffix" value=".jsp" />
            </bean>
        </beans>
      
      • 实现Controller的handleRequest方法, 拦截请求
      public class MyHandler implements Controller {
        public ModelAndView   handleRequest(javax.servlet.http.HttpServletRequest request,
                                          javax.servlet.http.HttpServletResponse response)
                throws Exception {
              // 装在模型数据和逻辑视图
              ModelAndView modelAndView = new ModelAndView();
              // 添加模型数据
              modelAndView.addObject("name", "Tom");
              // 添加逻辑视图, 显示show.jsp
              modelAndView.setViewName("show");
              return modelAndView;
          }
      }
      
      • show.jsp
      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      <%@ page isELIgnored="false" %>
      <html>
      <head>
        <title>Title</title>
      </head>
      <body>
      ${name}
      </body>
      </html>
      
      • 项目结构


        项目结构
      • 访问localhost:8080/test即可访问到show.jsp

    基于注解方式的使用

    • SpringMVC基础配置
    • Controller, HandlerMapping通过注解进行映射
    • XML配置ViewResolver组件映射
    • 具体代码实现
      • 配置Spring servlet拦截器, web.xml
          <web-app>
          <display-name>Archetype Created Web Application</display-name>
          <servlet>
            <servlet-name>SpringMVC</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>
          </servlet>
          <servlet-mapping>
            <servlet-name>SpringMVC</servlet-name>
            <url-pattern>/</url-pattern>
          </servlet-mapping>
        </web-app>
      
      • 配置spring配置文件
        <!--将AnnotationHandler自动扫秒进来-->
        <context:component-scan base-package="com.rui.handler" />
        <!--配置视图解析器, 将逻辑视图解析为UI视图-->
        <bean
                class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!--配置前缀-->
            <property name="prefix" value="/" />
            <!--配置后缀-->
            <property name="suffix" value=".jsp" />
        </bean>
      
      • Controller, @RequestMapping映射到jsp上
        @Controller
        public class AnnotationHandler {
            /**
             * 业务方法: ModelAndView完成数据的传递, 视图的解析
             */
            @RequestMapping("/modelAndView")
            public ModelAndView modelAndView() {
                // 创建ModelAndView对象
                ModelAndView modelAndView = new ModelAndView();
                // 填充模型
                modelAndView.addObject("name", "Tom");
                // 设置逻辑视图
                modelAndView.setViewName("show");
                return modelAndView;
            }
            /**
             * 另外一种
             */
            @RequestMapping("/modelTest")
            public String ModelTest(Model model) {
                // 填充模型
                model.addAttribute("name", "jerry");
                // 设置逻辑视图
                return "show";
            }
            /**
             * 第三种
             */
            @RequestMapping("/modelMap")
            public String ModelMap(ModelMap modelMap) {
                // 填充模型
                modelMap.put("name", "your baba");
                return "show";
            }
        }
      
      • 项目的目录结构如上

    SpringMVC数据绑定

    • 什么是数据绑定
      将HTTP请求中的参数绑定到Handler业务方法的形参.


      数据绑定原理图解
      1. SpringMVC初始化时,RequestMappingHandlerAdapter类会把一些默认的参数解析器添加到argumentResolvers中。当SpringMVC接收到请求后首先根据url查找对应的HandlerMethod
      2. 遍历HandlerMethodMethodParameter数组
      3. 根据MethodParameter的类型来查找确认使用哪个HandlerMethodArgumentResolver,遍历所有的argumentResolverssupportsParameter(MethodParameter parameter)方法。。如果返回true,则表示查找成功,当前MethodParameter,使用该HandlerMethodArgumentResolver。这里确认大多都是根据参数的注解已经参数的Type来确认。
      4. 解析参数,从request中解析出MethodParameter对应的参数,这里解析出来的结果都是String类型。
      5. 转换参数,把对应String转换成具体方法所需要的类型,这里就包括了基本类型、对象、List、Set、Map。
    • 常用的数据绑定类型
      • 基本数据类型
      • 包装类
      • 数组
      • 对象
      • 集合(List, Set, Map)
      • JSON

    RESTful API

    RESTful风格概述

    • REST: Representational State Transfer(表述性状态转移)
    • REST并不是一种创新技术, 它指的是一组架构约束条件和原则
    • 符合REST的约束条件和原则的架构, 被称为RESTful架构

    RESTful核心内容

    • 资源与URI: URI就是资源的地址
    • 资源的表述: 客户端和服务器之间传送就是资源的表述
    • 状态转移: 资源在客户端发生变迁, 进入后续的状态, 即客户端获取资源以后可能对资源进行修改

    RESTful架构特点

    • 统一了客户端访问资源的接口
    • url更加简洁, 易于理解, 便于扩展
    • 有利于不同系统之间的资源共享

    RESTful的四种基本操作

    • GET: 获取资源, 获取数据的时候, 跟的参数为/参数, 没有问号
    • POST: 新建资源
    • PUT: 修改资源
    • DELETE: 删除资源
    @GetMapping(value="/getById/{id}")
    public ModelMap getById(@PathVariable(value="id") int id) {
    }
    

    SpringMVC 拦截器

    • Maven中设置版本
      <properties>
        <spring-version>4.3.4.RELEASE</spring-version>
      </properties>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>${spring-version}</version>
       </dependency>
    
    • 配置DispatcherServlet
      web.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
          <display-name>Archetype Created Web Application</display-name>
          <servlet>
            <servlet-name>SpringMVC</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>
          </servlet>
          <servlet-mapping>
            <servlet-name>SpringMVC</servlet-name>
            <url-pattern>/</url-pattern>
          </servlet-mapping>
    </web-app>
    

    springmvc.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
        <!--自动扫秒-->
        <context:component-scan base-package="com.rui" />
        <!--配置视图解析器, 将逻辑视图解析为UI视图-->
        <bean
                class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!--配置前缀-->
            <property name="prefix" value="/" />
            <!--配置后缀-->
            <property name="suffix" value=".jsp" />
        </bean>
    </beans>
    

    拦截器与过滤器

    • 拦截器与过滤器之间的区别
      • 拦截器是使用JDK动态代理实现的, 拦截的是对应调用方法的拦截
      • 过滤器是使用Filter实现的, 拦截的是request对象

    SpringMVC拦截器的配置和应用

    • SpringMVC也可以使用拦截器对请求进行拦截处理, 用户可以自定义拦截器来实现特定的功能, 自动以的拦截器必须实现HandlerInterceptor接口
      • preHandler(): 这个方法在业务处理器处理请求之前被调用, 在该方法中对用户请求request进行处理, 返回值为Boolean, 返回false不继续执行, 返回true会继续执行
      • postHandler(): 这个方法在业务处理器处理完请求后, 但是DispatcherServlet向客户端返回响应前被调用, 在该方法中对用户请求request进行处理
      • afterCompletion():这个方法在DispatcherServlet完全处理完请求后被调用, 可以在该方法中进行一些资源清理的操作. 多个拦截器的时候, 等拦截器执行完毕以后才会执行这个方法
    • 拦截器的配置
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd">
    
        <!--自动扫秒-->
        <context:component-scan base-package="com.rui" />
        <!--    拦截器的注册-->
        <mvc:interceptors>
            <mvc:interceptor>
                <mvc:mapping path="/user/**"/>
                <!--    update这个方法不走拦截器      -->
                <mvc:exclude-mapping path="/user/update"/>
                <bean class="com.rui.Interceptor.LoginInterceptor" />
            </mvc:interceptor>
            
        </mvc:interceptors>
        <!--配置视图解析器, 将逻辑视图解析为UI视图-->
        <bean
                class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!--配置前缀-->
            <property name="prefix" value="/" />
            <!--配置后缀-->
            <property name="suffix" value=".jsp" />
        </bean>
    </beans>
    
    • 拦截器的实现
    public class LoginInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest httpServletRequest,
                                 HttpServletResponse httpServletResponse,
                                 Object o) throws Exception {
            System.out.println("preHandler");
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest httpServletRequest,
                               HttpServletResponse httpServletResponse,
                               Object o,
                               ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle");
    
        }
    
        @Override
        public void afterCompletion(HttpServletRequest httpServletRequest,
                                    HttpServletResponse httpServletResponse,
                                    Object o, Exception e) throws Exception {
            System.out.println("afterCompletion");
    
        }
    }
    

    当用户访问类似user/searchuser/search/11接口的时候就会进入拦截器, 可以在用户进入以后进行处理登录等操作.

    SpringMVC 全局异常

    无SpringMVC全局异常的流程图

    无SpringMVC全局异常的流程图

    有SpringMVC全局异常的流程图

    有SpringMVC全局异常的流程图

    Spring和SpringMVC包扫描隔离

    # Spring配置文件
    <context:component-scan base-package="com.rui" annotation-config="true">
          <context:exclude-filter type="annotation"
                                    expression="org.springframework.stereotype.Controller" />
     </context:component-scan>
    
    # SpringMVC配置文件
    <context:component-scan base-package="com.rui.controller"
                            use-default-filters="false"
                            annotation-config="true">
        <context:include-filter type="annotation"
                                expression="org.springframework.stereotype.Controller" />
    </context:component-scan>
    

    代码实现

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    import org.springframework.web.servlet.HandlerExceptionResolver;
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.view.json.MappingJacksonJsonView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @Component
    public class ExceptionResolver implements HandlerExceptionResolver {
        Logger logger = LoggerFactory.getLogger(ExceptionResolver.class);
        @Override
        public ModelAndView resolveException(HttpServletRequest httpServletRequest,
                                             HttpServletResponse httpServletResponse, Object o, Exception e) {
            logger.error("{} Exception", httpServletRequest.getRequestURI(), e);
            ModelAndView modelAndView = new ModelAndView(new
                    MappingJacksonJsonView());
            // 当使用是jackson2.x的时候后, 使用MappingJackson2JsonView
            modelAndView.addObject("status", ResponseCode.ERROR.getCode());
            modelAndView.addObject("msg", "接口异常");
            modelAndView.addObject("data", e.toString());
            return modelAndView;
        }
    }
    
    

    相关文章

      网友评论

          本文标题:SpringMVC

          本文链接:https://www.haomeiwen.com/subject/hzgijctx.html