超级赞!SpringMVC中的请求参数的完美处理技巧~

Java技术迷

共 6574字,需浏览 14分钟

 ·

2021-08-19 12:20

点击关注公众号,Java干货及时送达

Java技术迷 | 出品

本篇文章我们来学习一下SpringMVC中是如何处理请求中的参数的。

回想一下原生Servlet是如何处理请求参数的?我们需要使用HttpServletRequest调用getParameter方法进行获取,就像这样:

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取参数值
String username = req.getParameter("username");
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}

下面来看看SpringMVC是如何处理这一需求的。

@RequestParam

在SpringMVC中,我们可以直接在方法上声明入参获取请求参数,比如:

@Controller
public class HelloController {

@RequestMapping("/hello")
public String hello(String username) {
System.out.println(username);
return "success";
}
}

那在传递参数的时候参数名就必须指定为username,这样处理方法就能够直接获取到请求参数,当然了,这样获取有一个弊端,就是参数名被固定了,只能是username,我们可以在参数前添加@RequestParam注解来解决:

@RequestMapping("/hello")
public String hello(@RequestParam("user") String username) {
System.out.println(username);
return "success";
}

此时参数名就可以随意定义,转而由@RequestParam注解来指定需要接收的参数名。

当请求中未携带user参数时,程序就会出错:

Resolved exception caused by handler execution: org.springframework.web.bind.MissingServletRequestParameterException: Required String parameter 'user' is not present

这是因为@RequestParam默认要求参数必须携带,否则就会报错,可以通过修改注解中的required属性值来解决这一个问题:

@RequestMapping("/hello")
public String hello(@RequestParam(value = "user",required = false) String username) {
System.out.println(username);
return "success";
}

此时无论是否携带user参数,程序都不会出错,当未携带user参数时,username值为null。

还可以通过配置defaultValue属性值来指定当参数未携带时的默认值:

@RequestMapping("/hello")
public String hello(@RequestParam(value = "user",required = false,defaultValue = "zhang") String username) {
System.out.println(username);
return "success";
}

此时当请求未携带user参数时,username值为 zhang  。

@RequestHeader

SpringMVC中也能非常方便地获取请求头中的信息,如:

@RequestMapping("/hello")
public String hello(@RequestHeader("User-Agent") String userAgent) {
System.out.println(userAgent);
return "success";
}

通过@RequestHeader注解即可轻松获取请求头信息,其value值为请求头的key,和@RequestParam注解类似,当试图去获取一个不存在的请求头时,程序便会报错:

@RequestMapping("/hello")
public String hello(@RequestHeader("test") String userAgent) {
System.out.println(userAgent);
return "success";
}

报错信息为:

Missing request header 'test' for method parameter of type String

所以也可以在注解中添加required属性来解决:

@RequestMapping("/hello")
public String hello(@RequestHeader(value = "test",required = false) String userAgent) {
System.out.println(userAgent);
return "success";
}

defaultValue属性也是一样的用法。

@RequestBody

在前后端分离的项目开发中,后端接收到的往往并不是一个直接的字符参数,而是一串JSON数据,那么该如何处理JSON类型的请求参数呢?

其实很简单,先接收到JSON参数,再通过一些第三方库将JSON解析成正常的属性值即可,而在SpringMVC中,可以直接使用@RequestBody注解来解决:

@RequestMapping("/hello")
public String hello(@RequestBody String json) {
System.out.println(json);
return "success";
}

通过这种方式能够获取到前端提交的JSON参数:

