2021软件创新实验室暑假集训springmvc框架(设计原理简单使用源码探究)(代码片段)

Dreamchaser追梦 Dreamchaser追梦     2022-12-09     747

关键词:

系列文章目录

注:因为集训还没结束,没有统计所有人的博文,所以以上目录并不完整。理论上20级有Java篇10篇,应用篇7篇;19级各赛道各四篇(每次上课都会有一篇博文作总结)

前言

写本文的原因主要是为了实验室暑假集训备课所写,但是本着要么就不写,要写就写好的原则,同时也是为了让我复习技术,我就从开始的模式背景开始讲起,到SpringMVC的使用,再到SpringMVC的源码原理探究。也算自己对于SpringMVC框架的小总结吧。

一、MVC模式的发展

1.Model1

对于浏览器上丰富多彩的网页,我们是如何获取到的呢?直观的去想,我们发送给服务器一个http请求,服务器收到后返回相应的网页,可是我们希望网页上的数据根据我们的请求而变化,但是原先静态网页无法满足这个需求,因为它已经把前端代码和数据固定死了,而我们希望里面的数据可以根据请求的不同而不同。解决方案也不难想,我们只需把前端代码部分里的数据由Java程序提供即可,而这便是Model1的解决方案。

在早期 Java Web 的开发中,统一把显示层、控制层、数据层的操作全部交给 JSP 或者 JavaBean 来进行处理,我们称之为 Model1

在这里插入图片描述

2.Model2

但是model1存在一个很大的问题——代码高度耦合。JSP肩负着控制,视图渲染,数据查询处理等多项职责,同时html代码也和Java代码严重耦合在一起,这为日后项目的维护和拓展带来了极大的困难。

我们希望有一种模式可以摆脱这种困扰,于是有人提出了MVC模式,所谓MVC,其实是一种利用分层来解耦合的思想,这种利用分层/分模块解决耦合问题的方法在计算机领域颇为普遍。

那什么是MVC呢,其实它就是将Model1模式中担负了数据渲染,控制,数据分散开来,形成三层——控制层(Controller)、数据层(Model)、视图层(View)
在这里插入图片描述

  • V即View视图,是指用户看到并与之交互的界面。比如由html元素组成的网页界面,或者软件的客户端界面。MVC的好处之一在于它能为应用程序处理很多不同的视图。在视图中其实没有真正的处理发生,它只是作为一种输出数据并允许用户操作的方式。
  • M即model模型是指模型表示业务规则。在MVC的三个部件中,模型拥有最多的处理任务。被模型返回的数据是中立的,模型与数据格式无关,这样一个模型能为多个视图提供数据,由于应用于模型的代码只需写一次就可以被多个视图重用,所以减少了代码的重复性。
  • C即controller控制器是指控制器接受用户的输入并调用模型和视图去完成用户的需求,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。

具体到JavaEE项目中就是下图所示。
在这里插入图片描述

3.SpringMVC中MVC

和MVC模式类似,不过SpringMVC将model层进行了细分,分为Service层(业务层)和Dao层(数据库层,又称Mapper层)。这样细分也是为了解耦合的需要,在日常开发中我们有必要将业务层的代码抽离出来。
在这里插入图片描述

4.更多设计模式——DDD领域驱动设计思想 ?

其实MVC发展远没有结束,随着业务的日渐庞大,像传统的MVC模式已经不能满足业务的需要,单方面的纵向切分在日渐庞大的业务中显得力不从心。DDD领域驱动设计便是一种解决这个问题的设计思想。

从DDD思想延伸出很多实地解决方案,比如当下热门的分布式微服务思想。

其实不管是什么设计思想,

如果你能深入理解职责、封装。并随着业务的迭代,不断的重构你的代码,那么你不需要什么DDD,或者其他方法论。

该内容与本文无关,只做简单的延伸,具体可以自行百度搜索相关内容,
阅读材料推荐:可落地的DDD的(2)-为什么说MVC工程架构已经过时

二、SpringMVC的简单使用

理解了什么是MVC后,我们开始开发一个简单Demo项目

注:下面的demo应用摘自第一个Spring MVC程序,我根据示例做出了点修改

