1.获取原生ServletAPI
原生的Servelt通过HttpServletRequest为后台发送数据,通过HttpServletResponse获取处理后的数据
代码实践
1)网页部分
网页发起目标路径访问请求
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<!--获取servlet原生api-->
<a href="hello5">获取servlet原生api</a>
</body>
</html>
2)处理器部分
@RequestMapping(path="/hello5")
public String sayHello5(HttpServletRequest request, HttpServletResponse response){
System.out.println("request:"+request);
System.out.println("==========================");
HttpSession session = request.getSession();
System.out.println("session:"+session);
System.out.println("==========================");
ServletContext context = session.getServletContext();
System.out.println("context:"+context);
System.out.println("==========================");
System.out.println("response:"+response);
return "success";
}
2.常用注解
2.1RequestParam
作用:把请求中指定名称的参数给控制器中的形参赋值
属性:
- value/name:请求中的参数名
- required:请求中是否必须提供此参数,默认为true,不提供则报错
示例
前面一开始我们提到的例子必须是前端name与形参名必须一致,但有时我们因为某些原因不会统一,这时需要用到requestParam注解
1)网页部分:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<!--@RequestParam-->
<a href="hello6?name='哈哈'">@RequestParam传递</a>
</body>
</html>
2)控制器部分:
@RequestMapping(path="/hello6")
public String sayHello6(@RequestParam(value = "name") String username){
System.out.println(username);
return "success";
}
3)结果显示:
注意:从上述例子来看,前端传来的数据名为name,但是后台接收的形参名为username,通过@RequestParam我们可以将使两个不同名的值完成传值
2.2 RequestBody
作用:用于获取请求体内容,直接得到的是key=value&key=value...结构的数据(get请求方法不适用)
相当于直接将表单中的请求参数全部封装到一条字符串中。
什么时候用的到:我们请求中有个概念叫做异步,异步请求需要用到json数据格式
属性:
- required:是否必须有请求体(默认为true,true时get请求会报错,flase则不报错但是为null)
get的请求参数全部被封装到地址后,并没有请求体
示例
1)网页部分:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<!--@RequestBody-->
<form action="testRequestBody" method="post">
姓名<input type="text" name="name"/><br/>
年龄<input type="text" name="age" />
<input type="submit" />
</form>
</body>
</html>
2)控制器部分:
/**
* @Description: 测试RequestBody
* @Param: [body]
* @return: java.lang.String
* @Author: XHY
* @Date: 2020/4/28
*/
@RequestMapping("/testRequestBody")
public String testRequestBody(@RequestBody String body){
System.out.println(body);
return "success";
}
3)结果显示:
2.3 PathVariable
作用:绑定URL中的占位符。例如url中有个/delete/{id} (url中出现占位符是rest风格URL)
属性:
- value:指定url中的占位符名称
- required:是否必须提供占位符
示例
1)网页部分:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<!--@PathVariable-->
<a href="testPathVariable/hehe/31">PathVariable1</a>
</body>
</html>
2)控制器部分:
/**
* @Description: 测试PathVariable
* @Param: [name, age]
* @return: java.lang.String
* @Author: XHY
* @Date: 2020/4/28
*/
@RequestMapping("/testPathVariable/{name}/{age}")
public String testPathVariable(@PathVariable("name") String name,@PathVariable("age") int age){
System.out.println(name+"/"+age);
return "success";
}
3)结果显示:
2.3.1 REST风格URL
REST(representation State Transfer)(也被成为restful)
与原有请求方式不同,我们Springmvc通过为不同控制器类的不同方法设置不同的请求路径来区分我要向那个方法发起请求,但restful不同,它将所有请求方法设置为一样的请求路径,那么我们如何区分我该向那个方法发起请求呢,我们通过设置不同方法获取请求的方式如get/post/put以及请求路径后所带的占位符,通过请求方式与后者所跟占位符名的不同我们来区分要调用哪个处理器方法。
再细致一些,比如我们有两个方法,一个有参数叫id,另一个无参,他们的请求方式相同但是我们通过requestPath/{id}与requestPath来区分我们要调用哪个方法。
优点:结构清晰、符合标准、易于理解、拓展方便、更利于缓存。
2.3.2 HiddentHttpMethodFilter
作用:由于浏览器表单只支持get/post请求,delete/put等并不支持,spring3.0增加了一个过滤器HiddentHttpMethodFilter,可以将浏览器请求方式更改为指定方式来发送给我们的控制器方法
使用方法:
- 在web.xml中配置该过滤器
- 该方式必须使用post请求
- 按照要求提供_method请求参数,该参数就是我们需要指定的请求方式
这中方式相对繁琐,暂未学习,而且后面可以通过类似webClient代替这样的请求修改方式。所以这里暂不做描述。
2.4 RequestHeader
作用:获取请求中的消息头
属性:
- value:提供消息头名称
- required:是否必须提供此消息头
注:实际开发中并不常用
示例
1)网页部分:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<!--@RequestHeader-->
<a href="testRequestHeader">RequestHeader</a>
</body>
</html>
2)控制器部分:
/**
* @Description: 测试RequestHeader
* @Param: [accept]
* @return: java.lang.String
* @Author: XHY
* @Date: 2020/4/29
*/
@RequestMapping("/testRequestHeader")
public String testPathVariable(@RequestHeader("accept") String accept){
System.out.println(accept);
return "success";
}
3)结果显示:
2.5 Cookie Value
作用:将指定cookie名称的值传入控制器参数
属性:
- value:指定cookie名称
- required:是否必须提供此cookie
示例
1)网页部分:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<!--@RCookieValue-->
<a href="testCookieValue">CookieValue</a>
</body>
</html>
2)控制器部分:
/**
* @Description:
* @Param: [cookieValue]
* @return: java.lang.String
* @Author: XHY
* @Date: 2020/4/29
*/
@RequestMapping("/testCookieValue")
public String testCookieValue(@CookieValue("JSESSIONID") String cookieValue){
System.out.println(cookieValue);
return "success";
}
3)结果显示:
2.6 ModelAttribute
作用:用去修饰方法和参数
- 出现在方法上表示此方法会在控制器方法执行前执行;
- 出现在参数上表示获取指定的数据给参数赋值
属性:
- value:用于获取数据的key
应用场景:当表单提交的数据不是完整的实体类数据时,保证没有提交的字段使用数据库对象原来的数据。
举例:当我有一个用户类,用户类有id、姓名、年龄三个属性,但我在前端页面上只写了id和name两个属性,传给处理器时,会默认被null。但是我们希望这个年龄可以根据我们输入的id与姓名去数据库中查询出来封装进去。所以我们可以通过@ModelAttribute在方法执行前直接通过id去调用进行填充并返回完整对象。
示例
1)网页部分:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<!--@ModelAttribute-->
<form action="testModelAttribute">
姓名<input type="text" name="name"/><br/>
<input type="submit" />
</form>
</body>
</html>
2)控制器部分:
①有返回值写法
/**
* @Description: 测试ModelAttribute
* @Param: [user]
* @return: java.lang.String
* @Author: XHY
* @Date: 2020/4/29
*/
@RequestMapping("/testModelAttribute")
public String testModelAttribute(User user){
System.out.println(user);
return "success";
}
/**
* @Description:
* @Param: [name]
* @return: com.pojo.User
* @Author: XHY
* @Date: 2020/4/29
* @notice:形参的名字必须与前端页面提交的字段名一致,不能像处理器那样直接写个自定义对象,
* 因为在处理器的形参中,核心控制器会为器注入对象,但是在ModelAttribute方法中并不会,如
* 果你也写User user2这样的形参,那么这个ModelAttribute方法会由于参数对应不上而被跳过
*/
@ModelAttribute
public User completeUser(String name){
User user = new User();
user.setName(name);
user.setAge(33);
return user;
}
② 无返回值写法
/**
* @Description: 测试ModelAttribute
* @Param: [user]
* @return: java.lang.String
* @Author: XHY
* @Date: 2020/4/29
*/
@RequestMapping("/testModelAttribute")
public String testModelAttribute(@ModelAttribute("abc") User user){
System.out.println(user);
return "success";
}
@ModelAttribute
public void completeUser(String name, Map<String,User> map){
User user = new User();
user.setName(name);
user.setAge(33);
map.put("abc",user);
}
3)结果显示:
2.7 SessionAttribute
作用:用于多次执行控制器方法间的参数共享(只能作用在类上)
属性:
- value:用于指定存入的属性名称
- type:用于指定存入的数据类型
注:我们原来如果需要在页面直接传递数据需要通过在request域中进行数据的存取来达到传递目标,但是这是一个原生的ServletAPI。如果使用它就会与Servelt产生过高的耦合度,也就是如果我们没有引入servlet的jar包我们甚至连编译都无法通过。因此这里引入了Model来解决这个问题(Model由于继承了LinkdeHashMap所以其实它本质上是一个map键值对集合),通过向model中添加键值对也就是向request域中添加数据。而我们如果需要在多个方法调用同一个参数那么需要这个参数在我们的session域中,我们的@SessionAttribute则可以在session域声明这么一个参数。当声明这个注解后,我们在model中加入属性如果与seesion属性名相同,也会存储到session域中。我们通过ModelMap获取我们在session中添加的属性。
示例
1)网页部分:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<!--@SeesionAttribute-->
<a href="testSessionAttribute">putgogogogo</a>
<a href="getSessionAttribute">getgogogogo</a>
<a href="deleteSessionAttribute">deletegogogogo</a>
</body>
</html>
2)控制器部分:
@Controller
@SessionAttributes(value = {"msg"})
public class controllerHelloController {
/**
* @Description: 向request域与session域中放入msg属性
* @Param: [model]
* @return: java.lang.String
* @Author: XHY
* @Date: 2020/4/29
*/
@RequestMapping("/testSessionAttribute")
public String testSessionAttribute(Model model){
model.addAttribute("msg","gogogogogo");
return "success";
}
/**
* @Description: 获取session域中的msg
* @Param: [modelMap]
* @return: java.lang.String
* @Author: XHY
* @Date: 2020/4/29
*/
@RequestMapping("/getSessionAttribute")
public String getSessionAttribute(ModelMap modelMap){
String str = (String)modelMap.get("msg");
System.out.println(str);
return "success";
}
/**
* @Description: 清除两个域中的值
* @Param: [status]
* @return: java.lang.String
* @Author: XHY
* @Date: 2020/4/29
*/
@RequestMapping("/deleteSessionAttribute")
public String deleteSessionAttribute(SessionStatus status){
status.setComplete();
return "success";
}
}