[华为云在线课程][SpringMVC入门][四][处理器详解][学习笔记]

举报
John2021 发表于 2022/07/17 23:00:43 2022/07/17
【摘要】 1.@RequestMapping注解使用细节这个注解标记一个接口,是接口开发中使用最多的注解之一。 1.1.请求URL标记请求URL只需要在相应方法上添加该注解就可以了package org.example.controller;import org.springframework.stereotype.Controller;import org.springframework.web....

1.@RequestMapping注解使用细节

这个注解标记一个接口,是接口开发中使用最多的注解之一。

1.1.请求URL

标记请求URL只需要在相应方法上添加该注解就可以了

package org.example.controller;

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

@Controller
public class MyController3 {
    @RequestMapping("/hello3")
    public ModelAndView hello() {
        return new ModelAndView("hello3");
    }
}

这里@RequestMapping("/hello3")表示当请求地址为/hello3时,这个方法被触发。其中,地址可以是多个,就是可以多个地址映射到同一个方法。

package org.example.controller;

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

@Controller
public class MyController3 {
    @RequestMapping("/hello3")
    public ModelAndView hello3() {
        return new ModelAndView("hello3");
    }

    @RequestMapping({"/hello2","/hello"})
    public ModelAndView hello2() {
        return new ModelAndView("hello");
    }
}

这个配置表示请求地址为/hello2和/hello都可以访问到这个方法。

1.2.请求窄化

同一个项目中会存在多个接口,例如订单相关的接口都是/order/xxx格式,用户相关的接口都是/user/xxx格式。为了方便处理,这里的前缀可以统一在Controller上处理。

package org.example.controller;

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

@Controller
@RequestMapping("/hello")
public class MyController4 {
    @RequestMapping("/hello3")
    public ModelAndView hello3() {
        return new ModelAndView("hello3");
    }
}

在类上加了@RequestMapping注解之后,此时,要想访问到hello,地址就应该是/hello/hello3。

1.3.请求方法限定

默认情况下,使用@RequestMapping注解定义好的方法,可以被GET请求访问到,也可以被POST请求访问到,但是DELETE和PUT请求不能访问到。
我们也可以指定具体的访问方法:

package org.example.controller;

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;

@Controller
public class MyController3 {
    @RequestMapping(value = "/hello3",method = RequestMethod.GET)
    public ModelAndView hello3() {
        return new ModelAndView("hello3");
    }

    @RequestMapping(value = {"/hello2","/hello"},method = RequestMethod.POST)
    public ModelAndView hello2() {
        return new ModelAndView("hello");
    }
}

通过@RequestMapping注解,指定了/hello3接口只能被GET请求访问到,/hello2和/hello只能被POST请求访问到,强行访问就会报错:
hello3进行GET请求

hello3进行POST请求

hello进行GET请求

hello进行POST请求

限定的方法也可以有多个:

@RequestMapping(value = {"/hello2","/hello"},method = {RequestMethod.GET,RequestMethod.POST,
RequestMethod.DELETE,RequestMethod.PUT})
public ModelAndView hello2() {
    return new ModelAndView("hello");
}

经过这个配置后,接口就可以被GET,POST,PUT,DELETE访问到了。但是,由于JSP只支持GET,POST以及HEAD,所以这个测试,不能使用JSP做页面模板。可以将视图换成其他的,或者返回JSON。

2.Controller中接口方法各种返回值类型

2.1.返回ModelAndView

如果是前后端不分离的开发,大部分情况下,返回ModelAndView,即数据加视图:

@Controller
public class MyController3 {
    @RequestMapping(value = "/hello3",method = RequestMethod.GET)
    public ModelAndView hello3() {
        ModelAndView modelAndView = new ModelAndView("hello3");
        modelAndView.addObject("username", "helloolleh");
        return modelAndView;
    }
}

在Model中放入我们的数据,然后在ModelAndView中指定视图名称

2.2.返回Void

没有返回值,并不一定真的没有返回值,只是方法的返回值为void,我们可以通过其他方式给前端返回。实际上,这种方式也可以理解为Servlet中的那一套。
需要注意的是,由于默认Maven项目中没有Servlet,需要额外添加一个依赖:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
</dependency>

