请求处理
三种注解
RequestParam 获取请求参数
/**
* 默认情况下函数参数就是需要获取的字段值,若不传值则为null
* 当请求信息里面的字段与需要获取的字段名称不一样时,则可使用@RequestParam("user")注解来获取值,这种情况下
* 必须传递值,否则报错
* RequestParam注解属性
* * value:指定获取的参数key
* * required 是否必须传值,默认是true
* * defaultValue:默认值
* 注意区分:
*
* @RequestParam("user")
* @PathVariable("user") /book/{user}?user=zhangsan
*/
@RequestMapping("/handle01")
public String handle01(@RequestParam("user") String username) {
System.out.println(username);
return "success";
}
RequestHeader 获取请求头参数
/**
* RequestHeader:获取请求头的信息
* 用法与RequestParam类似
* 该注解的属性
* * value:指定获取的参数key
* * required 是否必须传值,默认是true
* * defaultValue:默认值
*/
@RequestMapping("/handle02")
public String handle02(@RequestHeader("User-Agent") String userAgent) {
System.out.println(userAgent);
return "success";
}
CookieValue 获取某个cookie的值
/**
* @CookieValue:获取cookie的值 用法与RequestParam类似
* 该注解的属性
* * value:指定获取的参数key
* * required 是否必须传值,默认是true
* * defaultValue:默认值
*/
@RequestMapping("/handle03")
public String handle03(@CookieValue("JSESSIONID") String JSESSIONID) {
System.out.println(JSESSIONID);
return "success";
}
POJO (Plain old Java Object) 自动封装
可以直接将请求的参数封装为POJO类
前端代码
<form action="addBook" method="post">
书名 <input type="text" name="bookName">
作者 <input type="text" name="author">
价格 <input type="text" name="prices">
库存 <input type="text" name="stock">
销量 <input type="text" name="sales">
省份 <input type="text" name="address.province">
城市 <input type="text" name="address.city">
街道 <input type="text" name="address.street">
<input type="submit">
</form>
后端代码
/**
* 如果我们请求的参数是一个POJO
* 则SpringMVC则会自动进行赋值
* 将POJO中的每个属性,从request尝试出来,并封装(当属性名相同时才可以进行封装)
* 还可以级联封装
*
* @param book
* @return
*/
@RequestMapping("/addBook")
public String addBook(Book book) {
System.out.println(book);
return "success";
}
支持原生API
- HttpServletRequest
- HttpServletResponse
- HttpSession
- java.security.Principal
- Locale:国际化有关的区域信息
- InputStream //字节流1
- OutputStream
- Reader //字符流
- Writer
乱码问题解决
- get请求
修改server.xml配置
<Connector URIEncoding="UTF-8" port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
- post请求
- 请求乱码
request.setCharacterEncoding(“UTF-8”)
可以使用 org.springframework.web.filter.CharacterEncodingFilter 在web.xml文件中进行配置,要在其他filter之前
- 请求乱码
<!--字符编码-->
<!--要在其他filter之间-->
<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>
<!--指定响应的编码-->
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- 响应乱码
response.setContentType(“text/html;charset=utf-8”)
数据输出
使用原生API
使用Map、Model或ModelMap作为函数参数
Map
直接存储值就可以
@RequestMapping("/demo01")
public String demo01(Map<Stringa, Object> map) {
System.out.println(map.getClass());
map.put("msg", "你好");
return "success";
}
Model
@RequestMapping("/demo02")
public String demo02(Model model) {
model.addAttribute("msg", "hahah");
System.out.println(model.getClass());
return "success";
}
ModelMap
@RequestMapping("/demo03")
public String demo03(ModelMap model) {
model.addAttribute("msg", "呵呵呵");
System.out.println(model.getClass());
return "success";
}
总结
- 真正执行他们的类均是class org.springframework.validation.support.BindingAwareModelMap
- 所存储的数据均存在于request域中
- 通过比较,对于以上三个方法中的BindingAwareModelMap对象不是同一个
ModelAndView
顾名思义:既包含视图数据,也包含模型数据
@RequestMapping("/demo04")
public ModelAndView demo04() {
// 构造参数是要跳转的页面
// ModelAndView modelAndView = new ModelAndView("success");
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("success");
modelAndView.addObject("msg", "你好!");
return modelAndView;
}
SessionAttributes注解
给BindingAwareModelMap或ModelAndView中保存的数据,同时也session保存一份
- value属性:指定要保存至session的数值对应的在request域中的key
- type属性:指定要保存至session的数值对应的在request域中value的类型
ModelAttributeTest注解详解
业务场景引入
以修改图书信息为例,一般图书名称是不需要修改的,但是当修改信息时,传入的图书名称是null,从而在dao层会出现异常
因此可以使用ModelAttribute注解来解决
注解思路
package pers.lele.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import pers.lele.domain.Book;
import java.util.Map;
@Controller
@RequestMapping("/book")
public class BookControl {
Object m1;
Object m2;
Object m3;
Object b1;
Object b2;
boolean flag = false;
@RequestMapping("/update")
public String updateBook(@ModelAttribute("book") Book book, ModelMap map) {
System.out.println(book);
b2 = book;
System.out.println(b1 == b2);
//SpringMVC创建一个Book对象,值默认都是null
//Book{id='100', name='null', price=12.0, sell=12}
m2 = map;
System.out.println(m2);
/*
upadte book set name = book.name , price = book.price
where id = book.id;
*/
System.out.println(m1 == m2);
return "success";
}
@ModelAttribute
public void udpateBefore(Model model) {
if (flag == false) {
Book book = new Book("100", "水浒传", 12, 65);
b1 = book;
model.addAttribute("book", book);
System.out.println("udpateBefore....");
m1 = model;
System.out.println(m1);
flag = true;
}
}
@RequestMapping("/updateplus")
public String updateplus(@ModelAttribute("name") String name,ModelMap map) {
map.addAttribute("haha","haha");
System.out.println(map.get("book"));
m3 = map;
System.out.println("updateplus");
System.out.println(m1);
System.out.println(m2);
System.out.println(m3);
System.out.println(m1 == m2);
System.out.println(m1 == m3);
return "success";
}
}
总结
被@ModelAttribute注解标志的方法会优先被执行且使用的是同一个 BindingAwareModelMap(隐式模型)