zoukankan      html  css  js  c++  java
  • SpringMVC 入门

    SpringMVC 框架概述

    Spring Web MVC是基于Servlet API构建的传统Web框架,并且从一开始就已包含在Spring框架中

    与Spring Web MVC并行,Spring Framework 5.0引入了一个新的反应式Web框架,其名称“ Spring WebFlux;

    理解:

    首先SpringMVC 是一个MVC构架模式的web框架,是基于Servlet的,从Spring第一个版本就一起推出了,

    传统web框架,指的是SpringMVC依然使用多线程同步并发的方式来处理请求,现如今大家都在鼓吹异步并发多么多么好,从测试数据来看异步并发效率的确更好,但是其并不成熟,极大多数公司项目还没有更新到异步技术,盲目的进行重构可能会引发更多的问题, 并且异步编程在代码结构上会产生较大的变化,对于初学者而言,掌握难度是较大的;

    构架图:
    image-20200206122121806

    Spring-MVC在系统中的位置

    image-20200206122121806

    可以看出

    SpringMVC 并没有代替Servlet,它只是在Servlet上提供了一套封装好的组件,提高开发效率;

    还使得开发出的项目更加规范;否则每个人可能有每个人不同的MVC;

    SpringMVC核心组件

    思考:

    若没有SpringMVC框架,我们该如何去编写一个较大的web项目呢,可以发现在选课系统中出现了大量的Servlet,因为一个请求地址就需要一个Servlet,使得项目体积变大,且Servlet是长期存在内存的;

    第一步,我们希望用一个Servlet来处理多个请求甚至是所有请求,就需要实现能根据请求路径查找处理请求方法的逻辑,这也是SpringMVC要做的第一件事情;

    • DispatcherServlet:前端控制器
      用户请求首先到达前端控制器,它就相当于mvc模式中的c,DispatcherServlet是整个流程控制的调度中心,由它调用其它组件处理用户的请求,DispatcherServlet的存在降低了组件之间的耦合性。
    • Handler:处理器
      Handler是继DispatcherServlet前端控制器的后端控制器,DispatcherServlet会将请求发送至对应的Handler来进行处理。Handler是处理业务逻辑的地方,需要我们自己来编写具体代码,等同于之前的Service层
    • HandlerMapping:处理器映射器
      HandlerMapping负责根据用户请求路径找到Handler,springmvc提供了不同的映射器实现不同的映射方式,例如:BeanName映射,配置文件映射,注解映射等。
    • HandlAdapter:处理器适配器
      通过HandlerAdapter来执行Handler,因为Handler有不同形式,意味着调用方式是不同的,这是适配器模式的应用,我们也可以扩展适配器来实现新的Handler;
    • ViewResolver:视图解析器
      ViewResolver负责从Handler中获取数据和视图,根据逻辑视名称查找物理视图文件,并查找View对象,再生成View对象;
    • View:视图
      View的职责就是装配数据,SpringMVC框架提供了很多的View视图类型的支持,包括:jstlView、freemarkerView、pdfView等。常用视图就是jsp。我们需要根据业务需求,通过页面标签或页面模版技术将模型数据展示给用户

    当然还有一些其他的

    类型 说明
    HandlerExceptionResolver Handler异常处理器
    LocaleResolver 提供国际化的视图。根据不同地区显示不同内容
    ThemeResolver 根据不同地区提供个性化的布局
    MultipartResolver 解析multipart请求数据,如浏览器表单文件上传
    FlashMapManager 常用于通过重定向将属性从一个请求传递到另一个请求

    请求处理流程简述

    入门程序

    pom依赖

    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>org.example</groupId>
      <artifactId>MVC01</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>war</packaging>
    
      <name>MVC01 Maven Webapp</name>
      <!-- FIXME change it to the project's website -->
      <url>http://www.example.com</url>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
      </properties>
    
      <dependencies>
        <!--   SpringMVC -->
        <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>5.2.2.RELEASE</version>
        </dependency>
    
        <!--JEE相关的-->
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>jstl</artifactId>
          <version>1.2</version>
        </dependency>
        <dependency>
          <groupId>javax.servlet.jsp</groupId>
          <artifactId>javax.servlet.jsp-api</artifactId>
          <version>2.3.3</version>
          <scope>provided</scope>
        </dependency>
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>4.0.1</version>
          <scope>provided</scope>
        </dependency>
      </dependencies>
    </project>
    

    web.xml配置

    与在web项目中使用Spring中相同的是,我们也需要让SpringMVC随着web项目启动,SpringMVC的做法是利用DIspatcherServlet;

    <?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">
    
        <servlet>
            <servlet-name>DispatcherServlet</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>
    
    <!--    要交给SpringMVC处理的请求-->
        <servlet-mapping>
            <servlet-name>DispatcherServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>
    

    DispatcherServlet做了两个事情,1:初始化一个Spring容器,2:注册一个Servlet

    SpringMVC本质上也是一个Spring容器,在不涉及WEB时使用方法和Spring没有任何区别;ß

    url-pattern

    只有请求地址能够匹配到到被DispatcherServlet的url-pattern的请求才会被SpringMVC处理,那么那些请求要交给SpringMVC处理呢,通常是除静态资源以外的请求;

    常用pattern:

    pattern 说明
    / 除了.jsp 以外的所有请求
    /* 所有请求
    *.action 所有 以action结尾的请求

    需要说明的是action并不是固定的不同公司可能不同,但无论是点什么,其目的都是为了和静态资源加以区分

    创建控制器类

    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.mvc.Controller;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class TestController implements Controller {
    
        @Override
        public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
            ModelAndView modelAndView = new ModelAndView();//创建一个表示模型和视图的对象
            modelAndView.setViewName("index.jsp");//设置视图名称
            modelAndView.addObject("msg","hello springMVC");//添加视图需要的数据
            //httpServletRequest.setAttribute("msg","hello SpringMVC"); //等同于上面一行
            return modelAndView; //返回模型和视图给dispatcherServlet
        }
    }
    

    ModelAndView,其实就是把视图资源和数据打包到一起,然后视图名称交给视图解析器,Object放到请求中;

    注册控制器到容器中

    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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <bean name="/testController" class="com.yh.controller.TestController"/>
    </beans>
    

    DispatcherServlet是按照请求路径来查找Handler,我们必须告诉SpringMVC,这个控制器是用来处理哪个请求地址的,默认情况下,SpringMVC会查找beanName与请求地址相同的Handler来处理;

    测试:

    打开浏览器输入地址:http://localhost:8080/MVC01_war_exploded/testController

    image-20200206143953076

    我们在Request中添加了key为msg的字符内容hello SpringMVC

    看到上述内容说明SpringMVC以及成功处理了请求;

    注解配置Controller

    上述方法每个Controller只能处理一个请求地址,不够灵活,且需要Controller实现指定接口,这是就需要使用注解来配置Controller了;

    • @Controller

      该注解写在类上,用于注册控制器bean到容器中,这是之前以及学习过的

    • @RequestMapping("url")

      该注解写在方法上时,用于为方法指定要匹配的url,该url是相对根路径的

      写在类上时类上的url是相对于根路径,而类中方法则相对于类的url

    案列:

    @Controller
    //@RequestMapping("/user")
    public class UserController {
        @RequestMapping("/getMsg")
        public ModelAndView getMsg(){
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.setViewName("/index.jsp");
            modelAndView.addObject("msg","hello SpringMVC annotation!");
            return modelAndView;
        }
    }
    

    请求地址:http://localhost:8080/MVC01_war_exploded/getMsg,可正常访问

    当把类上注释的url打开时,上面的地址404了

    正确地址:http://localhost:8080/MVC01_war_exploded/user/getMsg

    需要注意的是:
    viewName路径若不带/时则从当前请求的位置查找文件,带/则表示从根路径查找

    默认配置阅览

    我们完成了一个简单的入门案例,但是你会发现除了DispatcherServlet之外没有出现其他上面提到过的组件,那么它们是不是没有作用呢?

    其实SpringMVC提供了很多默认配置,使我们可以快速的开项目,而无需繁琐的配置,在SpringMVC的包下可以找到一个DispatcherServlet.properties配置,这便是默认的配置文件了;

    RouterFunctionMapping和HandlerFunctionAdapter都是webFlux中的这里不多关注;

    HandlerMapping 映射方式
    BeanNameUrlHandlerMapping 用beanName作为url
    RequestMappingHandlerMapping 使用注解配置url
    HandlerAdapter 处理对象:
    HttpRequestHandlerAdapter 实现HttpRequestHandler的处理器
    SimpleControllerHandlerAdapter 实现Controller的处理器
    RequestMappingHandlerAdapter 使用注解的handler,无需实现接口
    SimpleServletHandlerAdapter Servlet类Handler,需继承HttpServlet

    SimpleServletHandlerAdapter默认是没有的,当需要使用Servlet相关API时使用,需要在配置文件中声明

    <bean class="org.springframework.web.servlet.handler.SimpleServletHandlerAdapter"/>
    

    注意:当手动添加了适配器后,系统就不会自动添加任何其他适配器了;

    SimpleServletHandlerAdapter案例:

    @Controller("/servletController")
    public class YouController extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.getWriter().println("servlet API");
        }
    }
    

    请求地址:http://localhost:8080/MVC01_war_exploded/servletController,记得注册Adapter到容器中;

    在上述4中handler中最常用的是使用注解形式的;

    视图解析配置

    视图解析器用于查找视图文件,及生成视图对象,我们不用过多关注,唯一会用到的就是,为视图名称配置前缀和后缀从而简化,Handler中的书写

    在一个实际项目中页面文件可能比较多,可以用文件夹管理,但是这导致我们在编写视图名称时更加繁琐,例如:

    handler中:

    这时就可在配置中对视图解析器进行相关设置;

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <!--指定视图类型-->
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
      <!--指定前缀-->
        <property name="prefix" value="/pages/jsp/"/>
      <!--指定后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
    

    处理器中:

    @RequestMapping("/getMsg")
    public ModelAndView getMsg(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("index");
        modelAndView.addObject("msg","hello SpringMVC annotation!");
        return modelAndView;
    }
    

    视图解析器会自动在viewName前后分别拼接前缀和后缀;如:/pages/jsp/index.jsp

    启用MVC 配置

    上面提到,SpringMVC默认会加载DispatcherServlet.properties中的配置作为默认配置,当我们需要添加额外的自定义配置时该怎么办呢?这是我们需要启用MVC配置,通过在配置文件中添加以下标签

    <mvc:annotation-driven/>
    

    为了减少配置项,该标签向容器中添加了提供MVC基础服务的Bean,并添加了json,xml,的转换器

    有兴趣可以源码位置:web包下的AnnotationDrivenBeanDefinitionParser,

    此时看不出该标签对系统有什么影响,但在后续自定义验证器,转换器时就不得不使用到该标签了

    官方原话:

    "in XML configuration, you can use the `<mvc:annotation-driven/>` element to enable MVC configuration, the preceding example registers a number of Spring MVC infrastructure beans and adapts to dependencies available on the classpath (for example, payload converters for JSON, XML, and others)"
    
  • 相关阅读:
    UOJ.26.[IOI2014]Game(交互 思路)
    Good Bye 2016 F.New Year and Finding Roots(交互)
    Codeforces.835E.The penguin's game(交互 按位统计 二分)
    Codeforces.744B.Hongcow's Game(交互 按位统计)
    Codeforces.862D.Mahmoud and Ehab and the binary string(交互 二分)
    正睿OI 提高 Day1T3 ZYB玩字符串(DP)
    划分vlan
    2三层交换机实现vlan间的路由
    交换机基础-交换机远程telnet
    自动化运维环境的搭建问题处理
  • 原文地址:https://www.cnblogs.com/yangyuanhu/p/12271415.html
Copyright © 2011-2022 走看看