在基于 SpringMVC 构建的 Web 应用程序中,Controller 扮演着处理 HTTP 请求的关键角色。而在实际应用中,HTTP 请求无论是 GET 请求还是 POST 请求,通常都会携带各种参数,这些参数对于服务器理解和处理请求至关重要。SpringMVC 为我们提供了多种灵活的方式来接收这些参数,本文将详细介绍其中最为常用的三种方式。
HttpServletRequest对象是 Servlet 规范中的核心对象之一,它包含了客户端请求的所有信息,包括请求参数。通过HttpServletRequest的getParameter方法,我们可以根据参数名获取对应的参数值。
假设我们有一个简单的 HTML 表单,用于提交用户的姓名和年龄:
DOCTYPE html>
<html>
<head>
<title>表单提交示例title>
head>
<body>
<form action="/userInfo" method="post">
<label for="name">姓名:label>
<input type="text" id="name" name="name" required><br>
<label for="age">年龄:label>
<input type="number" id="age" name="age" required><br>
<input type="submit" value="提交">
form>
body>
html>
对应的 Controller 代码如下:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
@Controller
public class UserController {
@RequestMapping("/userInfo")
@ResponseBody
public String getUserInfo(HttpServletRequest request) {
String name = request.getParameter("name");
String ageStr = request.getParameter("age");
int age = Integer.parseInt(ageStr);
return "姓名:" + name + ",年龄:" + age;
}
}
优点:
这种方式非常直观,对于熟悉 Servlet 规范的开发者来说容易理解和上手。
可以获取到请求中的所有信息,不仅仅是参数,还包括请求头、请求方式等,灵活性较高。
缺点:
代码较为繁琐,需要手动从HttpServletRequest对象中提取参数,并且需要进行类型转换,容易出错。
代码的可读性和维护性较差,特别是在处理大量参数时,代码会显得冗长且混乱。
这种方式是直接把HTTP请求中的参数写在控制类相应方法的形参中,通过@RequestParam注解指定接收的请求参数名。
还是以上述的 HTML 表单为例,Controller 代码可以简化为:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class UserController {
@RequestMapping("/userInfo")
@ResponseBody
public String getUserInfo(@RequestParam("name") String name,@RequestParam("age") int age) {
return "姓名:" + name + ",年龄:" + age;
}
}
在@RequestParam注解中包含三个属性:
@RequestParam(value="参数名",required="true/false",defaultValue="")
优点:
代码简洁明了,直接在方法参数中声明需要接收的参数,减少了很多样板代码。
类型转换由 SpringMVC 自动完成,减少了手动转换的错误风险,提高了开发效率。
缺点:
对于复杂的参数结构(如对象嵌套、数组等),使用方法形参接收会变得复杂,代码可读性会下降。
如果请求参数较多,方法的参数列表会变得很长,不利于维护。
当请求参数较多时,可以创建一个 Java 实体类来封装这些参数。SpringMVC 会自动将请求参数与实体类中的属性进行匹配,前提是属性名与参数名一致。这种方式利用了 JavaBean 的特性,将相关的参数组合在一起,提高了代码的可读性和维护性。
首先创建一个User实体类:
public class User {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
然后修改 Controller 代码:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class UserController {
@RequestMapping("/userInfo")
@ResponseBody
public String getUserInfo(User user) {
return "姓名:" + user.getName() + ",年龄:" + user.getAge();
}
}
优点:
代码结构清晰,将相关参数封装在一个实体类中,便于管理和维护。
对于复杂的参数结构,使用实体类接收更加直观和方便,提高了代码的可读性。
可以利用实体类的校验机制,对参数进行合法性校验。
缺点:
需要额外创建实体类,如果项目中参数类型较多,会增加一定的代码量。
对于简单的参数接收场景,使用实体类可能会显得过于繁琐。
在实际的 SpringMVC 项目开发中,选择合适的 Controller 参数接收方式至关重要。HttpServletRequest接收方式适合需要获取请求的所有信息且对灵活性要求较高的场景,但代码较为繁琐;方法形参接收方式简洁高效,适用于简单参数的接收,但对于复杂参数结构不太友好;实体类型接收方式则将参数封装在实体类中,提高了代码的可读性和维护性,适用于参数较多且结构复杂的场景。开发者应根据具体的业务需求和参数特点,合理选择参数接收方式,以提高项目的开发效率和代码质量。
Controller数据传递,指的是将Controller方法中获取到的数据传递到JSP页面中进行显示。要实现这个功能,需要依靠Servlet三大作用域来实现,作用域是服务器运行阶段在内存中开辟的空间, 用于存储数据,不同的作用域有效范围是不一样的。
作用域 | 对象类型 | 有效范围 |
---|---|---|
request(请求作用域) | HttpServletRequest | 仅在当次请求中有效 |
session(会话作用域) | HttpSession | 在当前会话中有效 |
application(应用作用域) | ServletContext | 在整个服务器运行过程中都是有效的 |
三个作用域操作通用方法:
JSP页面中可以通过EL表达式获取作用域中指定属性的值。
获取request作用域中属性的值:${requestScope.[属性名]}
获取session作用域中属性的值:${sessionScope.[属性名]}
获取application作用域中属性的值:${applicationScope.[属性名]}
也可以直接通过${[属性名]}来获取值,默认按照request–》session–》application作用域的顺序寻找对应属性的值,直到找到为止。
在Controller方法中,可以通过HttpServletRequest、Model/ModelMap/Map、ModelAndView对象将数据存储到request作用域中。
可以在Controller方法中加入一个HttpServletRequest类型的参数获取当前请求对象。
@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello(HttpServletRequest request){
request.setAttribute("username","张三");
return "hello";
}
}
SpringMVC在调用方法前会创建一个隐含的数据模型,作为模型数据的存储容器,这个隐形模型类型为BindingAwareModelMap
, SpringMVC 会帮我们把模型数据存入请求域 。BindingAwareModelMap
继承了ModelMap,实现了Model和Map接口,以下是继承关系,因此,我们可以在Controller方法中加入Model/ModelMap/Map类型的参数用来获取该模型对象。
@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello(Model model){
model.addAttribute("username","张三");
return "hello";
}
}
@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello(ModelMap model){
model.addAttribute("username","张三");
return "hello";
}
}
@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello(Map<String,Object> map){
map.put("username","张三");
return "hello";
}
}
通过创建ModelAdnView对象并返回也可以将数据存储到数据模型然后传递到View页面中。
@Controller
public class HelloController {
@RequestMapping("/hello")
public ModelAndView hello(){
ModelAndView mv=new ModelAndView();
mv.setViewName("hello");
mv.addObject("username","张三");
return mv;
}
}
可以在Controller方法中加入一个HttpSession类型的参数获取当前会话。
@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello(HttpSession session){
session.setAttribute("username","张三");
return "hello";
}
}
Tomcat服务器会为每一个Web应用创建一个ServletContext对象。这个对象全局唯一,而且Web应用 中的所有Servlet都共享这个对象。在SpringMVC框架启动后会创建IoC容器并将ServletContext放在IoC容器中,因此,我们可以通过属性注入获取该对象。
@Controller
public class HelloController {
@Autowired
private ServletContext context;
@RequestMapping("/hello")
public String hello(){
context.setAttribute("username","张三");
return "hello";
}
}
rvlet都共享这个对象。在SpringMVC框架启动后会创建IoC容器并将ServletContext放在IoC容器中,因此,我们可以通过属性注入获取该对象。
@Controller
public class HelloController {
@Autowired
private ServletContext context;
@RequestMapping("/hello")
public String hello(){
context.setAttribute("username","张三");
return "hello";
}
}