Java--SpringMVC之RequestMapping请求映射和处理器方法参数

Posted MinggeQingchun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java--SpringMVC之RequestMapping请求映射和处理器方法参数相关的知识,希望对你有一定的参考价值。

1、新建一个maven的web项目,选择

maven-archetype-webapp

2、pom.xml文件加入依赖

spring-webmvc依赖,间接把spring的依赖都加入到项目;jsp,servlet依赖

<properties>
    <!-- 项目构建使用的编码,避免中文乱码 -->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <!-- 源码编译 jdk 版本 -->
    <maven.compiler.source>1.8</maven.compiler.source>
    <!-- 运行代码的 jdk 版本 -->
    <maven.compiler.target>1.8</maven.compiler.target>
  </properties>

  <dependencies>
    <!-- junit单元测试 -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>

    <!--springmvc依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>

    <!-- servlet依赖 -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>

  </dependencies>

  <build>
    <resources>
      <resource>
        <directory>src/main/java</directory><!--所在的目录-->
        <includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <!-- filtering 选项 false 不启用过滤器, *.property 已经起到过滤的作用了 -->
        <filtering>false</filtering>
      </resource>
    </resources>
  </build>

3、新建web.xml文件,并在该配置文件中注册SpringMVC框架的核心对象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">

    <!-- 声明,注册SpringMVC的核心对象DispatcherServlet
        在Tomcat服务器启动后,创建DispatcherServlet对象实例

        DispatcherServlet在创建过程中,会同时创建SpringMVC容器对象,读取SpringMVC配置文件,把这个配置文件中的对象都创建好,
        用户发起请求时就可以直接适用对象

        Servlet初始化会执行 init() 方法;DispatcherServlet在 init() 方法中
        (1)创建容器,读取配置文件
            WebApplicationContext ctx = new ClassPathXmlApplicationContext("springmvc.xml");
        (2)将容器对象放入到ServletContext中
            getServletContext().setAttribute(key, ctx);
    -->
    
    <servlet>
        <servlet-name>myweb</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <!-- 启动Tomcat报错,无法读取这个文件 /WEB-INF/myweb-servlet.xml
            Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/myweb-servlet.xml]
            SpringMVC创建容器对象时,默认读取的配置文件是 /WEB-INF/<servlet-name>-servlet.xml

            因此需要自定义SpringMVC读取配置文件的位置
            <init-param> :在servlet类中通过getInitParamenter(String name)方法访问初始化参数
            param-name 就是参数名;param-value就是参数值,支持多个参数
            在这个方法中通过 getInitParamter("key"); key 就是 param-name的值,来获取对应的参数值
        -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>


        <!-- tomcat启动后,创建Servlet对象
            load-on-startup:表示Tomcat启动后创建对象的顺序;
            它的值是整数,数值越小,Tomcat创建对象的时间越早,大于等于0的整数
        -->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>myweb</servlet-name>

        <!-- url-pattern  拦截匹配规则的 url 请求,进入springmvc 框架处理,
        springmvc 就会去找能够处理这个url 的 handler去执行业务逻辑
        可使用两种值
            (1)使用扩展名方式,语法  *.xx , xx是自定义的扩展名,
                常用的方式 *.do, *.action, *.mvc等等
                不能使用 *.jsp
                http://localhost:8080/myweb/some.do
                http://localhost:8080/myweb/other.do
            (2)使用斜杠 "/"
        -->
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

</web-app>

4、创建一个发起请求的页面 index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <p>SpringMVC项目</p>
    <p> <a href="menu/some.do">发起some.do的GET请求</a> </p>
    <br/>

    <form action="menu/other.do" method="post">
        <input type="submit" value="post请求other.do">
    </form>
    <br/>

    <p> <a href="menu/noMethod.do">发起noMethod.do的GET请求</a> </p>
    <br/>

    <form action="menu/noMethod.do" method="post">
        <input type="submit" value="post请求noMethod.do">
    </form>
</body>
</html>

5、创建控制器(处理器)类

6、创建一个结果的 show.jsp,显示处理结果

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>/WEB-INF/view/show.jsp从request作用域获取数据</h3>
    <h3>msg数据:$msg</h3><br/>
    <h3>fun数据:$fun</h3>
</body>
</html>

 7、创建SpringMVC的配置文件(和spring的配置文件一样)

工程的类路径即 src 目录下创建 SpringMVC 的配置文件 springmvc.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"
       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="com.mycompany.controller" />

    <!-- 声明SpringMVC框架中的视图解析器,设置视图文件的路径:InternalResourceViewResolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 前缀:视图文件的路径 -->
        <property name="prefix" value="/WEB-INF/view/" />
        <!-- 后缀:视图文件的扩展名 -->
        <property name="suffix" value=".jsp" />
    </bean>

</beans>

