SpringMVC(六)处理请求2.0

(1)复杂数据类型
这里指的复杂数据类型指的是一个自定义类型中还包含另外一个对象类型,如用户类型中包含产品对象:

public class User {
    private String username;
    private Product product;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Product getProduct() {
        return product;
    }

    public void setProduct(Product product) {
        this.product = product;
    }
}

示例代码如下:

// 自动参数映射复杂数据类型
    @RequestMapping("/action02")
    public String action02(Model model, User user) {
        model.addAttribute("message", user.getUsername() + "," + user.getProduct().getName());
        return "foo/index";
    }

SpringMVC(六)处理请求2.0
为了方便这里我使用的是url,这里当然可以是一个表单,如下代码所示:

<form method="post" action="foo/action02">
     username:<input name="username" /><br/>
     pdctname:<input name="product.name" /><br/>
    <button>提交</button>
</form>

(2)数组
方法一:

提交时使用param1=aaa&param1=bbb&param1=3

接收时使用String param1[] 这种参数既可以获取数组的值

示例:

//3.自动参数映射数组数据类型
    @RequestMapping("/act03")
    public String act03(Model model,Integer[] id){
        model.addAttribute("msg",Arrays.toString(id));
        return "hi";
    }

SpringMVC(六)处理请求2.0
方法二:

提交时使用param1=aaa&param1=bbb&param1=3

接收时使用List param1 这种参数既可以获取数组的值
示例:

POJO Car.java

import java.util.ArrayList;
import java.util.List;

/**车*/
public class Car {
    /**编号*/
    private int id;
    /**名称*/
    private String name;
    /**价格*/
    private double price;
    /**尺寸*/
    private Size size;

    private List<Integer> ids;
    public List<Integer> getIds() {
        return ids;
    }

    public void setIds(List<Integer> ids) {
        this.ids = ids;
    }

    public Car(int id, String name, double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    public Car() {
    }

    public Size getSize() {
        return size;
    }

    public void setSize(Size size) {
        this.size = size;
    }

    public static List<Car> getCars() {
        return cars;
    }

    public static void setCars(List<Car> cars) {
        Car.cars = cars;
    }

    public int getId() {
        return id;
    }

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

    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;
    }

    @Override
    public String toString() {
        return "Car{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", price=" + price +
                ", size=" + size +
                ", ids=" + ids +
                '}';
    }

    public static List<Car> cars=new ArrayList<>();
    static {
        cars.add(new Car(101,"朗逸",16.59));
        cars.add(new Car(102,"菲斯塔",15.50));
        cars.add(new Car(103,"雅阁",25.98));
        cars.add(new Car(104,"卡罗拉",17.58));
        cars.add(new Car(105,"轩逸",16.15));
    }
}

action

@RequestMapping("/act02")
    public String act02(Model model,Car car){
        model.addAttribute("msg",car);
        return "hi";
    }

SpringMVC(六)处理请求2.0
(2)List集合类型
不能直接在action的参数中指定List类型,定义一个类型包装List集合在其中,ProductList类如下所示:

import java.util.List;

//产品集合
public class ProductList {
    private List<Product> items;

    public List<Product> getItems() {
        return items;
    }

    public void setItems(List<Product> items) {
        this.items = items;
    }
}

 // 集合类型
    @RequestMapping("/action03")
    public String action03(Model model, ProductList products) {
        model.addAttribute("message", products.getItems().get(0) + "<br/>" + products.getItems().get(1));
        return "foo/index";
    }

SpringMVC(六)处理请求2.0
这里同样可以使用一个表单向服务器提交数据。

TomCat高版本可能会产生如下错误:

java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
    at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:479)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:684)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:806)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

Get请求新的安全规范要求URL中不能直接带[],如下所示:

25-Oct-2018 14:12:09.277 警告 [http-nio-8080-exec-2] org.apache.tomcat.util.http.parser.HttpParser.<clinit> Character [,] is not allowed and will continue to be rejected

解决办法(四种):

1、替换url请求。不用{}[]特殊字符! * ’( ) ; : @ & = + $ , / ? # [ ])

2、对请求编码解码。 UrlDecode、UrlEncode

3、配置Tomcat对字符的支持:

3.1、更换Tomcat版本 (注,Tomcat从 7.0.73, 8.0.39, 8.5.7 版本后添加了对Url的限制。)

3.2、配置tomcat支持|{}等字符的方法是:

在 conf/catalina.properties 中最后添加一行:

org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true

tomcat.util.http.parser.HttpParser.requestTargetAllow=|{}[]

注3.2这种方法从8.5以后就被放弃的了,新的方法如下:

tomcat.util.http.parser.HttpParser.requestTargetAllow is deprecated since Tomcat 8.5: tomcat official doc.

You can use relaxedQueryChars / relaxedPathChars in the connectors definition to allow these chars: tomcat official doc.

修改conf/server.xml文件,如下所示:

<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" URIEncoding="utf-8" relaxedQueryChars="],["/>

(3)Map集合类型
Map与List的实现方式基本一样,这里先定义了一个包装Map的类型ProductMap,代码如下所示:

/**
 * * 产品字典
 */
public class ProductMap {
    private Map<String, Product> items;

    public Map<String, Product> getItems() {
        return items;
    }

    public void setItems(Map<String, Product> items) {
        this.items = items;
    }
}
Action的定义如下:
    // Map类型
    @RequestMapping("/action04")
    public String action04(Model model, ProductMap map) {
        model.addAttribute("message", map.getItems().get("p1") + "<br/>" + map.getItems().get("p2"));
        return "foo/index";
    }

SpringMVC(六)处理请求2.0