SpringMVC请求参数

SpringMVC请求参数

一、概述

二、请求方式

RequestMapping可以由于所以请求,可以用在类上面,这些它下面的方法都要进行拼接路径,当然GetMapping也可以用在类上面,这样就指定了下面所有方法的请求方式了。

这是RequestMapping源码:

java 复制代码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.web.bind.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
    String name() default "";

    @AliasFor("path")
    String[] value() default {};

    @AliasFor("value")
    String[] path() default {};

    RequestMethod[] method() default {};

    String[] params() default {};

    String[] headers() default {};

    String[] consumes() default {};

    String[] produces() default {};
}

path与value等价, RequestMethod是枚举类型:

java 复制代码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.web.bind.annotation;

public enum RequestMethod {
    GET,
    HEAD,
    POST,
    PUT,
    PATCH,
    DELETE,
    OPTIONS,
    TRACE;

    private RequestMethod() {
    }
}
java 复制代码
package com.itheima.controller;

import com.itheima.service.QuickService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

//定义成为Bean
@Controller
@RequestMapping("/aaa")
public class QuickController2 {
//    注入配置好的Service
//    @Autowired
//    private QuickService quickService;
    //这是映射地址
//    @RequestMapping(value = {"/quick","/quickxxx","/quickyyy"},method = RequestMethod.GET)
    @GetMapping(value = {"/quick","/quickxxx","/quickyyy"})
    public String quick()
    {
        System.out.println("quick is running");
        return "/index.jsp";
    }
}

三、数据传递

3.1基本传输形式

java 复制代码
package com.itheima.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itheima.pojo.User;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;

@Controller
public class ParamController2 {
//    正常访问,客户端与服务端参数匹配时
//http://localhost/param1?username=zhangsan&age=18
@RequestMapping("/param1")
public String param1(String username,int age){
    System.out.println(username+"===="+age);
    return "/index.jsp";
}

//    客户端与服务端名字不匹配是使用@RequestParam注解且指定对应的客户端参数名
    //http://localhost/param1?username=zhangsan&age=18
    @RequestMapping("/param2")
    public String param2(@RequestParam("username") String name,int age){
        System.out.println(name+"===="+age);
        return "/index.jsp";
    }
    //多个值时
    //    使用数组进行接收
    //http://localhost/param3?hobby=zq&hobby=pq&hobby=tq
    @RequestMapping("/param3")
    public String param3(String hobby[]){
        for (String s : hobby){
            System.out.println(s);
            }
        return "/index.jsp";
        }
    //使用List进行接收,由于SpingMVC会把List当成一个对象,创建对象进行封装,然后List是一个接口无法创建对象,所以我们要使用@RequestParam来告诉SpringMVC我们只想简单的封装
    @RequestMapping("/param4")
    public String param4(@RequestParam List<String>hobby){
        for (String s : hobby){
            System.out.println(s);
        }
        return "/index.jsp";
    }
    //    使用Map进行封装也是要加@RequestParam以表明这与客户端的参数对应,因为Map无法在名字上与多个变量进行对应
//    http://localhost/param5?username=zhangsan&age=18
    @RequestMapping("/param5")
    public String param5(@RequestParam Map<String,String>map){
        map.forEach((k,v)->{
            System.out.println(k+"=="+v);
        });
        return "/index.jsp";
    }
}

map传输是这样的,对应参数对应要求不高:

然后下面再补充几个属性:required是表示是否必须传输,默认是false的,然后还可以通过defaultValue指定默认值

java 复制代码
@RequestMapping("/param1")
public String param1(@RequestParam(required = true,defaultValue = "mm") String username,Integer age){
    System.out.println(username+"===="+age);
    return "/index.jsp";
}

同时int是基本类型不能为空,为空的话会报错:

改为Integer即可。

3.2封装为实体类传输

java 复制代码
package com.itheima.pojo;

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

public class User {

    private String username;
    private Integer age;
    private String[] hobbies;
    private Date birthday;
    private Address address;

    public String getUsername() {
        return username;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public String[] getHobbies() {
        return hobbies;
    }

    public void setHobbies(String[] hobbies) {
        this.hobbies = hobbies;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", age=" + age +
                ", hobbies=" + Arrays.toString(hobbies) +
                ", birthday=" + birthday +
                ", address=" + address +
                '}';
    }
}
java 复制代码
package com.itheima.pojo;

public class Address {