8、启动Tomcat,或者未修改Java代码,只修改 jsp 代码,重启资源即可配置如下 

选择Edit Configurations...

点击添加,选择Tomcat Server ----> Local

 

如果这里没有Tomcat Server 选项 ;有可能是tomcat插件没启用,我们点击

file---->setting---->搜索tomcat---->勾选上

(3)配置Tomcat的信息

(4)点击Deployment----加号➕----Artifact...,配置访问路径

对应web.xml文件中的url-pattern 访问的路径 

启动Tomcat,输入的访问地址为 网址+端口号+工程名+访问的路径;如:

 输入 :http://localhost:8888/spring-web/

一、@RequestMapping请求映射规则 

@RequestMapping 注解可以定义处理器对于请求的映射规则。该注解可以注解在方法上,也可以注解在类上

1、value 属性

value属性值常以 "/" 开始

@RequestMapping 的 value 属性用于定义所匹配请求的 URI。一个@Controller 所注解的类中,可以定义多个处理器方法。不同的处理器方法所匹配的 URI 是不同的,不同的 URI 被指定在注解于方法之上的@RequestMapping 的value 属性中。但若这些请求具有相同的 URI 部分,则这些相同的 URI,可以被抽取到注解在类之上的@RequestMapping 的 value 属性中。此时的这个 URI 表示模块的名称。URI 的请求是相对于 Web 的根目录

(1)@RequestMapping放在类上面,就是请求地址的公共部分(模块名称)

(2)@RequestMapping放在方法上面,结合类上的RequestMapping的value值即是模块的某个方法请求

2、method属性

Method 属性的取值为 RequestMethod 枚举常量。常用的为 RequestMethod.GET 与RequestMethod.POST,分别表示提交方式的匹配规则为 GET 与 POST 提交

注:

(1)指定了GET请求,就不能使用POST请求,不然报错

(2)不指定请求方式,没有限制,GET和POST皆可

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

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * @RequestMapping
 *    value:放在类上就是请求地址的公共部分(模块名称)
 */
@Controller
@RequestMapping("/menu")
public class MyController 

    /**
     * @RequestMapping :请求映射
     *      属性:method,表示请求的方式,值为RequestMethod枚举值
     *      Get请求方式,RequestMethod.GET
     *      POST请求方式,RequestMethod.POST
     *
     * 指定了请求方式,如Get,使用POST请求会报错:
     * HTTP Status 405 - Request method 'POST' not supported
     */
    //指定some.do使用get请求方式
    @RequestMapping(value = "/some.do",method = RequestMethod.GET)
    public ModelAndView doSome() // doGet()----service请求处理
        //处理 some.do请求,相当于service调用处理完成
        ModelAndView mdv = new ModelAndView();
        mdv.addObject("msg","欢迎使用SpringMVC做web开发");
        mdv.addObject("fun","执行的是doSome方法");
        mdv.setViewName("show");

        return mdv;
    

    //指定other.do是post请求方式
    @RequestMapping(value = "/other.do",method = RequestMethod.POST)
    public ModelAndView doOther()
        ModelAndView mv  = new ModelAndView();
        mv.addObject("msg","====欢迎使用SpringMVC做web开发====");
        mv.addObject("fun","执行的是doOther方法");
        mv.setViewName("other");
        return mv;
    

    //不指定请求方式,没有限制
    @RequestMapping(value = "/noMethod.do")
    public ModelAndView doNoMethod(HttpServletRequest request,
                                   HttpServletResponse response,
                                   HttpSession session)
        ModelAndView mv  = new ModelAndView();
        mv.addObject("msg","====欢迎使用SpringMVC做web开发====" + request.getParameter("name"));
        mv.addObject("fun","执行的是doNoMethod方法");
        mv.setViewName("other");
        return mv;
    

二、处理器方法参数

1、逐个参数接收

(1)请求参数名与该请求处理方法的参数名相同

index.jsp页面

<p>提交参数给Controller</p>
    <form action="receiveproperty.do" method="post">
        姓名:<input type="text" name="name"> <br/>
        年龄:<input type="text" name="age"> <br/>
        <input type="submit" value="提交参数">
    </form>

MyController.java处理器类

/**
     * 1、逐个接收请求参数
     *      处理器(控制器)方法的形参名和请求中参数名必须一致;同名请求参数赋值给同名形参
     *
     * SpringMVC框架接收请求参数
     * (1)使用request对象接收请求参数
     *      String strName = request.getParameter("name");
     *      String strAge = request.getParameter("age");
     * (2)SpringMVC框架通过DispatcherServlet调用 MyController的doSome()方法
     *      调用方法时,按名称对应,把接收的参数赋值给形参
     *      doSome(strName,Integer.valueOf(strAge))
     *      框架会提供类型转换的功能,能把String转为 int ,long , float, double等类型
     */
    @RequestMapping(value = "/receiveproperty.do")
    public ModelAndView doSome(String name,Integer age)
        System.out.println("doSome, name="+name+"   age="+age);

        //处理 some.do请求,相当于service调用处理完成
        ModelAndView mdv = new ModelAndView();
        mdv.addObject("myname",name);
        mdv.addObject("myage",Integer.valueOf(age));
        mdv.setViewName("show");

        return mdv;
    