{"name:"张三","age":"20"}

你还可以直接将请求参数中的JSON串转换为Bean对象:

@RequestMapping("/hello")
public String hello(@RequestBody Person person) {
System.out.println(person);
return "success";
}

此时SpringMVC将按照参数名和Person对象中的属性名进行一一对应,并将参数值封装到Person中生成一个对象,这样便极大地方便了开发流程。

@CookieValue

通过@CookieValue注解可以很方便地获取到请求中的cookie信息:

@RequestMapping("/hello")
public String hello(@CookieValue("_ga") String ga) {
System.out.println(ga);
return "success";
}

同理,若是获取不存在的cookie,也会出现错误,解决方案和前面是一样的,就不再赘述了。

传入对象类型

当请求参数较为复杂时,比如一个对象,如果借助@RequestParam注解,就必须这样:

@RequestMapping("/hello")
public String hello(
@RequestParam("name") String name,
@RequestParam("age") Integer age,
@RequestParam("sex") Character sex,
@RequestParam("address") String address
) {
System.out.println(name);
System.out.println(age);
System.out.println(sex);
System.out.println(address);
return "success";
}

并且随着参数的增多,这种冗余的代码还要继续编写,为此,SpringMVC有一个更加优雅的解决方案,就是直接接收一个对象类型的参数,所以,要先将这些参数封装成一个对象:

@Data
@ToString
public class Person {
private String name;
private Integer age;
private Character sex;
private String address;
}

此时方法中只需接收一个Person类型的参数即可:

@RequestMapping("/hello")
public String hello(Person person) {
System.out.println(person);
return "success";
}

它同时还支持级联封装,如:

@Data
@ToString
public class Person {
private String name;
private Integer age;
private Character sex;
private Address address;
}

@Data
@ToString
public class Address {
private String province;
private String city;
}

现在Person对象中的地址属性仍然是一个对象,SpringMVC仍然能够将数据准确无误地封装到Person参数中,但请求参数在传递时就需要通过 . 来进行传送,比如:

http://localhost:8080/hello?name=zhangsan&sex=f&age=20&address.province=jiangxi&address.city=nanchang

需要注意的是请求参数中的参数名必须和对象中定义的属性名一致。

传入原生API

有时候一些需求也不得不使用到原生的API,比如设置cookie、session等,SpringMVC当然也考虑到了这一点,所以若是想使用原生的API,则直接写到方法的入参中即可,如:

@RequestMapping("/hello")
public String hello(HttpServletResponse response) {
Cookie cookie = new Cookie("test", "test");
response.addCookie(cookie);
return "success";
}

想操作Session,就将HttpSession作为参数传入:

@RequestMapping("/hello")
public String hello(HttpSession session) {
session.setAttribute("test","test");
return "success";
}

SpringMVC支持以下九个ServletAPI的对象:

1.HttpServletRequest2.HttpServletResponse3.HttpSession4.java.security.Principal5.Locale6.InputStream7.OutputStream8.Reader9.Writer

这九个对象都能够直接以参数的形式传入方法中。

解决乱码问题

如果在发送请求时携带的参数是中文的,就会产生乱码,在原生的Servlet开发中,我们通常使用:

request.setCharacterEncoding("UTF-8");

但这是用来解决POST请求乱码的,对于响应的乱码,应使用:

response.setContentType("text/html;charset=utf-8");

然而在SpringMVC中,我们通常不会使用到HttpServletRequest和HttpServletResponse对象,那么乱码问题该如何解决呢?

可以定义一个Filter过滤器,来拦截所有请求,并在过滤器中集中处理乱码的问题,SpringMVC已经考虑到了这一点,并为我们提供了一个专门解决乱码问题的过滤器CharacterEncodingFilter,只需在web.xml文件中进行配置:

<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>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

注意:若项目中配置了多个Filter,则CharacterEncodingFilter一定要配置在其它Filter之前。

以上便是有关SpringMVC中处理请求参数的全部内容!

本文作者:汪伟俊 为Java技术迷专栏作者 投稿,未经允许请勿转载。

1、 19 张图让你秒懂 Spring Cloud 全家桶!

2、 10 款牛哄哄的 Chrome 插件,你用了几个?

3、 在 IntelliJ IDEA 中这样使用 Git,贼方便了!

4、计算机时间到底是怎么来的?程序员必看的时间知识!

5、这些IDEA的优化设置赶紧安排起来,效率提升杠杠的!

6、和100位00后聊完,我明白了为什么还有6亿中国人仍不放弃QQ

7、真香!用 IDEA 神器看源码,效率真高!

点分享 

点收藏 

点点赞 

点在看

浏览 86
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报