1.利用配置开发第一个SpringMVC项目

①创建 Web 应用并引入 JAR 包

在idea中创建Java EE项目
在这里插入图片描述

在这里插入图片描述
命名可以随意。

创建完成后在pom.xml写入配置,导入相关jar包

<?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>com.dreamchaser</groupId>
    <artifactId>demo-springmvc</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>demo-springmvc</name>
    <packaging>war</packaging>

    <dependencies>
        <!--测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <!--日志-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.21</version>
        </dependency>
        <!--J2EE-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <!--mysql驱动包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.35</version>
        </dependency>
        <!--springframework-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.github.stefanbirkner</groupId>
            <artifactId>system-rules</artifactId>
            <version>1.16.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.9</version>
        </dependency>
        <!--其他需要的包-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.4</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
    </dependencies>

</project>

②Spring MVC 配置

在 web.xml 中配置 Servlet,创建 Spring MVC 的配置文件。

Spring MVC 是基于 Servlet 的,DispatcherServlet 是整个 Spring MVC 框架的核心,主要负责截获请求并将其分派给相应的处理器处理。所以配置 Spring MVC,首先要定义 DispatcherServlet。跟所有 Servlet 一样,用户必须在 web.xml 中进行配置。

1)定义DispatcherServlet

在开发 Spring MVC 应用时需要在 web.xml 中部署 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">
    <display-name>springMVC</display-name>
    <!-- 部署 DispatcherServlet -->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 表示容器再启动时立即加载servlet -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!-- 处理所有URL -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

Spring MVC 初始化时将在应用程序的 WEB-INF 目录下查找配置文件,该配置文件的命名规则是“servletName-servlet.xml”,例如 springmvc-servlet.xml。

也可以将 Spring MVC 的配置文件存放在应用程序目录中的任何地方,但需要使用 servlet 的 init-param 元素加载配置文件,通过 contextConfigLocation 参数来指定 Spring MVC 配置文件的位置,示例代码如下。

<!-- 部署 DispatcherServlet -->
<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-servlet.xml</param-value>
    </init-param>
    <!-- 表示容器再启动时立即加载servlet -->
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

此处使用 Spring 资源路径的方式进行指定,即 classpath:springmvc-servlet.xml。

上述代码配置了一个名为“springmvc”的 Servlet。该 Servlet 是 DispatcherServlet 类型,它就是 Spring MVC 的入口,并通过 1 配置标记容器在启动时就加载此 DispatcherServlet,即自动启动。然后通过 servlet-mapping 映射到“/”,即 DispatcherServlet 需要截获并处理该项目的所有 URL 请求。

2)创建Spring MVC配置文件

在 WEB-INF 目录下创建 springmvc-servlet.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">
    <!-- LoginController控制器类,映射到"/login" -->
    <bean name="/login"
          class="net.biancheng.controller.LoginController"/>
    <!-- LoginController控制器类,映射到"/register" -->
    <bean name="/register"
          class="net.biancheng.controller.RegisterController"/>
</beans>

③创建 Controller(处理请求的控制器)

在 项目目录下创建controller 包,并在该包中创建 RegisterController 和 LoginController 两个传统风格的控制器类(实现 Controller 接口),分别处理首页中“注册”和“登录”超链接的请求。

LoginController 的具体代码如下:

public class LoginController implements Controller 
    @Override
    public ModelAndView handleRequest(HttpServletRequest arg0,
                                      HttpServletResponse arg1) throws Exception 
        return new ModelAndView("/WEB-INF/jsp/register.jsp");
    

RegisterController 的具体代码如下:

public class RegisterController implements Controller 
    @Override
    public ModelAndView handleRequest(HttpServletRequest arg0,
                                      HttpServletResponse arg1) throws Exception 
        return new ModelAndView("/WEB-INF/jsp/login.jsp");
    

④创建 View

这里采用 JSP 作为视图的模板引擎

index.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    未注册的用户,请
    <a href="$pageContext.request.contextPath /register"> 注册</a><br /> 已注册的用户,去
    <a href="$pageContext.request.contextPath /login"> 登录</a></body>
</html>

在 WEB-INF 下创建 jsp 文件夹,将 login.jsp 和 register.jsp 放到 jsp 文件夹下。login.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    登录页面!
</body>
</html>

register.jsp 代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
<body>
    注册页面!
</body>
</html>
</head>

⑤部署运行

配置tomcat
在这里插入图片描述
点击运行
在这里插入图片描述

部署成功!
在这里插入图片描述
在这里插入图片描述

以上便完成了最基本的SpringMVC项目搭建

这里我们可以看到,springmvc-servlet.xml的作用就是写各种配置以及告诉SpringMVC我们业务类的位置,在上面的项目中我们用配置的方式告诉了springmvc我们把Controller放在了哪里以及对应的请求映射。

但是如果每次都这么配,不免有些麻烦。所以一般情况我们都会用注解的方式去实现。

2.利用注解开发

根据我自己的经验,注解的使用是不难的,一般看看示例代码就会了。但是很多时候我们只是看注解概念,这时候你大概率会云里雾里的,一用起来还是不会。

所以我这里以代码的形式去讲解这些常用注解的实际使用。相信大家很快就能上手使用,如果不理解的,大家可以边看边打代码,然后去动手测试一下,相信你很快就能掌握的。

①一般的Controller


/**
 * 一般controller的演示类
 * @author Dreamchaser
 */
//标识其为一个Controller类
@Controller
//在controller类前加@RequestMapping注解,可以为所有方法映射路径加个前缀,比如/getRequest01,它实际的访问路径为/prefix/getRequest01
@RequestMapping("/prefix")
public class TestController 
    //@RequestMapping请求映射,value值是映射路径,method标识请求的方式,如get,post,delete,put等(这里是一个枚举类型)。
    // springmvc会根据value中的路径匹配,如果访问路径和value一致则会执行该方法,
    @RequestMapping(value = "/getRequest01",method = RequestMethod.GET )
    //返回类型可以有以下几种,Object,Strin

2021软件创新实验室暑假集训总结篇

系列文章目录20级Java篇【2021软件创新实验室暑假集训】计算机的起源与大致原理【2021软件创新实验室暑假集训】Java基础(一)【2021软件创新实验室暑假集训】Java基础(二)【2021软件创新实验室暑假集训】Java基... 查看详情

2021软件创新实验室暑假集训总结篇

系列文章目录20级Java篇【2021软件创新实验室暑假集训】计算机的起源与大致原理【2021软件创新实验室暑假集训】Java基础(一)【2021软件创新实验室暑假集训】Java基础(二)【2021软件创新实验室暑假集训】Java基... 查看详情

2021软件创新实验室暑假集训springboot框架(代码片段)

系列文章目录20级Java篇【2021软件创新实验室暑假集训】计算机的起源与大致原理【2021软件创新实验室暑假集训】Java基础(一)【2021软件创新实验室暑假集训】Java基础(二)【2021软件创新实验室暑假集训】Java基... 查看详情

2021软件创新实验室暑假集训springboot框架(代码片段)

系列文章目录20级Java篇【2021软件创新实验室暑假集训】计算机的起源与大致原理【2021软件创新实验室暑假集训】Java基础(一)【2021软件创新实验室暑假集训】Java基础(二)应用篇【2021软件创新实验室暑假集训... 查看详情

2021软件创新实验室暑假集训jdbc(原理使用以及实现简单的数据库连接池)(代码片段)

系列文章目录20级Java篇【2021软件创新实验室暑假集训】计算机的起源与大致原理【2021软件创新实验室暑假集训】Java基础(一)【2021软件创新实验室暑假集训】Java基础(二)【2021软件创新实验室暑假集训】Java基... 查看详情

2021软件创新实验室暑假集训jdbc(原理使用以及实现简单的数据库连接池)(代码片段)

系列文章目录20级Java篇【2021软件创新实验室暑假集训】计算机的起源与大致原理【2021软件创新实验室暑假集训】Java基础(一)【2021软件创新实验室暑假集训】Java基础(二)应用篇【2021软件创新实验室暑假集训... 查看详情