通过HttpServletRequest做服务端跳转

@RequestMapping("/hello")
public void hello(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    //服务器端跳转
    request.getRequestDispatcher("/WEB-INF/hello.jsp").forward(request,response);
}

通过HttpServletResponse做重定向

@RequestMapping("/hello2")
public void hello2(HttpServletRequest request,HttpServletResponse response)
    throws IOException{
    response.sendRedirect("/WEB-INF/hello.jsp");
}

也可以自己手动指定响应头实现重定向:

@RequestMapping("/hello3")
public void hello3(HttpServletRequest request,HttpServletResponse response)
    throws IOException{
    response.setStatus(200);
    response.addHeader("Location", "/WEB-INF/hello.jsp");
}

通过HttpServletResponse做出响应

@RequestMapping("/hello4")
public void hello4(HttpServletRequest request,HttpServletResponse response)
    throws IOException{
    response.setContentType("text/html;charset=utf-8");
    PrintWriter writer = response.getWriter();
    writer.write("hello requestmapping hello4");
    writer.flush();
    writer.close();
}

这种方式既可以返回JSON,又可以返回普通字符串。

2.3.返回字符串

  • 返回逻辑视图名
    前面的ModelAndView可以拆分为两部分,Model和View,在SpringMVC中,Model我们可以直接在参数中指定,然后返回值是逻辑视图名:
@RequestMapping("/hello5")
public String hello5(Model model) {
    //这是数据模型
    model.addAttribute("name", "hello hello5");
    //去查找一个名为hello的视图
    return "hello";
}

  • 服务端跳转
@RequestMapping("/hello5")
public String hello5() {
    return "forward:/WEB-INF/jsp/hello.jsp";
}

forward后面跟上跳转的路径

  • 客户端跳转
@RequestMapping("/hello5")
public String hello5() {
    return "redirect:/hello2";
}

将会跳转到localhost:8080/hello2。本质上就是浏览器重定向。

  • 真的返回一个字符串
    上面三个返回的字符串,都有有特殊含义的,如果一定要返回一个字符串,需要额外添加一个注意:@ResponseBody,这个注解表示当前方法的返回值就是要展示出来返回值,没有特殊含义。
@RequestMapping("/hello5")
@ResponseBody
public String hello5() {
    return "redirect:/hello2";
}

页面直接返回了redirect:/hello2。这里如果想单纯返回一个中文字符串,要在@RequestMapping中添加produces属性来解决乱码问题:

@RequestMapping(value = "/hello5",produces = "text/html;charset=utf-8")
@ResponseBody
public String hello5() {
    return "Java程序设计指南";
}

3.参数绑定

3.1.默认支持的参数类型

默认支持的参数类型,就是可以直接写在@RequestMapping所注解的方法中的参数类型,一共有四类:

  1. HttpServletRequest
  2. HttpServletResponse
  3. HttpSession
  4. Model/ModelMap

在请求的方法中,默认参数就是这几个,如果在方法中刚好需要这几个参数,那么可以把这几个参数加入到方法中。

3.2.简单数据类型

Integer,Boolean,Double等这些简单数据类型也支持。例如添加一本书:
首先,在/WEB-INF/jsp/目录下创建addbook.jsp,作为图书添加页面:

<%--
  Created by IntelliJ IDEA.
  User: John
  Date: 2022/7/17/0017
  Time: 6:17
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>图书添加页面</title>
</head>
<body>
<form action="/doAdd" method="post">
    <table>
        <tr>
            <td>书名:</td>
            <td><input type="text" name="name"></td>
        </tr>
        <tr>
            <td>作者:</td>
            <td><input type="text" name="author"></td>
        </tr>
        <tr>
            <td>价格:</td>
            <td><input type="number" name="price"></td>
        </tr>
        <tr>
            <td>是否上架:</td>
            <td>
                <input type="radio" value="true" name="ispublic"><input type="radio" value="false" name="ispublic"></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="添加">
            </td>
        </tr>
    </table>
</form>
</body>
</html>

然后创建控制器,控制器提供两个功能,访问jsp页面和提供添加接口:

package org.example.controller;

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