    private String city;
    private String area;

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getArea() {
        return area;
    }

    public void setArea(String area) {
        this.area = area;
    }

    @Override
    public String toString() {
        return "Address{" +
                "city='" + city + '\'' +
                ", area='" + area + '\'' +
                '}';
    }
}
java 复制代码
//    封装到实体当中,SpringMVC框架调用底层的set方法来进行反射
//    //http://localhost/param6?username=zhangsan&age=18&hobbies=zq&hobbies=pq&birthday=2018/11/11&address.city=tj&address.area=bh
@RequestMapping("/param6")
public String param6(User user){
    System.out.println(user);
    return "/index.jsp";

要是对象里面有对象像address一样,使用"实体类.属性"形式传输。

3.3 使用@RequestBody注解接收客户端传过来的JSON格式的字符串数据(封装为请求体)

3.3.1直接保留字符串形式
java 复制代码
@PostMapping("/param8")
    public String param8(@RequestBody String body){
        System.out.println(body);
        return "/index.jsp";
    }


当然我们也可以将客户端传递过来的JSON字符串转化为对象:

3.3.2将客户端传递过来的JSON字符串转化为对象
java 复制代码
 //    将客户端传递过来的JSON数据的请求体转化为为一个对象
    @PostMapping("/param9")
    public String param9(@RequestBody String body) throws JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        User user = objectMapper.readValue(body, User.class);
        System.out.println(user);
        return "/index.jsp";
    }

那如果每次都要写" ObjectMapper objectMapper = new ObjectMapper();User user = objectMapper.readValue(body, User.class);"势必会造成高耦合,所以我们直接配置RequestMappingHandlerAdapter的MappingJackson2HttpMessageConverter是实现JSON数据的请求体自动转化为为一个对象:

java 复制代码
//    配置RequestMappingHandlerAdapter的MappingJackson2HttpMessageConverter是实现JSON数据的请求体自动转化为为一个对象
    @PostMapping("/param10")
    public String param10(@RequestBody User user){
        System.out.println(user);
        return "/index.jsp";
    }

前面我们也学过配置SpringMVC的那几大组件(在SpringMVC的配置文件中进行配置),如果不配置的话会默认加载,因为我们要使用到一些属性,默认加载的没有,所以我们自己进行配置,RequestMappingHandlerAdapter有这样的属性:

java 复制代码
private List<HttpMessageConverter<?>> messageConverters = new ArrayList(4);

然后配置其中的MappingJackson2HttpMessageConverter即可:

java 复制代码
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
            </list>
        </property>
    </bean>

这样就可以自动转换了:

四、Restful风格传输数据

Rest(Representational State Transfer)表象化状态转变(表述性状态转变),在 2000 年被提出,基于 HTTP、URL、xml、JSON 等标准和协议,支持轻量级、跨平台、跨语言的架构设计。是 Web 服务的一种新网络应用程序的设计风格和开发方式。


使用Restful风格来进行Get请求:

需要使用@PathVariable注解来将URL中的参数名与代码中的参数名进行映射:

java 复制代码
//    使用Restful风格完成get请求,参数加在后面加占位符,而且前面的必须是名词
    @GetMapping("/user/{id}/{yyy}")
    public String findUserById(@PathVariable("id") String id,@PathVariable("yyy") String xxx){
        System.out.println("id:"+id);
        System.out.println("xxx:"+xxx);
        return "/index.jsp";
    }

五、文件上传

客户端要求:

(如果客户端不选择格式的话默认是EnCoding的格式)

服务端要求:

由于映射器适配器需要文件上传解析器,而该解析器默认未被注册,所以手动注册:

java 复制代码
<!--配置文件上传解析器,注意:id的名字是固定写法-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>

而 CommonsMultipartResolver 底层使用的 Apache 的是 Common-fileupload 等工具 API 进行的文件上传,所以还要导入坐标:

java 复制代码
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>

来测试一下吧:

java 复制代码
 //    实现文件上传功能
//    前端使用POST请求,且是MultyForm
//    后端使用 MultipartFile接收(与前端同名)
    @PostMapping("/param11")
    public String param11(@RequestBody MultipartFile myfile){
        System.out.println(myfile);
        return "/index.jsp";
    }


可以了。

当然还可以补充CommonsMultipartResolver属性:

java 复制代码
<!--配置文件上传解析器,注意:id的名字是固定写法-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="defaultEncoding" value="UTF-8"/><!--文件的编码格式 默认是ISO8859-1-->
    <property name="maxUploadSizePerFile" value="1048576"/><!--上传的每个文件限制的大小 单位字节-->
    <property name="maxUploadSize" value="3145728"/><!--上传文件的总大小-->
    <property name="maxInMemorySize" value="1048576"/><!--上传文件的缓存大小-->
</bean>

文件保存:

java 复制代码
@PostMapping("/param11")
    public String param11(@RequestBody MultipartFile myfile) throws IOException {
        System.out.println(myfile);
//        实现文件的保存
//        获取输入流
        InputStream inputStream = myfile.getInputStream();
//        定义输出流
        OutputStream outputStream = new FileOutputStream("C:\\Users\\PFR\\Desktop\\MM\\"+myfile.getOriginalFilename());
//        执行文件复制
        IOUtils.copy(inputStream,outputStream);

//        关闭流
        inputStream.close();
        outputStream.close();
        return "/index.jsp";
    }

文件复制实际上是我们之前导入的CommonsMultipartResolver带的org.apache.commons.io包:

六、获取请求头和Cookie的信息

6.1获取请求头

java 复制代码
//    获取请求头的信息
//    获取单个请求头
    @GetMapping("/param12")
    public String param12(@RequestHeader("accept-encoding") String requestHeader){
        System.out.println(requestHeader);
        return "/index.jsp";
    }

获取所有请求头的信息使用Map接收:

java 复制代码
//    获取所有请求头(使用Map容器进行接收)
@GetMapping("/param13")
public String param13(@RequestHeader Map<String,String>requestHeader){
    requestHeader.forEach((k,v)->{
        System.out.println(k+"=>"+v);
    });
    return "/index.jsp";
}

6.2获取Cookie信息

java 复制代码
//  获取Cookie的信息
    @GetMapping("/param14")
    public String param14(@CookieValue(value = "JSESSIONID",defaultValue = "") String jsessionid){
        System.out.println(jsessionid);
        return "/index.jsp";
    }

七、直接获取Request和session域中的数据

java 复制代码
//    直接获取Request和session域中的数据
        @GetMapping("/request1")
        public String Request1(HttpServletRequest httpServletRequest){
        //    向 Request域中存储数据
            httpServletRequest.setAttribute("name","mm");
            return "/request2";
        }
        //    接收数据
        @GetMapping("/request2")
        public String Request2(@RequestAttribute("name") String name){
            //    向 Request域中存储数据
            System.out.println(name);
            return "/index.jsp";
    }


当然@SessionAttribute也是同理。

八、在SpringMVC框架获取JavaWeb的常用对象------Resquest和Response

java 复制代码
//    在SpringMVC框架获取JavaWeb的常用对象------Resquest和Response
    @GetMapping("/param15")
    public String param15(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse){
        System.out.println(httpServletRequest);
        System.out.println(httpServletResponse);
        return "/index.jsp";
    }
相关推荐
用户962377954485 分钟前
原理分析 | 反序列化内存马 —— CC2 + Tomcat三种组件 + 无文件落地
后端
dEso RSET7 分钟前
Skywalking介绍,Skywalking 9.4 安装,SpringBoot集成Skywalking
spring boot·后端·skywalking
ROLL.78 分钟前
同步与异步
android·java
青槿吖8 分钟前
告别RestTemplate!Feign让微服务调用像点外卖一样简单
java·开发语言·分布式·spring cloud·微服务·云原生·架构
MacroZheng10 分钟前
横空出世!IDEA最强Spring插件来了,让你的开发效率成倍提升!
java·spring boot·后端
6Hzlia11 分钟前
【Hot 100 刷题计划】 LeetCode 155. 最小栈 | C++ 打包状态法 (最优雅的 O(1) 检索)
java·c++·leetcode
用户0953675158311 分钟前
Go :如何声明变量(var)与常量(const)
后端·go
2501_9130613411 分钟前
网络原理之HTTP(2)
java·网络协议
NEGl DRYN12 分钟前
Spring Boot 3.3.4 升级导致 Logback 之前回滚策略配置不兼容问题解决
java·spring boot·logback
MeAT ITEM15 分钟前
net.sf.jsqlparser.statement.select.Select.getSelectBody()
java