初识SpringMVC

o

SpringMVC是Spring的一个后续产品,是Spring的一个子项目

注:三层架构分为表述层(或表示层)、业务逻辑层、数据访问层,表述层表示前台页面和后台servlet
我们直接新建一个maven工程,然后添加框架支持,得到一个web工程

创建一个springmvc模块,注意在将java工程变成web工程时,下面的路径信息是否是将web.xml放在\src\main\webapp\WEB-INF\下。

还有记得将打包方式设置成war包形式(其实不用向上面手动添加支持,也可以在如下写明打包方式,则会在右下角弹出添加框架支持的提醒,点击即可,然后再去确认一下路径)

准备工作(添加依赖,配置和创建相关xml配置文件

添加如下依赖

html 复制代码
<dependencies>
        <!-- SpringMVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.1</version>
        </dependency>
        <!-- 日志 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
        <!-- ServletAPI -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <!-- Spring5和Thymeleaf整合包 -->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
            <version>3.0.12.RELEASE</version>
        </dependency>
    </dependencies>

配置web.xml

①默认配置方式:如下此配置作用下,SpringMVC的配置文件默认位于WEB-INF下,默认名称为<servlet-name>-servlet.xml,例如,以下配置所对应SpringMVC的配置文件位于WEB-INF下,文件名为springMVCservlet.xml

html 复制代码
<?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">
    <!-- 配置SpringMVC的前端控制器DispatcherServlet,对浏览器发送的请求统一进行处理 -->
    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <!--
            设置springMVC的核心控制器所能处理的请求的请求路径
            /所匹配的请求可以是/login或.html或.js或.css方式的请求路径
            /:匹配浏览器向服务器发送的所有请求(不包括.jsp)
            /*:可以匹配所有请求路径的请求(包括.jsp)
           -->
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

<servlet>标签中,<servlet-name>是用于给servlet命名的。这个名字可以在多个地方使用。例如:

  1. 在servlet的配置中,可以使用servlet的名字来标识servlet。例如,在web.xml文件中,可以使用<servlet-name>来命名servlet,然后在其他地方使用这个名字来引用这个servlet。
  2. 在Java代码中,可以通过servlet名字来获取servlet的实例。例如,可以使用ServletContext.getServlet()方法,传入servlet名字,来获取servlet的实例。

至于<servlet-name><servlet-mapping>中的名字是否需要一致,实际上它们并不需要一致。这两个名字是分别用于标识servlet的名称和映射规则的,它们之间没有直接的关联。但是,为了方便理解和维护代码,建议在这两个地方使用相同的名字。

②扩展配置方式

可通过init-param标签设置SpringMVC配置文件的位置和名称,通过load-on-startup标签设置

SpringMVC前端控制器DispatcherServlet的初始化时间创建springmvc.xml配置文件

html 复制代码
 <!-- 配置SpringMVC的前端控制器DispatcherServlet,对浏览器发送的请求统一进行处理 -->
    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 通过初始化参数指定SpringMVC配置文件的位置和名称 -->
        <init-param>
            <!-- contextConfigLocation为固定值 -->
            <param-name>contextConfigLocation</param-name>
            <!-- 使用classpath:表示从类路径查找配置文件,例如maven工程中的
            src/main/resources -->
            <param-value>classpath:springMVC.xml</param-value>
        </init-param>
        <!--
        作为框架的核心组件,在启动过程中有大量的初始化操作要做
        而这些操作放在第一次请求时才执行会严重影响访问速度
        因此需要通过此标签将启动控制DispatcherServlet的初始化时间提前到服务器启动时
        -->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springMVC</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

(注:/不能匹配.jsp请求路径的请求因此就可以避免在访问jsp页面时,该请求被DispatcherServlet处理,从而找不到相应的页面,/*则能够匹配所有请求,例如在使用过滤器时,若需要对所有请求进行过滤,就需要使用/*的写法)

创建请求控制器

创建SpringMVC配置文件

html 复制代码
 <!--扫描控制层组件-->
 <context:component-scan base-package="personal.december.springmvc.controller"></context:component-scan>
    <!-- 配置Thymeleaf视图解析器 -->
    <bean id="viewResolver"
          class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
        <property name="order" value="1"/>
        <property name="characterEncoding" value="UTF-8"/>
        <property name="templateEngine">
            <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
                <property name="templateResolver">
                    <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
                        <!-- 视图前缀 -->
                        <property name="prefix" value="/WEB-INF/templates/"/>
                        <!-- 视图后缀 -->
                        <property name="suffix" value=".html"/>
                        <property name="templateMode" value="HTML5"/>
                        <property name="characterEncoding" value="UTF-8" />
                    </bean>
                </property>
            </bean>
        </property>
    </bean>

测试

java 复制代码
// @RequestMapping注解:处理请求和控制器方法之间的映射关系
// @RequestMapping注解的value属性可以通过请求地址匹配请求,/表示的当前工程的上下文路径
// localhost:8080/springMVC/
@Controller
public class HelloController {
    @RequestMapping("/")
    public String protal(){
        //将逻辑视图返回,变成物理视图,即加上前缀和后缀
        return "index";
    }
}

结果如下,浏览器跳转到index.html视图(即物理地址如上图路径上下文下/WEB-INF/templates/index.html)

我们可以发现在index.html设置超链接时如下的不同之处

java 复制代码
<a th:href="@{/hello}">测试springmvc</a>
<a href="/hello">测试绝对路径</a>

前者因为thymeleaf会帮我们添加上上下文路径,记得是th:href,其使用对应如下阴影链接

当我鼠标放在第一个链接上时,显示的路径如下

测试绝对路径时显示如下

(总结:浏览器发送请求,若请求地址符合前端控制器的url-pattern,该请求就会被前端控制器DispatcherServlet处理。前端控制器会读取SpringMVC的核心配置文件,通过扫描组件找到控制器,将请求地址和控制器中@RequestMapping注解的value属性值进行匹配,若匹配成功,该注解所标识的控制器方法就是处理请求的方法。处理请求的方法需要返回一个字符串类型的视图名称,该视图名称会被视图解析器解析,加上前缀和后缀组成视图的路径,通过Thymeleaf对视图进行渲染,最终转发到视图所对应页面)

@RequestMapping

作用就是将请求和处理请求的控制器方法关联起来,建立映射关系。

SpringMVC 接收到指定的请求,就会来找到在映射关系中对应的控制器方法来处理这个请求。

@RequestMapping注解的位置

@RequestMapping标识一个类:设置映射请求的请求路径的初始信息

点击链接会跳转上下文下/templates/hello.html的内容

@RequestMapping标识一个方法:设置映射请求请求路径的具体信息

例如在下面这种情况下,左边匹配的路径为上下文/hello,而右边在类上也用注解相关联起路径,所以想要访问原来的内容则要匹配路径上下文下/first/hello,相当于要先匹配类的路径

点击链接出现报错

因为正确的路径和之前不一样了,还要先匹配类上设置的/first

@RequestMapping注解的value属性(属性必须设置,至少通过请求地址匹配请求映射)

@RequestMapping注解的value属性通过请求的请求地址匹配请求映射

其value属性是一个字符串类型的数组,表示该请求映射能够匹配多个请求地址所对应的请求

用{}括起来多个访问路径

可以看到下面两图的路径不同但访问页面相同

@RequestMapping注解的method属性

@RequestMapping注解的method属性通过请求的请求方式(get或post)匹配请求映射

该属性是一个RequestMethod类型的数组,表示该请求映射能够匹配多种请求方式的请求

若当前请求的请求地址满足请求映射的value属性,但是请求方式不满足method属性,则浏览器报错405:Request method 'POST' not supported

注:在@RequestMapping的基础上,对于处理指定请求方式的控制器方法,SpringMVC中提供了@RequestMapping的派生注解,如下

处理get请求的映射-->@GetMapping

处理post请求的映射-->@PostMapping

处理put请求的映射-->@PutMapping

处理delete请求的映射-->@DeleteMapping

2、常用的请求方式有get,post,put,delete

但是目前浏览器只支持get和post,若在form表单提交时,为method设置了其他请求方式的字符串(put或delete),则按照默认的请求方式get处理

若要发送put和delete请求,则需要通过spring提供的过滤器HiddenHttpMethodFilter,在

RESTful部分会讲到

@RequestMapping注解的params属性(了解)

@RequestMapping注解的params属性通过请求的请求参数匹配请求映射

该属性是一个字符串类型的数组,可以通过四种表达式设置请求参数和请求映射的匹配关系

"param":要求请求映射所匹配的请求必须携带param请求参数

"!param":要求请求映射所匹配的请求必须不能携带param请求参数

"param=value":要求请求映射所匹配的请求必须携带param请求参数且param=value

"param!=value":要求请求映射所匹配的请求必须携带param请求参数但是param!=value

如下使用

则点击第二个链接则无法跳转到指定页面,因为设置了param属性,要求带有字段username

只有携带username这一请求参数才可以正常访问

(若当前请求满足@RequestMapping注解的value和method属性,但是不满足params属性,此时页面回报错400)

@RequestMapping注解的headers属性(了解)

@RequestMapping注解的headers属性通过请求的请求头信息匹配请求映射

@RequestMapping注解的headers属性是一个字符串类型的数组,可以通过四种表达式设置请求头信息和请求映射的匹配关系

"header":要求请求映射所匹配的请求必须携带header请求头信息

"!header":要求请求映射所匹配的请求必须不能携带header请求头信息

"header=value":要求请求映射所匹配的请求必须携带header请求头信息且header=value

"header!=value":要求请求映射所匹配的请求必须携带header请求头信息且header!=value

如上设置该属性后,要求链接跳转需要请求头,当我复制链接到浏览器地址栏搜索则会报错。因为没有来源

(请求头和请求体的键不区分大小写)

若当前请求满足@RequestMapping注解的value和method属性,但是不满足headers属性,此时页面显示404错误,即资源未找到

SpringMVC支持ant风格的路径

?:表示任意的单个字符(不包括?)问号本身在路径中代表分隔,?后面的内容会被当作请求参数处理

*:表示任意的0个或多个字符(不包括?和/)

**:表示任意层数的任意目录

注意:在使用**时,只能使用/**/xxx的方式

SpringMVC支持路径中的占位符(重点)

原始方式:/deleteUser?id=1

rest方式:/user/delete/1

SpringMVC路径中的占位符常用于RESTful风格中,当请求路径中将某些数据通过路径的方式传输到服务器中,就可以在相应的@RequestMapping注解的value属性中通过占位符{xxx}表示传输的数据,在通过@PathVariable注解,将占位符所表示的数据赋值给控制器方法的形参

java 复制代码
@RequestMapping("/test/rest/{username}/{id}")
    public String testRest(@PathVariable("id") Integer id,@PathVariable("username") String username){
        System.out.println("id="+id+",username="+username);
        return "hello";
    }


SpringMVC获取请求参数

通过ServletAPI获取

将HttpServletRequest作为控制器方法的形参,此时HttpServletRequest类型的参数表示封装了当前请求的请求报文的对象

创建一个表单:

html 复制代码
<form th:action="@{/param/servletAPI}" method="post">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    <input type="submit" value="提交"><br>
</form>
java 复制代码
@Controller
public class TestRequestMappingController {
    @RequestMapping("/param/servletAPI")
    public String test(HttpServletRequest request){
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        System.out.println("username="+username+",password="+password);
        return "hello";
    }
}

通过控制器方法的形参获取请求参数

java 复制代码
 @RequestMapping("/param/servletAPI")
    public String test(String username,String password){
        System.out.println("username="+username+",password="+password);
        return "hello";
    }

通过@RequestParam获取

@RequestParam是将请求参数和控制器方法的形参创建映射关系

java 复制代码
@RequestMapping("/param/servletAPI")
   public String test(@RequestParam("username") String name, String password){
       System.out.println("username="+name+",password="+password);
       return "hello";
   }

@RequestParam注解一共有三个属性:

value:指定为形参赋值的请求参数的参数名

required:设置是否必须传输此请求参数,默认值为true

若设置为true时,则当前请求必须传输value所指定的请求参数,若没有传输该请求参数,且没有设置defaultValue属性,则页面报错400:Required String parameter 'xxx' is not present;

若设置为false,则当前请求不是必须传输value所指定的请求参数,若没有传输,则注解所标识的形参的值为null

defaultValue:不管required属性值为true或false,当value所指定的请求参数没有传输或传输的值为""时,则使用默认值为形参赋值

@RequestHeader

@RequestHeader是将请求头信息和控制器方法的形参创建映射关系

该r注解一共有三个属性:value、required、defaultValue,用法同@RequestParam

@CookieValue

@CookieValue是将cookie数据和控制器方法的形参创建映射关系

该注解一共有三个属性:value、required、defaultValue,用法同@RequestParam

记得先获取一下coockie

通过POJO获取请求参数

创建一个User类

还有toString,get和set方法,注意要有无参构造器

可以在控制器方法的形参位置设置一个实体类类型的形参,此时若浏览器传输的请求参数的参数名和实体类中的属性名一致,那么请求参数就会为此属性赋值

解决获取请求参数的乱码问题

解决获取请求参数的乱码问题,可以使用SpringMVC提供的编码过滤器CharacterEncodingFilter,但是必须在web.xml中进行注册(在servlet标签外面)

html 复制代码
<!--配置springMVC的编码过滤器-->
    <filter>
        <filter-name>CharacterEncodingFilter</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>
        <init-param> <!--设置响应的编码-->
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

SpringMVC中处理编码的过滤器一定要配置到其他过滤器之前,否则无效

域对象共享数据

1\使用ServletAPI向request域对象共享数据

2\使用ModelAndView向request域对象共享数据

java 复制代码
@Controller
public class TestScopeController {
    @RequestMapping("/test/mav")
    public ModelAndView testMav(){
        /**
         * ModelAndView有Model和View的功能
         * Model主要用于向请求域共享数据
         * View主要用于设置视图,实现页面跳转
         */
        ModelAndView modelAndView = new ModelAndView();
        //向请求域共享数据
        modelAndView.addObject("test1","hello,ModelAndView");
        //设置逻辑视图
        modelAndView.setViewName("hello");
        return modelAndView;
    }
}

注意控制器方法一定要将ModelAndView作为方法的返回值

3\使用map向request域对象共享数据

java 复制代码
 @RequestMapping("/test/map")
    public String testMap(Map<String,Object> map){
        map.put("test4","hehe,map");
        return "hello";
    }

4\使用model向request域对象共享数据

java 复制代码
@RequestMapping("/test/model")
    public String testModel(Model model){
        model.addAttribute("test2","haha,Model");
        return "hello";
    }

5\使用ModelMap向request域对象共享数据

java 复制代码
 @RequestMapping("/test/modelmap")
    public String testModelMap(ModelMap modelMap){
        modelMap.addAttribute("test3","eee,ModelMap");
        return "hello";
    }

Model、ModelMap、Map的关系

三种类型的参数其实本质上都是 BindingAwareModelMap 类型的,在底层都是由它创建的。

向session域共享数据,向application域共享数据

java 复制代码
<p th:text="${session.test11}"></p>
<p th:text="${application.test22}"></p>


 @RequestMapping("/session")
    public String testSession(HttpSession httpSession){
        httpSession.setAttribute("test11","session");
        return "hello";
    }

    @RequestMapping("/application")
    public String testApplication(HttpSession httpSession){
        ServletContext servletContext = httpSession.getServletContext();
        servletContext.setAttribute("test22","application");
        return "hello";
    }

SpringMVC的视图

SpringMVC中的视图是View接口,视图的作用渲染数据,将模型Model中的数据展示给用户

SpringMVC视图的种类很多,默认有转发视图和重定向视图

当工程引入jstl的依赖,转发视图会自动转换为JstlView

若使用的视图技术为Thymeleaf,在SpringMVC的配置文件中配置了Thymeleaf的视图解析器,由此视图解析器解析之后所得到的是ThymeleafView

ThymeleafView

当控制器方法中所设置的视图名称没有任何前缀时,此时的视图名称会被SpringMVC配置文件中所配置的视图解析器解析,视图名称拼接视图前缀和视图后缀所得到的最终路径,会通过转发的方式实现跳转,(如下在springmvc配置文件中的前缀和后缀视图的指定,可以知道,

如下逻辑地址为today,在添加前缀和后缀后得到访问的物理地址为上下文路径下/WEB-INF/templates/today.html

转发视图

SpringMVC中默认的转发视图是InternalResourceView

SpringMVC中创建转发视图的情况:

当控制器方法中所设置的视图名称以"forward:"为前缀时,创建InternalResourceView视图,此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析,而是会将前缀"forward:"去掉,剩余部分作为最终路径通过转发的方式实现跳转

java 复制代码
<a th:href="@{/test/view/InternalResourceView}">测试springmvc下的InternalResourceView</a>
java 复制代码
@RequestMapping("/test/view/InternalResourceView")
    public String testInternalResourceView(){
        return "forward:/test/mav";
    }

点击链接后转发结果如下(我们可以发现转发到的路径不是/test/mav,但是显示的界面内容是)

重定向视图

SpringMVC中默认的重定向视图是RedirectView

当控制器方法中所设置的视图名称以"redirect:"为前缀时,创建RedirectView视图,此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析,而是会将前缀"redirect:"去掉,剩余部分作为最终路径通过重定向的方式实现跳转

java 复制代码
<a th:href="@{/test/view/RedirectView}">测试springmvc下的RedirectView</a><br>
java 复制代码
 @RequestMapping("/test/view/RedirectView")
    public String testRedirectView(){
        return "redirect:/test/mav";
    }

点击链接后,我们可以发现转发的路径和上面InternalResourceView不同。

(重定向视图在解析时,会先将redirect:前缀去掉,然后会判断剩余部分是否以/开头,若是则会自动拼接上下文路径)

视图控制器view-controller

当控制器方法中,仅仅用来实现页面跳转,即只需要设置视图名称时,可以将处理器方法使用viewcontroller标签进行表示

即我们可以不用像下图一样,专门写一个控制器来表示首页

而是在springmvc的配置文件中使用下图标签

java 复制代码
<!--
        path:设置处理的请求地址
        view-name:设置请求地址所对应的视图名称
        -->
    <mvc:view-controller path="/" view-name="today"></mvc:view-controller>

(注:

当SpringMVC中设置任何一个view-controller时,其他控制器中的请求映射将全部失效,

此时需要在SpringMVC的核心配置文件中设置开启mvc注解驱动的标签:

<mvc:annotation-driven />

RESTful(REST:Representational State Transfer,表现层资源状态转移。)

RESTful的实现

具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE用来删除资源。

REST 风格提倡 URL 地址使用统一的风格设计,从前到后各个单词使用斜杠分开,不使用问号键值对方式携带请求参数,而是将要发送给服务器的数据作为 URL 地址的一部分,以保证整体风格的一致性。

HiddenHttpMethodFilter

SpringMVC处理ajax请求

@RequestBody

@RequestBody获取json格式的请求参数

@ResponseBody

@ResponseBody响应浏览器json数据

@RestController注解

文件上传和下载

文件下载

文件上传

拦截器

拦截器的配置

拦截器的三个抽象方法

异常处理器

基于配置的异常处理

基于注解的异常处理
注解配置SpringMVC

创建初始化类,代替web.xml

创建SpringConfig配置类,代替spring的配置文件

创建WebConfig配置类,代替SpringMVC的配置文件

相关推荐
爱学java的ptt2 分钟前
mysql的存储引擎
数据库·mysql
小宇的天下10 分钟前
innovus Flip chip 产品设计方法(3)
数据库·windows·microsoft
GalenZhang88835 分钟前
使用 Python SDK 将数据写入飞书多维表格
数据库·python·飞书·多维表格
云和数据.ChenGuang37 分钟前
GaussDB 期末考试题与面试题
数据库·opengauss·gaussdb·数据库期末试题
不屈的铝合金41 分钟前
SQL 语言概述与数据库核心前置配置了解
数据库·sql·mysql·约束·sql 语句分类·字符集配置·校对规则
萧曵 丶41 分钟前
可重复读(Repeatable Read)隔离级别下幻读产生的原因
数据库·sql·mysql
Antoine-zxt1 小时前
MySQL宕机日志迷局破解指南:从前台启动到精准排错
数据库·mysql·adb
松涛和鸣1 小时前
DAY47 FrameBuffer
c语言·数据库·单片机·sqlite·html
阳宗德1 小时前
基于CentOS Linux release 7.1实现了Oracle Database 11g R2 企业版容器化运行
linux·数据库·docker·oracle·centos
Tinachen881 小时前
YonBIP旗舰版本地开发环境搭建教程
java·开发语言·oracle·eclipse·前端框架