@Controller
public class BookController {
    @RequestMapping("/book")
    public String addBook() {
        return "addbook";
    }

    @RequestMapping(value = "/doAdd", method = RequestMethod.POST)
    @ResponseBody
    public void doAdd(String name, String author, Double price, Boolean ispublic) {
        System.out.println(name);
        System.out.println(author);
        System.out.println(price);
        System.out.println(ispublic);
    }
}

注意,由于doAdd方法确定不想返回任何值,所以需要给该方法添加@ResponseBody注解,表示方法不去查找相关视图。另外,POST请求上传的中文会有乱码问题,所以需要在web.xml中再额外添加一个编码过滤器:

<!--编码过滤器,解决中文乱码问题-->
<filter>
    <filter-name>encoding</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>forceRequestEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <param-name>forceResponseEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

最后,浏览器输入http://localhost:8080/book,就可以执行添加操作,服务端会打印出来相应的日志。
在上面的绑定中,有个要求,表单中字段的name属性要和接口中的变量名一一对应才能映射成功,否则服务端无法接收前端传来的数据。有些特殊情况,服务端的接口变量名可能和前端不一致,这时可以通过@RequestParam注解来解决。这个注解的功能有三个方面:

  1. 给变量取别名
  2. 设置变量是否必填
  3. 给变量设置默认值
@RequestMapping(value = "/doAdd", method = RequestMethod.POST)
@ResponseBody
public void doAdd(@RequestParam("name") String bookname, String author, Double price, Boolean ispublic) {
    System.out.println(bookname);
    System.out.println(author);
    System.out.println(price);
    System.out.println(ispublic);
}

注解中的"name"表示给bookname这个变量取得别名,也就是说bookname将接收前端传来的name这个变量的值。在这个注解中,还可以添加required属性和defaultValue属性

@RequestMapping(value = "/doAdd", method = RequestMethod.POST)
@ResponseBody
public void doAdd(@RequestParam(value = "name", required = true, defaultValue = "你好啊世界") String bookname,
                    String author, Double price, Boolean ispublic) {
    System.out.println(bookname);
    System.out.println(author);
    System.out.println(price);
    System.out.println(ispublic);
}

required属性默认为true,只要添加了@RequestParam注解,这个参数默认必填,不填会报400错误,如果这个参数不是必填,可以手动将required设置false。但是,如果同时设置defaultValue,这时候前端不传该参数到后端,即使required属性为true,也不会报错。

3.3.实体类

参数也可以是实体类。实际开发中,大部分情况下都是实体类。改用一个Book对象来接收前端传来的数据:

package org.example.model;

public class Book {
    private String name;
    private String author;
    private Double price;
    private Boolean ispublic;

    public Book() {
    }

    public Book(String name, String author, Double price, Boolean ispublic) {
        this.name = name;
        this.author = author;
        this.price = price;
        this.ispublic = ispublic;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public Boolean getIspublic() {
        return ispublic;
    }

    public void setIspublic(Boolean ispublic) {
        this.ispublic = ispublic;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", price=" + price +
                ", ispublic=" + ispublic +
                '}';
    }
}

服务端接收数据方式如下:

@RequestMapping(value = "/doAdd", method = RequestMethod.POST)
@ResponseBody
public void doAdd(Book book) {
    System.out.println(book);//Book{name='Java指南', author='某人', price=100.0, ispublic=true}
}

前端页面传值和上面的写法是一样的,直接写上属性名就行了,不需要写book对象名。
如果碰到对象里面还有对象的情况,比如Book对象中还有一个Author对象:

package org.example.model;

public class Book {
    private String name;
    private Double price;
    private Boolean ispublic;
    private Author author;

    public Book() {
    }

    public Book(String name, Double price, Boolean ispublic, Author author) {
        this.name = name;
        this.price = price;
        this.ispublic = ispublic;
        this.author = author;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public Boolean getIspublic() {
        return ispublic;
    }

    public void setIspublic(Boolean ispublic) {
        this.ispublic = ispublic;
    }

    public Author getAuthor() {
        return author;
    }

    public void setAuthor(Author author) {
        this.author = author;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", price=" + price +
                ", ispublic=" + ispublic +
                ", author=" + author +
                '}';
    }
}
package org.example.model;

public class Author {
    private String name;
    private Integer age;

    public Author() {
    }

    public Author(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Author{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

前端要更改写法:

<%--
  Created by IntelliJ IDEA.
  User: John
  Date: 2022/7/17/0017
  Time: 6:17
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>图书添加页面</title>
</head>
<body>
<form action="/doAdd" method="post">
    <table>
        <tr>
            <td>书名:</td>
            <td><input type="text" name="name"></td>
        </tr>
        <tr>
            <td>作者名字:</td>
            <td><input type="text" name="author.name"></td>
        </tr>
        <tr>
            <td>作者年龄:</td>
            <td><input type="number" name="author.age"></td>
        </tr>
        <tr>
            <td>价格:</td>
            <td><input type="number" name="price"></td>
        </tr>
        <tr>
            <td>是否上架:</td>
            <td>
                <input type="radio" value="true" name="ispublic"><input type="radio" value="false" name="ispublic"></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="添加">
            </td>
        </tr>
    </table>
</form>
</body>
</html>

这样后端直接用Book对象就能接收到所有数据。

@RequestMapping(value = "/doAdd", method = RequestMethod.POST)
@ResponseBody
public void doAdd(Book book) {
    System.out.println(book);//Book{name='Java指南', price=200.0, ispublic=true, author=Author{name='某人', age=100}}
}

3.4.自定义参数绑定

前面这些转换都是系统自动进行的,仅限于基本数据类型。特殊的数据类型系统无法自动转换,例如日期。前端传一个日期到后端,后端不是用字符串接收,而是使用一个Date对象接收,这时就会出现参数类型转换失败。这时需要我们手动定义参数类型转换器,将日期字符串手动转为Date对象。

package org.example.controller.utils;

import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

@Component
public class DateConverter implements Converter<String, Date> {
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

    @Override
    public Date convert(String source) {
        try {
            return simpleDateFormat.parse(source);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
}

在自定义的参数类型转换器中,将一个String转为Date对象,同时,将这个转换器注册为Bean。
在SpringMVC配置文件中,配置Bean使其生效

<mvc:annotation-driven conversion-service="conversionService"/>
<bean class="org.springframework.format.support.FormattingConversionServiceFactoryBean"
        id="conversionService">
    <property name="converters">
        <set>
            <ref bean="dateConverter"/>
        </set>
    </property>
</bean>
package org.example.model;

import java.util.Date;

public class Book {
    private String name;
    private Double price;
    private Author author;
    private Date publishDate;

    public Book() {
    }

    public Book(String name, Double price, Author author, Date publishDate) {
        this.name = name;
        this.price = price;
        this.author = author;
        this.publishDate = publishDate;
    }

    public Date getPublishDate() {
        return publishDate;
    }

    public void setPublishDate(Date publishDate) {
        this.publishDate = publishDate;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }


    public Author getAuthor() {
        return author;
    }

    public void setAuthor(Author author) {
        this.author = author;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", price=" + price +
                ", author=" + author +
                ", publishDate=" + publishDate +
                '}';
    }
}
<%--
  Created by IntelliJ IDEA.
  User: John
  Date: 2022/7/17/0017
  Time: 6:17
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>图书添加页面</title>
</head>
<body>
<form action="/doAdd" method="post">
    <table>
        <tr>
            <td>书名:</td>
            <td><input type="text" name="name"></td>
        </tr>
        <tr>
            <td>作者名字:</td>
            <td><input type="text" name="author.name"></td>
        </tr>
        <tr>
            <td>作者年龄:</td>
            <td><input type="number" name="author.age"></td>
        </tr>
        <tr>
            <td>价格:</td>
            <td><input type="number" name="price"></td>
        </tr>
        <tr>
            <td>出版时间:</td>
            <td><input type="date" name="publishDate"></td>
        </tr>
        <tr>
            <td><input type="submit" value="添加"></td>
        </tr>
        <%--<tr>
            <td>是否上架:</td>
            <td>
                <input type="radio" value="true" name="ispublic"><input type="radio" value="false" name="ispublic"></td>
        </tr>--%>
        <%--<tr>
            <td colspan="2">
                <input type="submit" value="添加">
            </td>
        </tr>--%>
    </table>
</form>
</body>
</html>
@RequestMapping(value = "/doAdd", method = RequestMethod.POST,produces = "text/html;charset=utf-8")
@ResponseBody
public String doAdd(Book book) {
    return book.toString();//Book{name='Java指南', price=200.0, author=Author{name='某人', age=100}, publishDate=Sun Jul 17 00:00:00 CST 2022}
}

配置完成后,在服务端可以接收前端传来的日期参数。

3.5.集合类的参数

  1. String数组
    String数组可以直接用数组去接收,前端传递的时候,数组的传递其实就是多个相同的key,一般用在checkbox。比如在前端页面增加爱好:
<%--
  Created by IntelliJ IDEA.
  User: John
  Date: 2022/7/17/0017
  Time: 6:17
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>图书添加页面</title>
</head>
<body>
<form action="/doAdd" method="post">
    <table>
        <tr>
            <td>书名:</td>
            <td><input type="text" name="name"></td>
        </tr>
        <tr>
            <td>作者名字:</td>
            <td><input type="text" name="author.name"></td>
        </tr>
        <tr>
            <td>作者年龄:</td>
            <td><input type="number" name="author.age"></td>
        </tr>
        <tr>
            <td>价格:</td>
            <td><input type="number" name="price"></td>
        </tr>
        <tr>
            <td>出版时间:</td>
            <td><input type="date" name="publishDate"></td>
        </tr>
        <tr>
            <td>是否上架:</td>
            <td>
                <input type="radio" value="true" name="ispublic"><input type="radio" value="false" name="ispublic"></td>
        </tr>
        <tr>
            <td>爱好:</td>
            <td>
                <input type="checkbox" name="favorites" value="吃饭">吃饭
                <input type="checkbox" name="favorites" value="睡觉">睡觉
                <input type="checkbox" name="favorites" value="看电视">看电视
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="添加">
            </td>
        </tr>
    </table>
</form>
</body>
</html>
package org.example.model;

import java.util.Arrays;
import java.util.Date;

public class Book {
    private String name;
    private Double price;
    private Author author;
    private Date publishDate;
    private String[] favorites;

    public Book() {
    }

    public Book(String name, Double price, Author author, Date publishDate, String[] favorites) {
        this.name = name;
        this.price = price;
        this.author = author;
        this.publishDate = publishDate;
        this.favorites = favorites;
    }

    public Date getPublishDate() {
        return publishDate;
    }

    public void setPublishDate(Date publishDate) {
        this.publishDate = publishDate;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }


    public Author getAuthor() {
        return author;
    }

    public void setAuthor(Author author) {
        this.author = author;
    }

    public String[] getFavorites() {
        return favorites;
    }

    public void setFavorites(String[] favorites) {
        this.favorites = favorites;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", price=" + price +
                ", author=" + author +
                ", publishDate=" + publishDate +
                ", favorites=" + Arrays.toString(favorites) +
                '}';
    }
}

在服务端用一个数组去接收favorites对象:

@RequestMapping(value = "/doAdd", method = RequestMethod.POST, produces = "text/html;charset=utf-8")
@ResponseBody
public void doAdd(Book book, String[] favorites) {
    System.out.println(Arrays.toString(favorites));
    System.out.println(book);
    /*
    *   [吃饭, 睡觉]
        Book{name='Java指南', price=200.0, author=Author{name='某人', age=100}, publishDate=Sun Jul 17 00:00:00 CST 2022, favorites=[吃饭, 睡觉]}
    * */
}

注意,前端传来的数组对象,服务端不可以使用List集合去接收。

  1. List集合
    如果需要使用List集合接收前端传来的数据,List集合本身需要放在一个封装对象中,这时List中可以是基本数据类型,也可以是对象。例如一个班级类,班级有多个学生:
package org.example.model;

import java.util.List;

public class MyClassroom {
    private Integer id;
    private List<Student> students;

    public MyClassroom() {
    }

    public MyClassroom(Integer id, List<Student> students) {
        this.id = id;
        this.students = students;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public List<Student> getStudents() {
        return students;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }

    @Override
    public String toString() {
        return "MyClassroom{" +
                "id=" + id +
                ", students=" + students +
                '}';
    }
}
package org.example.model;

public class Student {
    private Integer id;
    private String name;

    public Student() {
    }

    public Student(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

添加班级的时候可以传递多个Student,前端页面如下:

<%--
  Created by IntelliJ IDEA.
  User: John
  Date: 2022/7/17/0017
  Time: 19:40
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>添加班级学生</title>
</head>
<body>
<form action="/addClass" method="post">
    <table>
        <tr>
            <td>班级号:</td>
            <td><input type="text" name="id"></td>
        </tr>
        <tr>
            <td>学生号:</td>
            <td><input type="text" name="students[0].id"></td>
        </tr>
        <tr>
            <td>学生名:</td>
            <td><input type="text" name="students[0].name"></td>
        </tr>
        <tr>
            <td>学生号:</td>
            <td><input type="text" name="students[1].id"></td>
        </tr>
        <tr>
            <td>学生名:</td>
            <td><input type="text" name="students[1].name"></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="提交">
            </td>
        </tr>
    </table>
</form>
</body>
</html>

服务端直接接收数据即可:

package org.example.controller;

import org.example.model.MyClassroom;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class ClassController {
    @RequestMapping("/class")
    public String addClass() {
        return "addClass";
    }


    @RequestMapping("/addClass")
    @ResponseBody
    public void addClass(MyClassroom myClassroom) {
        System.out.println(myClassroom);//MyClassroom{id=1, students=[Student{id=1, name='hello'}, Student{id=2, name='world'}]}
    }
}
  1. Map
    相对于实体类而言,Map是一种比较灵活的方案,但Map的维护性比较差,一般不推荐使用。
    例如给班级类添加其他属性信息:
package org.example.model;

import java.util.List;
import java.util.Map;

public class MyClassroomMap {
    private Integer id;
    private List<Student> students;
    private Map<String,Object> info;

    public MyClassroomMap() {
    }

    public MyClassroomMap(Integer id, List<Student> students, Map<String, Object> info) {
        this.id = id;
        this.students = students;
        this.info = info;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public List<Student> getStudents() {
        return students;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }

    public Map<String, Object> getInfo() {
        return info;
    }

    public void setInfo(Map<String, Object> info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return "MyClassroomMap{" +
                "id=" + id +
                ", students=" + students +
                ", info=" + info +
                '}';
    }
}

在前端,通过以下方式给这个Map赋值。

<%--
  Created by IntelliJ IDEA.
  User: John
  Date: 2022/7/17/0017
  Time: 19:40
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>添加班级学生Map</title>
</head>
<body>
<form action="/addClassMap" method="post">
    <table>
        <tr>
            <td>班级号:</td>
            <td><input type="text" name="id"></td>
        </tr>
        <tr>
            <td>班级名称:</td>
            <td><input type="text" name="info['name']"></td>
        </tr>
        <tr>
            <td>班级位置:</td>
            <td><input type="text" name="info['pos']"></td>
        </tr>
        <tr>
            <td>学生号:</td>
            <td><input type="text" name="students[0].id"></td>
        </tr>
        <tr>
            <td>学生名:</td>
            <td><input type="text" name="students[0].name"></td>
        </tr>
        <tr>
            <td>学生号:</td>
            <td><input type="text" name="students[1].id"></td>
        </tr>
        <tr>
            <td>学生名:</td>
            <td><input type="text" name="students[1].name"></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="提交">
            </td>
        </tr>
    </table>
</form>
</body>
</html>

服务端代码:

package org.example.controller;

import org.example.model.MyClassroom;
import org.example.model.MyClassroomMap;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class ClassControllerMap {
    @RequestMapping("/classmap")
    public String addClass() {
        return "addClassMap";
    }


    @RequestMapping("/addClassMap")
    @ResponseBody
    public void addClass(MyClassroomMap myClassroom) {
        System.out.println(myClassroom);//MyClassroomMap{id=1, students=[Student{id=1, name='hello'}, Student{id=2, name='你好啊'}], info={name=班级名称1, pos=班级位置1}}
    }
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。