软件创新实验室2021年暑假集训使用typora+gitee搭建图床(代码片段)

使用Typora+gitee搭建图床前言咱们在用typora写博客的时候总会遇到一个问题,那就是图片问题。如果你的typora是没有设置过图床的,那么和设置过图床的typora判若两人。没有设置过的显示路径是本地磁盘的绝对路径,... 查看详情

软件创新实验室2021年寒假集训java技术培训——java前置知识学习

系列文章目录【软件创新实验室2021年寒假集训】汇总篇20级Java培训第一天:【软件创新实验室2021年寒假集训】Java技术培训——Java前置知识学习第二天:Java基础(一)第三天:【软件创新实验室2021年寒假集... 查看详情

软件创新实验室2021年寒假集训java后端开发漫谈及感悟分享

系列文章目录【软件创新实验室2021年寒假集训】汇总篇20级Java培训第一天:【软件创新实验室2021年寒假集训】Java技术培训——Java前置知识学习第二天:Java基础(一)第三天:【软件创新实验室2021年寒假集... 查看详情

软件创新实验室2021年寒假集训java技术培训——java基础(代码片段)

系列文章目录【软件创新实验室2021年寒假集训】汇总篇20级Java培训第一天:【软件创新实验室2021年寒假集训】Java技术培训——Java前置知识学习第二天:Java基础(一)第三天:【软件创新实验室2021年寒假集... 查看详情

2018.08.05暑假集训感受

今天是星期日,实验室人很少,我可以放开心情写写日记了~最近可能是有点厌学吧,到了晚上就没想法继续读下去了,感觉会很烦躁可能是因为学习新知识,但是却因为完全没看懂就觉得很烦吧,我还是很喜欢学习的,但还是... 查看详情

uestc2021暑假前集训(splay树)

      关于splay的教程可以在哔站上查询我校前辈算法讲堂然后代码对标的是两篇博客(实际上是一种姿势,因为这种代码姿势非常的优美)Splay入门解析【保证让你看不懂(滑稽)】-小蒟蒻yyb-博客园(cnblogs.... 查看详情

2021年swpuacm暑假集训day5单调栈算法(代码片段)

什么是单调栈顾名思义,单调栈即满足单调性的栈结构。这里的单调递增或递减是指的从栈顶到栈底单调递增或递减。既然是栈,就满足后进先出的特点。与之相对应的是单调队列。单调栈的实现插入在当前元素插入栈... 查看详情

2021年暑假acm集训队模拟赛第4场——题解(代码片段)

目录A山峦叠嶂B重叠正方形C一群X星人DX星群岛(MST,最小生成树模板题)EX星人的飞行设备(复杂一点的DP)FX星人的救援G最长回文子串HDNA序列拼接I防水板砖(搜索,DFS待补)J黑白树(比较复... 查看详情

[暑假集训--数论]poj2657comfort

DescriptionAgame-boardconsistsofNfieldsplacedaroundacircle.Fieldsaresuccessivelynumberedfrom1toNclockwise.Insomefieldstheremaybeobstacles.Playerstartsonafieldmarkedwithnumber1.Hisgoalistoreachagivenfi 查看详情

[暑假集训--数论]poj1365primeland

EverybodyinthePrimeLandisusingaprimebasenumbersystem.Inthissystem,eachpositiveintegerxisrepresentedasfollows:Let{pi}i=0,1,2,...denotetheincreasingsequenceofallprimenumbers.Weknowthatx>1canbereprese 查看详情

zzuacm2015暑假集训round01

A.EncodingProblemDescriptionGivenastringcontainingonly‘A’-‘Z’,wecouldencodeitusingthefollowingmethod:Eachsub-stringcontainingksamecharactersshouldbeencodedto“kX”where“X”istheonlycharacterinthissub-str 查看详情

[暑假集训--数位dp]cf55dbeautifulnumbers

Volodyaisanoddboyandhistasteisstrangeaswell.Itseemstohimthatapositiveintegernumberisbeautifulifandonlyifitisdivisiblebyeachofitsnonzerodigits.Wewillnotarguewiththisandjustcountthequantityofbeautifulnu 查看详情