您的位置:首页 > 编程语言 > Java开发

SpringMVC学习指南(1)

2020-10-24 17:48 921 查看

文章目录

  • 二、HelloWorld
  • 2.2 Helloworld
  • 2.2.3 测试
  • 2.3 程序分析
  • 三、拓展
  • 四、总结
  • 前言

    阅读提示:

        本博客会手把手教你创建一个SpringMVC的HelloWorld,没有过多的原理解析,适用于新手上路,大佬请略过。
        此文从IDEA创建项目到整合Tomcat以及Maven的设置都有详细的截图。😉

    谨以此文,纪念1024,也祭奠为了SpringMVC离我而去的头发😒😒😒😒

    一、概述

    1.1. SpringMVC简介:

    • springmvc是spring框架的一个模块,支持spring的所有特性,ioc和aop等,springmvc和spring无需通过中间整合层进行整合。
    • SpringMVC == Spring的web模块
    • Spring 为展现层提供的基于 MVC 设计理念的优秀的 Web 框架,是目前最主流的 MVC 框架之一。
    • Spring MVC 通过一套 MVC 注解,让 POJO 成为处理请求的控制器,而无须实现任何接口。
    • SpringMVC的MVC架构:与JavaWeb的MVC架构多了一个前端控制器,即:DispatcherServlet。
    • JavaWeb的MVC架构:

    1.2. MVC模式

    • Model(模型):分为两种

        数据模型,提供要展示的数据:Value Object(数据Dao)
      1. 业务模型:服务层(行为Service),提供数据和业务。
    • View:负责进行模型的展示,即:用户看到的界面

    • Controller: 俗称“调度员”,接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。

    1.3. Dao封装

    (1)Dao介绍

    • DAO = DataBase Access Object。数据库访问对象

    • 作用:

      数据库访问对象在开发时提供针对某张表的操作细节[CRUD]
  • 优点:

      在管理系统开发时,通过数据库访问对象可以避免反复的SQL命令书写
    1. 在管理系统开发时,通过数据库访问对象可以避免反复的JDBC开发步骤书写
  • DAO类:简而言之就是操作数据库的类。

  • (2)Dao类开发规则

    • 一个DA0类封装的是一张表操作细节

    • DAO类命名规则:

      表名+Dao: Emp表—>EmpDao;
    • Dept表—>DeptDao
  • DAO类所在包命名规则:域名.dao, 比如:nuc.edu.dao

  • 1.4. 实体类

    • 一个实体类用于描述一张表的结构

    • 实体类的类名应该与关联的数据库的表名保持一致,但是可以忽略大小写,应当遵守java命名规范。

    • 实体类中的属性应该与关联的表文件的字段保持一致。

    • 实体类的一个实例对象用于在内存中存储对应的表文件的一个数据行。

    二、HelloWorld

    开发环境:
    JDK:1.8
    Tomcat:9.0
    Maven:3.6.3
    IDEA:IntelliJ IDEA 2019.3.3

    2.1. 创建工程

    使用Maven创建工程

    2.1.1 创建父项目

    【一】 使用maven创建一个空项目,删除src文件夹。使其成为父项目。

    使用maven创建工程,这里先不使用模板,创建一个空的maven项目,作为父项目。

    开启自动导入:

    在建好的父工程的pom中导入依赖。

    <!--SpringMVC的依赖,它会将所有spring的依赖也都加进来-->
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.6.RELEASE</version>
    </dependency>
    
    <!--Servlet的依赖-->
    <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
    </dependency>
    <!--jsp的依赖-->
    <dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl-api</artifactId>
    <version>1.2</version>
    </dependency>
    <!--java单元测试模块的依赖-->
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    </dependency>

    可能出现的问题:

    • 依赖导入缓慢

    分析:

    • 有可能是IDEA使用了自带的Maven,我们打开设置看一下,如果是就换成我们自己安装的Maven。

    点击File,找到setting

    在setting中找到如下设置

    果然,IDEA使用的是自己的Maven。因为它会优先使用自己的Maven,(嘿,有点坑啊),不过,么得关系,改一下即可。

    修改之后:

    修改完之后可能会报以下错误。
    因为我们改了Maven配置,改变了Maven仓库的位置。

    不要慌,解决方案如下:clean一下就好

    (可选)删除父工程下的src文件夹,不删也关系,只是没用而已。

    2.1.2 创建Model

    【二】使用Model开发,新建一个Model

    使用模板开发,注意jdk版本,使用webapp这个模板。

    给Model起个好听的名字。当然是HelloWorld了。

    再次确认该Model使用的Maven。

    Model创建成功,如果还报错,继续使用Maven插件进行清理。清理之后,就会成功

    创建java文件夹和resource文件夹,使项目结果完整

    完整的项目结构

    2.1.3 添加Tomcat

    选择发布方式,我们选择war exploded。
    至于这两个的区别我们后面会说。

    Apply即可

    2.2 Helloworld

    2.2.1 导入依赖

    (1) spring核心容器(五个)

    1. commons-logging
    2. spring-beans
    3. spring-context
    4. spring-core
    5. spring-expression

    (2)支持注解的包

    1. spring-aop

    (3)web模块

    1. spring-web
    2. spring-mvc

    (4)偷懒

    • 为了简化开发,我们直接导入SpringMVC的依赖,它会自动导入Spring的依赖包。
    • 再导入Servlet、jsp、junit的依赖。
    <dependencies>
    
    <!--SpringMVC的依赖,它会将所有spring的依赖也都加进来-->
    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.6.RELEASE</version>
    </dependency>
    
    <!--Servlet的依赖-->
    <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
    </dependency>
    <!--jsp的依赖-->
    <dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl-api</artifactId>
    <version>1.2</version>
    </dependency>
    <!--java单元测试模块的依赖-->
    <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    </dependency>
    </dependencies>

    2.2.2 写配置

    web的配置

    web.xml配置文件

    • 配置 DispatcherServlet。
    • 配置SpringMVC的前端控制器,指定SpringMVC的配置文件。
    <?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>springDispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--    Servlet的初始化参数
    contextConfigLocation:指定SpringMVC配置文件位置
    -->
    <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <!--    Servlet启动加载,Servlet原本是第一次访问时创建对象
    load-on-startup:服务器在启动时就创建Servlet,值越小,越先创建对象
    -->
    <load-on-startup>1</load-on-startup>
    </servlet>
    
    <!--  处理所有请求,-->
    <servlet-mapping>
    <servlet-name>springDispatcherServlet</servlet-name>
    <!--  "/" 和 "/*" 都会拦截所有请求。但 "/*" 拦截范围更大,可以拦截到jsp页面,开发中不能拦截页面-->
    <url-pattern>/</url-pattern>
    </servlet-mapping>
    </web-app>

    框架自身的配置

    • 开启基于注解的开发,即:开启包扫描
    • 配置一个视图解析器。暂时用来页面路径拼串。
    <?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 https://www.springframework.org/schema/context/spring-context.xsd">
    
    <!--开启包扫描-->
    <context:component-scan base-package="nuc"></context:component-scan>
    
    <!--    配置一个视图解析器:目前可以帮我们拼接页面地址-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/pages/"></property>
    <property name="suffix" value=".jsp"></property>
    </bean>
    </beans>

    2.2.3 测试

    /**
    *  1. 告诉springMVC这是一个处理器,可以出来请求
    *      @Controller:标识那个组件是控制器
    */
    @Controller
    public class MyController {
    /**
    *
    *  “/”:表示从当前项目下开始:处理当前项目下的hello请求
    */
    @RequestMapping("/hello")
    public String myFirstRequest()
    {
    System.out.println("请求正在处理……");
    //视图解析器自动拼串,拿到它的前后缀。
    //转发到 /WEB-INF/pages/success.jsp 页面
    return "success";
    }
    }

    2.3 程序分析

    (1)程序运行流程

    1. 客户端点击链接: http://localhost:8080/SpringMVC_02_HelloWorld/hello

    2. 来到Tomcat服务器

    3. SpringMVC的前端控制器收到所有请求

    4. 前端控制器会查看“请求地址”和@RequestMapping标注的哪个方法匹配。

        一个方法设置一个请求,即使在不同类中也不能一样。会报错
    5. 前端控制器找到目标类目标方法,直接利用反射执行目标方法。

    6. 方法执行完之后会有一个返回值,SpringMVC认为这个返回值就是要去的页面地址。

    7. 拿到方法返回值之后,视图解析器会完成拼串,拿到完整的页面地址。

    8. 转发到这个页面地址。

    (2)注解@RequestMapping

    • 作用:告诉SpringMVC,这个方法用来处理什么请求。
    • “/”是可以省略的,默认也是从当前项目开始。

    (3)在web.xml文件中指定SpringMVC的配置文件

    • 如果不指定配置文件,即:不使用

      <init-param>
      标签指定配置文件。

      SpringMVC会去找一个默认文件,路径在“/WEB-INF/xxx-servlet.xml”
  • “xxx”名为Servlet标签中设置的名。

  • 找不到就报io异常,如下:

  • java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/xxx-servlet.xml

    (4)url-pattern

    • “/”:拦截所有请求,但不拦截jsp页面

    • “/*”:拦截所有请求,包括jsp页面的请求

    • 如果使用“/*”,运行代码,就会包404错误,因为jsp页面没找到。报错如下:

    14-Oct-2020 20:51:13.273 警告 [http-nio-8080-exec-4] org.springframework.web.servlet.DispatcherServlet.noHandlerFound No mapping for GET /SpringMVC_02_HelloWorld/WEB-INF/pages/success.jsp

    注意:使用“/”会使静态资源(如:HTML页面)报错

    【原因】

    • Tomcat的web.xml中有一个DefaultServlet是url-pattern=/

      所有项目的小web.xml都是继承于服务器的大web.xml的。

    • Tomcat中的DefaultServlet是处理Tomcat中的静态资源的。

      静态资源:除了jsp和Servlet都是静态资源。例如:.html就是静态资源。

    • Tomcat就会在服务器下找到这个静态资源,并把它返回。

    • 但是我们在前端控制器中也使用了“url-pattern=/”,就相当于禁用了Tomcat的DefaultServlet。

    • 然后静态资源就会来到DispatcherServlet(前端控制器)中找那个方法的 @RequestMapping是这个静态页面的路径。(当然没有呀,所以会报错)

  • 我们在前端控制器中写“/”也是为了迎合以后的Rest风格的URL地址。

  • 三、拓展

    复习下转发和重定向的知识

    原生Servlet的Web系统中资源跳转

    (1)跳转的两种方式:

    1. 转发:forward
    2. 重定向:redirect 302

    (2)转发和重定向代码怎么完成?

    转发:

    RequestDispatcher dispatcher = request.getRequestDispatcher("/testB");
    dispatcher.forward(request,response);

    重定向:

    response.sendRedirect(request.getContextPath()+"/testB");

    (3)转发和重定向的区别?

    • 相同点:都可以完成资源的跳转

    • 不同:

      转发是request对象触发的

    • 重定向是response对象触发的

    • 转发是一次请求,浏览器地址栏上的地址不会发生变化【/testA】

    • 重定向是两次请求,浏览器地址栏上的地址发生变化。【/testA /testB】

    • 重定向需要加项目名。

    • 转发是在本项目内部完成资源跳转

    • 重定向可以完成跨webapp跳转资源。

    (4)跳转的下一个资源可以是什么?

    • 跳转的下一个资源可以是web浏览器中任何一个资源,可以是Servlet、HTML、jsp等。

    (5)什么时候使用转发,什么时候使用重定向?(大部分情况下都使用重定向)

    • 若想完成跨webapp跳转,必须使用重定向。

    • 若在上一个资源中向request范围中存储了数据,希望在下一个资源中从request范围中取出来,必须使用转发。

    • 重定向可以解决浏览器的刷新问题。

    (6)重定向原理?

    response.sendRedirect("/jd/login");

       程序执行到以上代码,将请求路径/jd/login反馈给浏览器,浏览器又自动的向web浏览器发送了一次请求/jd/login。浏览器地址栏上最终显示的是:/jd/login

    (7)理解重定向与转发

    • 转发:A向B借钱,B没有,B对A说“稍等,我给您想办法”。后B有去找C借了钱,然后B把这钱有借给A。 A只求了一次人。
    • 重定向:A向B借钱,B没有,B对A说“您去找C吧”,A向C借到了钱。

       在浏览器上点击一个超链接,到最终页面显示出来,是一次请求。这句话并不严禁,在不考虑重定向时这句话才正确。

    (8)重定向可以解决页面刷新问题,刷新是刷新最后一个页面。

    四、总结

        相信读完本文的读者,都是多多少少了解过使用原生Servlet开发web项目的步骤的,那是相当的繁琐呀。使用SpringMVC之后会非常的便捷。
        有人会说,都有SpringMVC框架了,可以非常简便的开发了,为什么要去了解Servlet这种low到掉牙的技术呢。要知道SpringMVC的地层实现就是使用的Servlet,它只是给我们将Servlet包装了一下,方便我们开发。如果懂得Servlet的话,学习SpringMVC就是事半功倍。

    害~      本来想一篇博客就写完SpringMVC的大部分内容的,没想到只完成了Helloworld。但是,读到此文的读者,请移步到我的主页,先关注一波😊😊,我会尽快整理完SpringMVC后续的知识并发布博客。

    时空穿梭:博主首页

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: