SpringMVC01_MVC的执行和注解开发

一、SpringMVC概述

​ SpringMVC 是 Spring 框架的一个模块,因此 SpringMVC 无需和 Spring 进行整合就可以使用。SpringMVC 是一个基于 MVC 的 Web 框架,即 Spring Web MVC。Spring Web MVC 和 Struts2 都属于表现层的框架,它是 Spring 框架的一部分。

<!-- 引入 Spring 框架的 WebMVC 的依赖 -->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-webmvc</artifactId>
	<version>5.1.5.RELEASE</version>
</dependency>

(一)SpringMVC 的执行流程

​ 1.用户发起请求,请求被 servlet 拦截后,转发给 MVC 框架

​ 2.SpringMVC 中的 DispacherServlet 核心控制器,接受请求并转发给 HandlerMapping

​ 3.HandlerMapping 负责解析请求根据请求信息和配置信息找到匹配的 Controller 类,如果配置了拦截器会按照顺序执行拦截器中的 preHandler 方法

​ 4.找到匹配的 Controller 后会把请求参数传递给 Controller 里面的方法

​ 5.Controller 里面的方法执行完成之后会返回一个 ModeAndView 对象(视图名称和需要传递给视图的模型数据)

​ 6.视图解析器根据名字找到视图并把数据模型填充到视图内,再渲染成 HTML 内容,返回网页。

image-20230420164010301

(二)Spring MVC 入门案例

​ 1.从 mvn 模板新建一个 webapp,添加如下依赖

<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>5.3.20</version>
  </dependency>

  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.26</version>
  </dependency>

  <dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.15</version>
  </dependency>

  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
  </dependency>

  <dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>javax.servlet.jsp-api</artifactId>
    <version>2.3.1</version>
  </dependency>

  <dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
  </dependency>

  <dependency>
    <groupId>taglibs</groupId>
    <artifactId>standard</artifactId>
    <version>1.1.2</version>
  </dependency>
</dependencies>

​ 2.在 web.xml 中配置前端控制器

​ 可以引入 spring-beans.xml 的头文件,MVC 是 Spring 中的模块,所以 SpringMVC 和 Spring 有着相同的头部信息。

​ 配置 DispatcherServlet 时,需要为其 contextConfigLocation 属性指定要加载的 SpringMVC 的配置 文件。该文件中指定 SpringMVC 框架需要使用的处理器映射器、处理器适配器、视图解析器等组件。、

​ 如果 DispatcherServlet 初始化时没有为 contextConfigLoaction 属性指定要加载的文件,那么前端控制器就默认加载类路径下的以 DispatcherServlet 的 Servlet 名称-servlet.xml 格式的配置文件。

<!-- 配置前端控制器 -->
<servlet>
    <servlet-name>SpringMVC</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--配置初始化参数,为 contextConfigLocation 属性指定要加载的 SpringMVC 的配置文件,
    如果不配置,则默认加载 DispatcherServlet 的 ServletName 为名称的配置文件,例如:
    SpringMVC-servlet.xml
    -->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
</servlet>

​ 3.配置前端控制器映射

​ 下面的 url-pattern 表示凡是以 action 结尾的任何请求都会被这个 DispacherServlet 所解析

<!-- 配置前端控制器的映射 -->
<servlet-mapping>
	<servlet-name>SpringMVC</servlet-name>
	<url-pattern>*.action</url-pattern>
</servlet-mapping>

​ 4.处理器映射器

​ SpringMVC 提供了 一个 BeanNameUrlHandlerMapping 的处理器映射器类。该类的作用是将容器中 Java Bean 的 name 属性当作 url 来进行匹配,改类是 SpringMVC 框架使用,因此不需要为该 Bean 配置 id。

​ BeanNameUrlHandlerMapping:根据 bean 名称匹配 URL 地址,即下面的 Handler 处理器。

<!-- 配置处理器映射器 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

​ 5.配置处理器适配器

​ MVC 框架提供了 SimpleControllerHandlerAdapter 处理器适配器类,用于执行相应的 Handler 类。Handler 类就是我们需要编写的代码。

<!-- 配置处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

​ 6.配置处理器适配器

<!-- 配置 Handler 处理器 -->
<bean name="/book_list.action" class="com.ls.springmvc.controller.BookController"/>

