JavaEE之SpringMVC的使用

七、Spring MVC

7.1 MVC 思想(概念)

模型-视图-控制器(MVC)是一个众所周知的以设计界面应用程序为基础的设计思想。它主要通过分离模型、视图及控制器在应用程序中的角色将业务逻辑从界面中解耦。

  • 模型:

    负责封装应用程序数据在视图层展示。

  • 视图:

    仅仅只是展示这些数据,不包含任何业务逻辑。

  • 控制器:

    负责接收来自用户的请求,并调用后台服务(service或者dao)来处理业务逻辑。

处理后,后台业务层可能会返回了一些数据在视图层展示。控制器收集这些数据及准备模型在视图层展示。

MVC模式的核心思想是将业务逻辑从界面中分离出来,允许它们单独改变而不会相互影响。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YEgjHYMp-1651160155894)(JavaEE.assets/1651121869179.png)]

7.2 SpringMVC 理解

7.2.1 概念:

​ Spring MVC是Spring家族中的一个web成员,它是一种基于Java的实现了Web MVC设计思想的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring MVC也是要简化我们日常Web开发的。

​ Spring MVC是服务到工作者思想的实现。中央控制器是DispatcherServlet;应用控制器拆为处理器 映射器(Handler Mapping)进行处理器管理和视图解析器(View Resolver)进行视图管理;支持本地化/国际化(Locale)解析及文件上传等;提供了非常灵活的数据验证、格式化和数据绑定机制;提供了强大的约定大于配置(惯例优先原则)的契约式编程支持。

7.2.2 作用:
  1. 让我们能非常简单的设计出干净的Web层;
  2. 进行更简洁的Web层的开发;
  3. 天生与Spring框架集成(如IOC容器、AOP等);
  4. 提供强大的约定大于配置的契约式编程支持;
  5. 能简单的进行Web层的单元测试;
  6. 支持灵活的URL到页面控制器的映射;
  7. 非常容易与其他视图技术集成,如jsp、Velocity、FreeMarker等等,因为模型数据不放在特定的API里,而是放在一个Model里(Map数据结构实现,因此很容易被其他框架使用);
  8. 非常灵活的数据验证、格式化和数据绑定机制,能使用任何对象进行数据绑定,不必实现特定框架的API;
  9. 支持灵活的本地化等解析;
  10. 更加简单的异常处理;
  11. 对静态资源的支持;
  12. 支持Restful风格。
7.2.3 SpringMVC 请求流程

​ Spring MVC框架也是一个基于请求驱动的Web框架,并且使用了前端控制器模式(是用来提供一个集中的请求处理机制,所有的请求都将由一个单一的处理程序处理来进行设计,再根据请求映射规则分发给相应的页面控制器(动作/处理器)进行处理。首先让我们整体看一下Spring MVC处理请求的流程:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c6E7t9Cq-1651160155895)(JavaEE.assets/1651122327182.png)]

  • 流程分析:
  1. 首先用户发送请求,请求被SpringMvc前端控制器(DispatherServlet)捕获;

  2. 前端控制器(DispatherServlet)对请求URL解析获取请求URI,根据URI,调用HandlerMapping;

  3. 前端控制器(DispatherServlet)获得返回的HandlerExecutionChain(包括Handler对象以及

    Handler对象对应的拦截器);

  4. DispatcherServlet 根据获得的 HandlerExecutionChain,选择一个合适的HandlerAdapter。(附

    注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(…)方法);

  5. HandlerAdapter根据请求的Handler适配并执行对应的Handler;HandlerAdapter(提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据配置,Spring将做一些额外的工作:

    • HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息。
    • 数据转换:对请求消息进行数据转换。如String转换成Integer、Double等数据格式化:
    • 数据格式化: 如将字符串转换成格式化数字或格式化日期等
    • 数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中)
  6. Handler执行完毕,返回一个ModelAndView(即模型和视图)给HandlerAdaptor

  7. HandlerAdaptor适配器将执行结果ModelAndView返回给前端控制器。

  8. 前端控制器接收到ModelAndView后,请求对应的视图解析器。

  9. 视图解析器解析ModelAndView后返回对应View;

  10. 渲染视图并返回渲染后的视图给前端控制器。

  11. 最终前端控制器将渲染后的页面响应给用户或客户端