(2)请求参数名与该请求处理方法的参数名不相同

若请求 URL 所携带的参数名称与处理方法中指定的参数名不相同时,则需在处理方法参数前,添加一个注解@RequestParam(“请求参数名”),指定请求 URL 所携带参数的名称

index.jsp页面

<br/>
    <p>请求参数名和处理器方法的形参名不一样</p>
    <form action="receiveparam.do" method="post">
        姓名:<input type="text" name="rname"> <br/>
        年龄:<input type="text" name="rage"> <br/>
        <input type="submit" value="提交参数">
    </form>

MyController.java处理器类

/**
     * 逐个接收请求参数
     *
     * 请求中参数名和处理器方法的形参名不一样
     * @RequestParam : 逐个接收请求参数中,解决请求中参数名形参名不一样问题
     *      属性:1、value 请求中的参数名称
     *           2、required  boolean类型,默认是true
     *              true请求中必须包含此参数
     *      位置:在处理器方法的形参定义前面
     */
    @RequestMapping(value = "/receiveparam.do")
    public ModelAndView receiveParams(@RequestParam(value = "rname",required = false) String name,
                                    @RequestParam(value = "rage",required = false) Integer age)
        System.out.println("receiveparam, name="+name+"   age="+age);
        ModelAndView mv  = new ModelAndView();
        mv.addObject("myname",name);
        mv.addObject("m   yage",age);
        //show是视图文件的逻辑名称(文件名称)
        mv.setViewName("show");
        return mv;
    

2、对象接收

将处理器方法的参数定义为一个对象,保证请求参数名与这个对象的属性同名即可

Java对象Student.java类
public class Student 
    // 属性名和请求中参数名一样
    private String name;
    private Integer age;

index.jsp页面

<br/>
    <p>使用java对象接收请求参数</p>
    <form action="receiveobject.do" method="post">
        姓名:<input type="text" name="name"> <br/>
        年龄:<input type="text" name="age"> <br/>
        <input type="submit" value="提交参数">
    </form>
MyController.java处理器类
/**
     * 对象接收请求参数
     */
    @RequestMapping(value = "/receiveobject.do")
    public ModelAndView receiveObject(Student student)
        System.out.println("receiveParam, name=" + student.getName() + "   age=" + student.getAge());
        //可以在方法中直接使用 name , age
        //处理some.do请求了。 相当于service调用处理完成了。
        ModelAndView mv  = new ModelAndView();
        mv.addObject("myname",student.getName());
        mv.addObject("myage",student.getAge());
        mv.addObject("mystudent",student);
        //show是视图文件的逻辑名称(文件名称)
        mv.setViewName("show");
        return mv;
    

这里需要注意一个问题,我们使用POST请求,如果参数中包含中文,会出现乱码情况

使用GET请求不会出现此问题,我们需要在 web.xml 配置文件中注册字符集过滤器:spring-web-5.2.5.RELEASE.jar 的org.springframework.web.filter 包下的 CharacterEncodingFilter

public class CharacterEncodingFilter extends OncePerRequestFilter 

    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException 
        String encoding = this.getEncoding();
        if (encoding != null) 
            if (this.isForceRequestEncoding() || request.getCharacterEncoding() == null) 
                request.setCharacterEncoding(encoding);
            

            if (this.isForceResponseEncoding()) 
                response.setCharacterEncoding(encoding);
            
        

        filterChain.doFilter(request, response);
    

<!-- 注册声明过滤器,解决POST请求中文乱码 -->
    <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>
        <!--强制请求对象(HttpServletRequest)使用encoding编码的值-->
        <init-param>
            <param-name>forceRequestEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
        <!--强制响应对象(HttpServletResponse)使用encoding编码的值-->
        <init-param>
            <param-name>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <!-- /*:表示强制所有的请求先通过过滤器处理 -->
        <url-pattern>/*</url-pattern>
    </filter-mapping>

以上是关于Java--SpringMVC之RequestMapping请求映射和处理器方法参数的主要内容,如果未能解决你的问题,请参考以下文章

[Java]SpringMVC工作原理之二:HandlerMapping和HandlerAdapter

[Java] SpringMVC工作原理之二:HandlerMapping和HandlerAdapter

Java--SpringMVC之处理器方法返回值

Java--SpringMVC之url-pattern,静态资源;URL相对路径,绝对路径

Java--SpringMVC之RequestMapping请求映射和处理器方法参数

推荐学java——SpringMVC第一课