​ 7.编写 Handler 处理器

@Data
@Accessors(chain = true)
public class Book {
    private Long id;
    private String name;
    private Double price;
}

public class BookController implements Controller {
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ModelAndView modelAndView = new ModelAndView();
        ArrayList<Book> books = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            books.add(new Book().setId(Long.valueOf(i)).setName("spring"+i).setPrice(100.00+i));
        }
        modelAndView.addObject("bookList",books);
        modelAndView.setViewName("bookList");
        return modelAndView;
    }
}

​ 8.配置视图解析器

​ MVC 框架中提供了 InternalResourceViewResolver 视图解析器类,该类为 SpringMVC 框架使用,因此只需要将其配置到 Spring 容器中即可,不需要提供 id 属性。

​ prefix 属性:用于配置物理视图 url 路径中固定的前缀部分。

​ suffix 属性:用于配置物理视图 url 路径中固定的后缀路径。

​ 所以上面的处理器的全名称应该为 modelAndView.setViewName("/WEB-INF/jsp/bookList.jsp");

<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
</bean>

9.编写 JSP

​ 注意有的版本的 isELIgnored 是 false 也有的是 true,所以直接在头声明。将所有的 JSP 页面放到 web-inf 下,因为浏览器不能直接请求 web-inf 下的页面,只能通过后端程序完成请求转发,方便在后台控制。

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    图书列表:${bookList}
</body>
</html>

10.打包发布

​ 成功显示

​ 这一部分配置比较多,所以需要结合 MVC 的执行流程来看才能更清楚。

image-20230420170212506

(三) 非注解的映射器、适配器

1.映射器

​ 前面我们使用处理器映射器 BeanNameUrlHandlerMappinp 配置处理器映射器,但是她不能对 bean 的 url 进行集中管理,SpringMVC提供了可以进行 url 与 bean 映射的映射器 SimpleUrlHandlerMapping ,需要为其属性 mappings 提供一个 Properties 集合对象。其中 Properties 属性对象的 key 值就是 url,value 值就是 handler bean 的 id 属性值。

​ 更改配置如下所示,其中 HelloController 依然是实现了 Controller。

    <!-- 配置处理器映射器 -->
<!--        <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>-->
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/person.action">personController</prop>
                <prop key="/hello.action">helloController</prop>
            </props>
        </property>
    </bean>

    <!-- 配置 Handler 处理器 -->
    <bean id="personController" class="com.ls.controller.PersonController"/>
    <bean id="helloController" class="com.ls.controller.HelloController"/>

image-20230422171732898

2.适配器

​ SpringMVC 还提供了另外一种非注解的处理器适配器 HttpRequestHandlerAdapter,其中包含两个主要的方法,supports 方法返回一个布尔类型的值,用于判断只有 HttpRequestHandler 类型的对象才可以被当作 Handler 来执行。HttpRequestHandler 是 SpringMVC 框架提供的一个接口,只要实现了该接口的类都可以被当作 Handler 对象来执行。handle 方法执行一 个 Handler 对象,并返回一个 ModelAndView 逻辑视图。

      <!-- 配置处理器映射器 -->
    <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/book.action">bookController</prop>
            </props>
        </property>
    </bean>

<!-- 配置处理器适配器 -->
<!--    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>-->
        <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>

    <!-- 配置 Handler 处理器 -->
<!--    <bean id="personController" class="com.ls.controller.PersonController"/>-->
<!--    <bean id="helloController" class="com.ls.controller.HelloController"/>-->
    <bean id="bookController" class="com.ls.controller.BookController"></bean>

​ 需要编写的 Controller 实现 HttpRequestHandler

public class BookController implements HttpRequestHandler {
    @Override
    public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Book接收请求");
    }
}

image-20230422203347934

二、注解形式开发

​ 上面那些混个脸熟即可,主要理解处理过程,平时开发应该没人用罢

(一)配置映射器和适配器

​ SpringMVC 框架为了简化使用,提供了 mvc 命名空间。该空间下提供了 mvc:annotation-driven 元素,用于简化注解方式的映射器、适配器在 spring-mvc.xml 文件中的配置。

​ 不仅可以替代上面两个 bean 类的配置,而且 mvc:annotation-driven 的驱动类还默认加载了多个参数绑定的方法,比如 json 转换解析器就默认加载。

