SpringMVC @RequestMapping的使用演示和细节 详解

目录

一、@RequestMapping是什么?

[二、@RequestMapping 的使用演示](#二、@RequestMapping 的使用演示)

1.@RequestMapping在方法上的使用:

2.@RequestMapping同时在类和方法上使用:

3.@RequestMapping指定请求参数:

4.@RequestMapping使用Ant风格URL:

[5.@RequestMapping 配合 @PathVariable映射:](#5.@RequestMapping 配合 @PathVariable映射:)

三、@RequestMapping的使用细节

四、@RequestMapping延伸------SpringMVC中,如何通过注解实现POJO类直接作为Controller,而不依赖Servlet或接口?

五、总结


一、@RequestMapping是什么?

(1) @RequestMapping注解 用于将浏览器发来的 HTTP 请求映射到具体的 Controller类 或者 某个方法上

(2) @RequestMapping 定义了请求的 URL 路径、请求使用的 HTTP 方法(GET, POST 等)、请求的参数、请求头等匹配条件。

(3) @RequestMapping 既可以在类级别 使用,定义指定类的所有方法共享的基础路径;也可以在方法级别 使用,定义具体处理请求的路径;还可以同时在类和方法 级别上使用,并且,当同时修饰类和方法时,请求的 url 就是它们的组合------ ++/类请求值/方法请求值++ ,具体应该为------http://IP[域名]:port/WEB工程路径/类请求值/方法请求值


二、@RequestMapping 的使用演示

1.@RequestMapping在方法上的使用:

我们在 "SpringMVC 执行流程分析" 一文中已经演示过 @RequestMapping 在方法上的使用了,具体请见链接文章的 "快速入门" 部分。如下图所示:

2.@RequestMapping同时在类和方法上使用:

我们在 "SpringMVC 执行流程分析" 一文中已经配置过 applicationContext-mvc.xml 和 web.xml。

这里以 "购买商品并提示购买成功" 的小demo进行演示:先来准备一个 Controller 或者说是 Handler,OrderHandler代码如下:

java 复制代码
package com.cyan.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * @author : Cyan_RA9
 * @version : 22.0
 */
@RequestMapping(value = "/order")
@Controller
public class OrderHandler {
    /**
     * 1. method=RequestMethod.POST: 表示请求 purchase 目标方法的请求方式必须是 post
     * 2. SpringMVC 控制器默认支持 GET 和 POST 两种方式,(如果不指定默认就是这两个)
     */
    @RequestMapping(value = "/purchase", method = RequestMethod.POST)
    public String purchase() {
        System.out.println("make a purchase of goods~~~");
        return "purchase_OK";
    }
}

可以看到,OrderHandlerpurchase() 方法上面都用了 @RequestMapping 进行修饰,如果想访问 purcahse方法,正确的 URL 就应该是 **http://localhost:8080/SpringMVC/order/purchase**。

注意,此处我们将 @RequestMapping 的method属性指定为了 POST,其实一共有八种类型(常用的有GET,POST,PUT,DELETE,HEAD这些),如下图所示:

通过一个 form 表单 来访问这个URL,并且指定为 post 类型,testPurchase.jsp代码如下:

html 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>BUY_GOODS</title>
    <style>
        /* 给表格和所有单元格设置边框 */
        table, th, td {
            border: 1px solid black;
        }

        table {
            border-collapse: collapse;
            padding: 2px;
        }

        th {
            font-weight: bold;
            border: 2px solid blue;
        }
    </style>
</head>
<body>
<form action="order/purchase" method="post">    <!-- order前面不带/ -->
    <table class="my-table">
        <tr>
            <th colspan="2">Buy Goods</th>
        </tr>
        <tr>
            <td>buyerName: </td>
            <td><input type="text" name="buyerName"/></td>
        </tr>
        <tr>
            <td>amount: </td>
            <td><input type="text" name="amount"/></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="Purchase"/></td>
        </tr>
    </table>
</form>
</body>
</html>

表单效果图如下:

再来一个 purchase_OK 页面,对应 OrderHandler 的purchase()方法的 return "purchase_OK"。purchase_OK.jsp代码如下:

html 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Successfully</title>
</head>
<body>
    <h3>Purchase Successfully!</h3>
</body>
</html>

purchase_OK 页面效果图如下:

最后进行运行测试,运行结果如下GIF图所示:

注意,由于我们在OrderHandler中指定了请求方式为 POST类型,所以如果我们将 form表单 的method属性改为 get,如下图所示:

此时form表单的请求类型和要访问的purchase()方法指定的请求类型不一致,将会报错405,如下图所示:

3.@RequestMapping指定请求参数:

@RequestMapping 中的 params属性可以用于指定请求参数,如下图所示:

params 具体的使用方式有下面几种------

params = "param1_name" : 表示请求必须包含名称 是 "param1_name" 的请求参数。

params = "param1_name!=value1" :表示请求必须包含名称 是 "param1_name" 的请求参数 并且 它的 不可以是 value1(手动指定)。

params = "!=param1_name" :表示请求必须 不包含 参数名称 为 "param1_name" 的请求参数。

params = { "param1_name=value1", "param2_name" } :表示请求必须同时 包含名称 为 "param1_name" 和 "param2_name" 的请求参数 并且 param1_name 参数的必须是指定的 value1。

以 "保存订单" 的demo来测试 params 的具体用法。在OrderHandler中新增一个saveOrder 方法,OrderHandler类代码如下:

java 复制代码
package com.cyan.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * @author : Cyan_RA9
 * @version : 22.0
 */
@RequestMapping(value = "/order")
@Controller
public class OrderHandler {
    /**
     * 1. method=RequestMethod.POST: 表示请求 purchase 目标方法的请求方式必须是 post
     * 2. SpringMVC 控制器默认支持 GET 和 POST 两种方式,(如果不指定默认就是这两个)
     */
    @RequestMapping(value = "/purchase", method = RequestMethod.POST)
    public String purchase() {
        System.out.println("make a purchase of goods~~~");
        return "purchase_OK";
    }

    @RequestMapping(value = "/save", params = "orderId!=0", method = RequestMethod.GET)
    public String saveOrder(String orderId) {
        // 传入的参数会传递到方法的形参列表
        System.out.println("orderId = " + orderId);

        return "order_OK";
    }
}

对应的order_OK.jsp代码如下:

html 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>SuccessfullyEX</title>
</head>
<body>
<h3 style="color: cornflowerblue">Order Successfully!</h3>
</body>
</html>

再来一个用于测试 /order/save 的form表单,testOrder.jsp代码如下:

html 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>SAVE_ORDERS</title>
    <style>
        /* 给表格和所有单元格设置边框 */
        table, th, td {
            border: 1px solid black;
        }

        table {
            border-collapse: collapse;
            padding: 2px;
        }

        th {
            font-weight: bold;
            border: 2px solid blue;
        }
    </style>
</head>
<body>
<form action="order/save" method="get">
    <table class="my-table">
        <tr>
            <th colspan="2">Make an Order</th>
        </tr>
        <tr>
            <td>orderId: </td>
            <td><input type="text" name="orderId"/></td>
        </tr>
        <tr>
            <td>orderType: </td>
            <td><input type="text" name="orderType"/></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="ORDER"/></td>
        </tr>
    </table>
</form>
</body>
</html>

页面效果如下图所示:

我们先输入符合规则的orderId,测试效果如下GIF图所示:

但是,如果我们将 orderId 改成 0,就会报错400 ,如下GIF图所示:

4.@RequestMapping使用Ant风格URL:

@RequestMapping 支持下面三种 Ant 风格 URL------

"?" :匹配文件名中的任意一个 字符;

"*" :匹配文件名中的任意1到多个 字符(不能匹配空字符串);

"**":匹配多层路径(0到多个路径段)

这里up在之前用过的UserSerlvet上做做手脚,来测试 Ant风格 URL,UserServlet代码如下:

java 复制代码
package com.cyan.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


@Controller //@Controller注解,标识当前类是一个控制器,有时也称为Handler(处理器)
public class UserServlet {

    @RequestMapping(value = "/user/?/login")   //此处的value可以省略
    public String login() {
        System.out.println("This is login!");
        return "login_OK";
    }

    @RequestMapping(value = "/user/*/sign")   //此处的value可以省略
    public String sign() {
        System.out.println("This is sign~~~");
        return "login_OK";
    }

    @RequestMapping(value = "/user/**/register")   //此处的value可以省略
    public String register() {
        System.out.println("This is register+++");
        return "login_OK";
    }
}

再来一个 testAnt.jsp 用于测试URL的匹配情况,testAnt.jsp代码如下------

html 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>testAnt</title>
</head>
<body>
    <a href="user/1/login">login_test1</a> <br/>
    <a href="user/2/login">login_test2</a> <br/>
    <a href="user/3/login">login_test3</a> <br/> <br/>

    <a href="user/abc/sign">sign_test1</a> <br/>
    <a href="user/fff/sign">sign_test2</a> <br/>
    <a href="user/Cyan-RA9/sign">sign_test3</a> <br/> <br/>

    <a href="user/register">register_test1</a> <br/>
    <a href="user/Pro/register">register_test2</a> <br/>
    <a href="user/Pro/Max/Ultra/Plus/register">register_test3</a>
</body>
</html>

最后进行运行测试,测试情况如下 GIF图所示:

IDEA 后台的输出结果如下图所示:

正好对应了 UserServlet 中三个方法的输出语句,符合预期。

5.@RequestMapping 配合 @PathVariable映射:

一般情况下,URL的参数形式是------action 属性[+?+请求参数] 。其中,请求参数的格式是:name=value&name=value。 但是,借助 @PathVariable 可以省略参数名,简化URL.

新建一个 UserHandler 用于演示,UserHandler类代码如下:

java 复制代码
package com.cyan.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author : Cyan_RA9
 * @version : 22.0
 */
@Controller
@RequestMapping(value = "/user")
public class UserHandler {
    /*
        1. @RequestMapping 中定义的参数名和 @PathVariable 中指定的参数名 必须保持一致。
        2. 使用了 @PathVariable 的方法的形参名,可以与上面两者不一致,形参名无所谓。
     */
    @RequestMapping(value = "/sign/up/{username}/{userid}")
    public String sign_up(@PathVariable("username") String name, @PathVariable("userid") String id) {
        System.out.println(("Parameters Received : " + "username = " + name + ", userid = " + id));

        return "login_OK";
    }
}

再来一个 testPathVariable 页面,用于测试 URL 的简化效果,testPathVariable.jsp 代码如下------

html 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>@PathVariable Test</title>
</head>
<body>
    <h3>Click the reference to take a test</h3>
    <a href="user/sign/up/Cyan_RA9/141">点我就完事儿!</a>
</body>
</html>

测试结果如下GIF图所示:


三、@RequestMapping的使用细节

  1. @RequestMapping(及其派生注解)映射的 URL 不能重复,即同一个项目中不能有两个方法去匹配完全相同的 URL,这时候 Tomcat 启动时会报错,如下图所示:

2.@RequestMapping(value = "/xxx",method = RequestMethod.POST) 就等价于 @PostMapping(value = "/xxx")。类似的写法还有: @GetMapping,@PutMapping,@DeleteMapping。

3.如果已经确定 某个表单 或者 超链接 会提交字段数据, 那么要求++提交的参数名++ 和 ++目标方法的参数名++保持一致.(也就是我们在上面演示3 和 演示5中做的那样.)


四、@RequestMapping延伸------SpringMVC中,如何通过注解实现POJO类直接作为Controller,而不依赖Servlet或接口?

我们可以使用 @Controller 来把一个POJO类 标记为SpringMVC的 控制器,@Controller 本身可以看作是 @Component 的一个特例,所以被 @Controller 标记的类也会被 Spring 容器作为组件进行管理。除了 @Controller 之外,我们还需要另一个核心注解------@RequestMapping(或者它的派生注解),这个注解可以把浏览器发来的 HTTP 请求映射到具体的 Controller 类 或者 某个方法上面;@RequestMapping 直接定义了 HTTP 请求的一些属性,例如++请求的URL,请求的方法类型,请求的参数++ 等等。

那么上面说的这两个注解,就是我们自己 能操作的部分,但是真正要想实现对 Servlet API 的解耦,背后靠的是 前端控制器(DispatcherServlet),处理器映射器(HandlerMapping),处理器适配器(HandlerAdapter) 这三大组件的协同工作,尤其是 HandlerAdapter(因为它直接实现了 适配器模式)。DispatcherServlet 拿到 HandlerMapping 找到的处理器(即 我们标记的 POJO Controller)后,并不会直接调用它。而是将处理器交给 HandlerAdapter,让它去调用。HandlerAdapter 会从 HttpServletRequest 中提取信息(即参数解析),然后把提取到的有用信息 适配为 POJO 方法的参数,那么我们标记为控制器的 POJO,根本就不需要直接接触 HttpServletRequest 或 HttpServletResponse。而且 HandlerAdapter 通过反射直接检查 POJO 方法签名,只要方法签名符合 Spring MVC 的约定,就可以被调用,所以也不需要依赖接口。

SpringMVC的执行流程回顾------如下图所示:


五、总结

  • 🆗,以上就是 SpringMVC --- @RequestMapping 的全部内容了😀。
  • 这篇文章没什么难度,主要就是演示了一下 @RequestMapping 的各种使用方式和技巧,大家只要知道 @RequestMapping 在整个 Spring MVC 中很重要并且把它用熟练就可以了。
相关推荐
sheji34162 小时前
【开题答辩全过程】以 python杭州亚运会数据分析与可视化开题为例,包含答辩的问题和答案
开发语言·python·数据分析
代码萌新知3 小时前
设计模式学习(五)装饰者模式、桥接模式、外观模式
java·学习·设计模式·桥接模式·装饰器模式·外观模式
你的人类朋友4 小时前
【Node】单线程的Node.js为什么可以实现多线程?
前端·后端·node.js
iナナ5 小时前
Spring Web MVC入门
java·前端·网络·后端·spring·mvc
驱动探索者5 小时前
find 命令使用介绍
java·linux·运维·服务器·前端·学习·microsoft
卷Java5 小时前
违规通知功能修改说明
java·数据库·微信小程序·uni-app
CoderYanger5 小时前
优选算法-双指针:2.复写零
java·后端·算法·leetcode·职场和发展
weixin_446260855 小时前
快速构建网站的利器——Symfony PHP框架
开发语言·php·symfony
小雨凉如水5 小时前
k8s学习-pod的生命周期
java·学习·kubernetes
王夏奇6 小时前
C语言中#pragma的用法
c语言·开发语言