7.2.4 Spring MVC 优势
  1. 清晰的角色划分:前端控制器(DispatcherServlet)、请求到处理器映射(HandlerMapping)、处理器适配器(HandlerAdapter)、视图解析器(ViewResolver)、处理器或页面控制器 Controller)、验证器( Validator)、命令对象(Command 请求参数绑定到的对象就叫命令对象)、表单对象(Form Object 提供给表单展示和提交到的对象就叫表单对象)。
  2. 分工明确,而且扩展点相当灵活,可以很容易扩展,虽然几乎不需要;
  3. 和Spring 其他框架无缝集成,是其它Web框架所不具备的;
  4. 可适配,通过HandlerAdapter可以支持任意的类作为处理器;
  5. 可定制性,HandlerMapping、ViewResolver等能够非常简单的定制;
  6. 功能强大的数据验证、格式化、绑定机制;
  7. 利用Spring提供的Mock对象能够非常简单的进行Web层单元测试;
  8. 本地化、主题的解析的支持,使我们更容易进行国际化和主题的切换。
  9. 强大的JSP标签库,使JSP编写更容易。

还有比如RESTful(一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条

件。它主要用于客户端和服务器交互类的软件,目前了解即可)风格的支持、简单的文件上传、约定大

于配置的契约式编程支持、基于注解的零配置支持等等。

7.2.5 Spring MVC 环境搭建

新建wep-app项目

pom.xml坐标添加—>配置web.xml—>配置spring.xml—>页面控制器编写—>视图页面(.jsp)编写—>启动服务器

  1. pom.xml 坐标添加

    <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>11</maven.compiler.source>
            <maven.compiler.target>11</maven.compiler.target>
        </properties>
        <dependencies>
            <!-- spring web -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
                <version>5.2.4.RELEASE</version>
            </dependency>
            <!-- spring mvc -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>5.2.4.RELEASE</version>
            </dependency>
            <!-- web servlet -->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>3.0.1</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <!-- 编译环境插件 -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.3.2</version>
                    <configuration>
                        <source>11</source>
                        <target>11</target>
                        <encoding>UTF-8</encoding>
                    </configuration>
                </plugin>
                <!-- jetty插件 -->
                <plugin>
                    <groupId>org.eclipse.jetty</groupId>
                    <artifactId>jetty-maven-plugin</artifactId>
                    <version>9.4.27.v20200227</version>
                    <configuration>
                        <scanIntervalSeconds>10</scanIntervalSeconds>
                        <!-- 设置端口 -->
                        <httpConnector>
                            <port>8080</port>
                        </httpConnector>
                        <!-- 设置项目路径 -->
                        <webAppConfig>
                            <contextPath>/springmvc01</contextPath>
                        </webAppConfig>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
  2. 配置 web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app id="WebApp_ID" version="3.0"
             xmlns="http://java.sun.com/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    
        <!-- 编码过滤 utf-8 -->
        <filter>
            <description>char encoding filter</description>
            <filter-name>encodingFilter</filter-name>
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
            <init-param>
                <param-name>encoding</param-name>
                <param-value>UTF-8</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>encodingFilter</filter-name>
            <url-pattern>/*
        
    
        
        
            springMvc
            org.springframework.web.servlet.DispatcherServlet
            
                contextConfigLocation
                classpath:spring.xml
            
            
            1
        
        
        
            springMvc
            
            /
            
        
    
    
    

    要想启动我们的 SpringMVC 环境,目前对于 mvc 框架的配置还未进行。以上在 web.xml 中引用了

    spring.xml 文件。

  3. spring.xml 配置

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc.xsd
            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.xxxx.controller"/>
    
        <!-- 使用默认的 Servlet 来响应静态文件 -->
        <mvc:default-servlet-handler/>
    
        <!-- 开启注解驱动-->
        <mvc:annotation-driven/>
    
        <!-- 配置视图解析器 -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
              id="internalResourceViewResolver">
            <!-- 前缀:在WEB-INF目录下的jsp目录下 -->
            <property name="prefix" value="/WEB-INF/jsp/"/>
            <!-- 后缀:以.jsp结尾的资源 -->
            <property name="suffix" value=".jsp"/>
        </bean>
    
    </beans>
    
  4. 页面控制器的编写

    @Controller
    @RequestMapping("user")
    public class HelloConstroller {
        @RequestMapping("hello")
        public ModelAndView hello(){
            ModelAndView mv = new ModelAndView();
            mv.addObject("msg","hello springmvc");
            mv.setViewName("hello");
            return mv;
        }
    
  5. 添加视图页面

    在 WEB-INF 下新建 jsp 文件夹 ,并在文件夹下新建 hello.jsp

    <%--
      Created by IntelliJ IDEA.
      User: KT
    --%>
    <%@ page contentType="text/html;charset=UTF-8" isELIgnored="false" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <!-- el表达式接收参数值 -->
        <h2>${msg}</h2>
    </body>
    </html>
    
    
  6. 启动 jetty/tomcat 服务器开启测试

7.3 URL 地址映射配置

@RequestMapping

细化请求路径

通过注解 @RequestMapping 将请求地址与方法进行绑定,可以在类级别和方法级别声明。类级别的注解负责将一个特定的请求路径映射到一个控制器上,将 url 和类绑定;通过方法级别的注解可以细化映射,能够将一个特定的请求路径映射到某个具体的方法上,将 url 和类的方法绑定。

7.3.1 映射单个 URL

@RequestMapping("") 或 @RequestMapping(value="") 声明在方法上面,映射单个 URL

访问地址:(如果有类路径需要写在方法路径前面)

@Controller
public class DataController {
    @RequestMapping("test")
    public void test(Integer age,String name){
        System.out.println(age+"---"+name);
    }
7.3.2 映射多个 URL

@RequestMapping({"",""}) 或 @RequestMapping(value={"",""}) 声明在方法上面,映射多个 URL,多个地址都可以映射到同一个方法

7.3.3 映射 URL 在控制器上
  • 用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

  • @RequestMapping 声明在类上面,类中的的方法都是以该地址作为父路径

  • 声明级别:

​ 类级别 + 方法级别 (/类路径/方法路径)

7.3.4 设置URL 映射的请求方式

默认没有设置请求方式,在HTTP 请求中最常用的请求方法是 GET、POST,还有其他的一些方法,如:DELETE、PUT、HEAD 等。

可以通过 method 属性设置支持的请求方式,如 method=RequestMethod.POST;如设置多种请求方式,以大括号包围,逗号隔开即可。

  • 设置了请求方式,则只能按照指定的请求方式请求。

  • 访问地址:(只能使用POST请求访问)

7.3.5 通过参数名称映射 URL

通过参数名称访问

  • 访问地址:

    http://ip:port/springmvc01/url?test06

    其中?后面的内容是参数

    @RequestMapping(params = "test06") 
    public ModelAndView test06(){ 
        ModelAndView modelAndView = new ModelAndView(); 		      		      modelAndView.addObject("hello","test06");  
        modelAndView.setViewName("hello"); return modelAndView; 
    }
    

7.4 参数绑定

客户端请求的参数到控制器功能处理方法上的参数的绑定,对于参数绑定非常灵活。

7.4.1 基本数据类型
  • 参数值必须存在。如果没有指定参数值,也没有设置参数默认值,则会报500异常。

  • 通过注解 @RequestParam 标记一个形参为请求参数。(注解声明在形参的前面)

    * 可以通过注解的属性设置相关内容

    * 设置参数的默认值 defaultValue

7.5 请求转发与重定向

SpringMVC 默认采用服务器内部转发的形式展示页面信息。同样也支持重定向页面。

7.5.1 重定向

重定向是发一个302的状态码给浏览器,浏览器自己去请求跳转的网页。地址栏会发生改变。

  • 页面中获取参数值
    • ${param.参数名}
7.5.2 请求转发

请求转发,直接调用跳转的页面,让它返回。对于浏览器来说,它无法感觉服务器有没有forward。 地址栏不发生改变。可以获取请求域中的数据

  • 页面中获取数据

    • 获取传递的参数:${param.参数名}

    • 获取请求域的数据:${请求域中设置的名称}

  • 注意:

    如果没有redirect和forward这两个跳转行为,Spring MVC会介入视图解析器加上前后缀

7.6 JSON数据开发

  • 概念

    Json 在企业开发中已经作为通用的接口参数类型,在页面(客户端)解析很方便。SpringMVC 对于json 提供了良好的支持,这里需要修改相关配置,添加 json 数据支持功能

  • @ResponseBody

    该注解用于将 Controller 的方法返回的对象,通过适当的 HttpMessageConverter 转换为指定格式后,写入到 Response 对象的 body 数据区。

    返回的数据不是 html 标签的页面,而是其他某种格式的数据时(如 json、xml 等)使用(通常用于ajax 请求)。

  • @RequestBody

    该注解用于读取 Request 请求的 body 部分数据,使用系统默认配置的 HttpMessageConverter 进行解析,然后把相应的数据绑定到要返回的对象上 ,再把 HttpMessageConverter 返回的对象数据绑定到controller 中方法的参数上。

7.7 拦截器

  • 概念

    SpringMVC 中的 Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理。比如通过它来进行权限验证,或者是来判断用户是否登陆等操作。

  • 对于 SpringMVC拦截器的定义方式有两种:

    1. 实现接口:org.springframework.web.servlet.HandlerInterceptor

    2. 继承适配器:org.springframework.web.servlet.handler.HandlerInterceptorAdapter

你可能感兴趣的:(JavaEE,java-ee,java,spring)