​ 引入 mvc 命名空间之后,在配置文件中配置注解的适配器和映射器,并配置自动扫描包。

xmlns:mvc="http://www.springframework.org/schema/mvc"

http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd"

    <!--配置注解形式的适配器和映射器-->
    <mvc:annotation-driven/>

    <!--自动扫描包-->
    <context:component-scan base-package="com.ls"></context:component-scan>

​ 我是新建了一个 mvc 的配置文件,头文件是差不多的,不过不要忘了如果修改的话在 web.xml 里面把读取配置文件的信息改了,md就因为忘了改耽误半小时,,,,,,

image-20230424193804168

<!--配置注解形式的适配器和映射器-->
<mvc:annotation-driven/>

<!--自动扫描包-->
<context:component-scan base-package="com.ls"></context:component-scan>


<!-- 配置视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <property name="suffix" value=".jsp"/>
</bean>

(二)编写 Handler

​ 注解@Controller 标记的类,Spring 容器自动加载该 Bean 类并进行管理。对于该 Bean 中的使用注解 @RequestMapping 修饰的方法会进行自动映射。映射的 url 路径需要在 @RequestMapping 注解中定义。

​ 使用注解方式的映射器就不需要在 xml 中配置 url 和 Handler 之间的映射关系,让应用的配置信息得到极大的简化。

@Data
@Accessors(chain = true)
public class Car {
    private Integer id;
    private String name;
}
//---------------------------------------------------------------------------------
@Controller
@RequestMapping("/car")
public class CarController {
    @RequestMapping("/list.action")
    public ModelAndView list() {
        System.out.println("查询车辆列表");
        ArrayList<Car> cars = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            cars.add(new Car().setId(i+1).setName("宏光"+i));
        }
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("carList");
        modelAndView.addObject("carList",cars);
        return modelAndView;
    }
}

​ 随便来个页面测试

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>CarList</title>
</head>
<body>
    ${carList}
</body>
</html>

image-20230424193014305

​ 使用注解方式编写的 Handler,在项目中开发业务模块时,一个业务模块下的增、删、改、查等相关联的 操作,不用再分散到各个类中,而是集中到一个 Controller 类中来完成。业务变的不再分散,在业务模块中增加新的功能也变的更加灵活与方便。

三、Controller、Service、Mapper和POJO

​ 之前写博客的时候一直混乱搞不清这几个哥们的具体作用,找了一些不错的博主回答:原文链接

(一)Entity层:实体层 数据库在项目中的类

​ Entity层是实体层,也就是所谓的model,也称为pojo层,是数据库在项目中的类,该文件包含实体类的属性和对应属性的set、get方法;

(二)DAO层: 持久层 主要与数据库进行交互

​ DAO层=mapper层,现在用Mybatis逆向工程生成的mapper层,其实就是dao层。DAO层会调用entity层,DAO中会定义实际使用到的方法,比如增删改查。DAO 层的数据源和数据库连接的参数都是在配置文件中进行配置的,配置文件一般在同层的XML文件夹中。数据持久化操作就是指,把数据放到持久化的介质中,同时提供增删改查操作。

(三)Service层:业务层 控制业务

​ Service层主要负责业务模块的逻辑应用设计。先设计放接口的类,再创建实现的类,然后在配置文件中进行配置其实现的关联。service层调用dao层接口,接收dao层返回的数据,完成项目的基本功能设计。

​ 封装Service层的业务逻辑有利于业务逻辑的独立性和重复利用性。

(四)Controller层:控制层 控制业务逻辑

​ Controller层负责具体的业务模块流程的控制,controller层负责前后端交互,接受前端请求,调用service层,接收service层返回的数据,最后返回具体的页面和数据到客户端。
​ Controller层像是一个服务员,他把客人(前端)点的菜(数据、请求的类型等)进行汇总什么口味、咸淡、量的多少,交给厨师长(Service层),厨师长则告诉沾板厨师(Dao 1)、汤料房(Dao 2)、配菜厨师(Dao 3)等(统称Dao层)我需要什么样的半成品,副厨们(Dao层)就负责完成厨师长(Service)交代的任务。

posted @ 2023-04-24 19:39  Purearc  阅读(38)  评论(0)    收藏  举报