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

发布于:2025-09-15 ⋅ 阅读:(22) ⋅ 点赞:(0)

目录

一、@RequestMapping是什么?

二、@RequestMapping 的使用演示

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

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

        3.@RequestMapping指定请求参数:

        4.@RequestMapping使用Ant风格URL:

        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代码如下:

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代码如下:

<%@ 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代码如下:

<%@ 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类代码如下:

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代码如下:

<%@ 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代码如下:

<%@ 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代码如下:

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代码如下——

<%@ 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类代码如下:

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 代码如下——

<%@ 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 中很重要并且把它用熟练就可以了。