目录
一、获取请求参数
使用 @RequestParam 注解标记handler方法的形参,当请求参数名和形参名一致可以省略
@RequestMapping("/login2")
public String login2(@RequestParam("username") String uname, String password){
log.debug("username:" +uname +"password:" +password);
return "result";
}
请求参数必须 required (有则传入,没有不报错),默认required=true,请求参数必须提供
@RequestParam(value = "userName", required = false)
给请求参数设置默认值 defaultValue
@RequestParam(value = "userName", required = false, defaultValue = "missing")
1、一名一值
<h4>1.一名一值</h4>
<a href="/springmvc/user/login?username=atguigu&password=123456">登录1</a><br>
<a th:href="@{/user/login2(username=atguigu,password=123456)}">登录2</a><br>
<a th:href="@{/user/register(username=zhangsan,age=12,salary=123.45)}">注册1</a><br>
<a th:href="@{/user/register2(username='zhangsan',age=12)}">注册2</a>
@Controller
@Slf4j
@RequestMapping("/user")
public class UserController {
// 使用@RequestParam注解标记handler方法的形参
// SpringMVC 会将获取到的请求参数从形参位置给我们传进来
//登录1 (不用)
@RequestMapping("/login")
public String login(String username,String password){
log.debug("username:" +username +"password:" +password);
return "result";
}
//登录2
@RequestMapping("/login2")
public String login2(@RequestParam("username") String uname, String password){
log.debug("username:" +uname +"password:" +password);
return "result";
}
//注册1
@RequestMapping("/register")
public String register(String username,Integer age,Double salary){
log.debug("username:"+username +"age:"+age+"salary:"+salary);
return "result";
}
//注册2
@RequestMapping("/register2")
public String register2(String username,Integer age,//@RequestParam salary可以不是必须的,默认值为1000
@RequestParam(name = "salary",required = false,defaultValue = "1000") double salary){
log.debug("username:"+username +"age:"+age+"salary:"+salary);
return "result";
}
}
异常:当必须的参数没有提供,并且没有设置required
- 响应状态码:400(在 SpringMVC 环境下,400通常和数据注入相关)
- 说明信息:必需的 String 请求参数 'userName' 不存在
原因可以参考 @RequestParam 注解的 required 属性:默认值为true,表示请求参数默认必须提供。
2、一名多值 List<String>
<h3>2.获取请求参数-一名多值</h3>
<form th:action="@{/user/getTeams}" method="post">
请选择你最喜欢的球队:
<input type="checkbox" name="team" value="Brazil"/>巴西
<input type="checkbox" name="team" value="German"/>德国
<input type="checkbox" name="team" value="French"/>法国
<input type="checkbox" name="team" value="Holland"/>荷兰
<input type="checkbox" name="team" value="Italian"/>意大利
<input type="checkbox" name="team" value="China"/>中国
<br/>
<input type="submit" value="保存"/>
</form>
//一名多值
@RequestMapping("/getTeams")
public String getTeams(@RequestParam("team") List<String> teamList){
log.debug("teamList:"+teamList);
return "result";
}
3、实体类 (表单对应模型 )
<h4>3.实体类</h4>
<form action="emp/save" method="post">
姓名:<input type="text" name="empName"/><br/>
年龄:<input type="text" name="empAge"/><br/>
工资:<input type="text" name="empSalary"/><br/>
<input type="submit" value="保存"/>
</form>
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {
private Integer empId;
private String empName;
private int empAge;
private double empSalary;
}
//实体类
@RequestMapping("/addEmp")
public String addEmp1111(Employee employee123){
log.debug("Employee:"+employee123);
return "result";
}
4、实体类包含级联属性
<h4>4.实体类含级联属性</h4>
<form th:action="@{/user/addStudent}" method="post">
学成名称: <input type="text" name="stuName"><br>
学校编号: <input type="text" name="school.schoolId"><br>
学校名称: <input type="text" name="school.schoolName"><br>
课程1编号: <input type="text" name="subjectList[0].subjectId"><br>
课程1名称: <input type="text" name="subjectList[0].subjectName"><br>
课程2编号: <input type="text" name="subjectList[1].subjectId"><br>
课程2名称: <input type="text" name="subjectList[1].subjectName"><br>
课程1分数: <input type="text" name="scores['java']">
课程1分数: <input type="text" name="scores['mysql']">
<input type="submit" value="保存">
</form>
学生
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private String stuName;
private School school;
private List<Subject> subjectList;//List
//private Subject[] subjectArray;//Array
//private Set<Teacher> teacherSet;//Set ?? 不推荐使用
private Map<String, Double> scores;//Map
}
学校
@Data
@AllArgsConstructor
@NoArgsConstructor
public class School {
private Integer schoolId;
private String schoolName;
}
课程
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Subject {
private Integer subjectId;
private String subjectNAme;
}
//级联实体类
@RequestMapping("/addStudent")
public String addStudent(Student stu){
log.debug("Student:"+stu);
return "result";
}
二、获取请求头 @RequestHeader
@RequestHeader 获取请求消息头中的具体数据。
name 或 value 属性:指定请求消息头名称。
defaultValue 属性:设置默认值。
<h4>5.获取请求头</h4>
<a th:href="@{/user/getHeaders}">获取请求头</a>
//获取请求头 @RequestHeader(要获取的信息)
@RequestMapping("/getHeaders")
public String getHeaders(@RequestHeader("User-Agent") String userAgent,
@RequestHeader("Referer")String referer){
log.debug("浏览器类型:" + userAgent);
log.debug("从哪里来(上一个Url):" + referer);
return "result";
}
使用原生Servlet获取请求头:
String agent = request.getHeader("User-Agent")
三、获取指定Cookie @CookieValue
@CookieValue 获取当前请求中的 Cookie 数据。由于cookie实际上存储的是session_id,具体的数据是保存在session中,所以参数还要加上HttpSession。
name 或 value 属性:指定Cookie 名称
defaultValue 属性:设置默认值
<h4>6.获取Cookies信息</h4>
<a th:href="@{/user/getCookies}">获取Cookies信息</a>
//获取Cookies信息
@RequestMapping("/getCookies")
public String getCookies(@CookieValue(value = "JSESSIONID",defaultValue = "missing")
String sessionId, HttpSession httpSession){
log.debug("sessionId:" + httpSession);
return "result";
}
使用原生Servlet获取Cookie:
Cookie[] cookies = request.getCookies() ,再遍历集合获取内容
四、页面跳转控制
SpringMVC 框架会在前面附加 contextPath,所以我们不用添加应用路径
转发、重定向路径前添加 forward、redirect:后,路径不会再拼接前后缀(不会被thymeleaf解析)
//请求转发
//forward: 不会再追加前后缀(不会被thymeleaf解析)
@RequestMapping("/dispatcher1")
public String dispatcher1(){
log.info("---- dispatcher1 默认");
return "result"; //默认就是请求转发,自动添加前后缀
// /WEB-INF/templates/result.html
}
@RequestMapping("/dispatcher2")
public String dispatcher2(){
log.info("---- dispatcher2 forward:/WEB-INF/templates/result.html");
return "forward:/WEB-INF/templates/result.html";
}
@RequestMapping("/dispatcher3")
public String dispatcher3(){
log.info("---- dispatcher3 forward:/index.html");
return "forward:/index.html";
}
//重定向
//redirect: 不会再追加前后缀(不会被thymeleaf解析)
@RequestMapping("/redirect1")
public String redirect1(){
log.info("---- redirect1 不能访问WEB-INF ----");
return "redirect:/WEB-INF/templates/result.html";
}
@RequestMapping("/redirect2")
public String redirect2(){
log.info("---- redirect2 可以访问除WEB-INF外服务器资源 ----");
return "redirect:/index.html";
}
@RequestMapping("/redirect3")
public String redirect3(){
log.info("---- redirect3 可以重定向到互联网任意位置 ----");
return "redirect:http://www.atguigu.com";
}
复习:转发和重定向的区别
- 重定向会由浏览器发起新的请求,而请求转发不会发起新的请求。
- 重定向可以访问任意互联网资源,而请求转发只能访问本项目资源。
- 重定向不能访问本项目的WEB-INF内的资源,而请求转发可以访问本项目的WEB-INF内的资源。
- 发起重定向的资源和跳转到的目标资源没在同一次请求中,所以重定向不能在请求域中使用;而发起请求转发的资源和跳转到的目标资源在同一次请求中,所以请求转发可以在请求域中使用。
Day56.Servlet: Request、Response、获取参数、转发&重定向、书城项目二阶段_焰火青年·的博客-CSDN博客
五、获取原生 Servlet API 对象
HttpServletRequest HttpServletResponse() | HttpSession :通过参数获取
ServletContext (全局域) :自动装配、通过session获取
注意:
1、session(会话域)、application(应用域) 中传递数据,使用原生API。
2、request(请求域) 中传递数据,一般不使用原生API,而是使用下面的四种方式。
//可以自动装配全局上下文对象,已存在于IoC容器中
@Autowired//
private ServletContext servletContext;
//获取原生 ServletAPI
@RequestMapping("/getServletAPI")
public String getServletAPI(HttpServletRequest request,
HttpServletResponse response,
HttpSession session){//ServletContext 需要其他方式获取
log.info("request");
request.setAttribute("msg","username cannot be null");//请求域:当前请求
session.setAttribute("name","zhangsan");//session会话域:当前会话
response.addHeader("school","atguigu");//添加头信息
ServletContext servletContext = session.getServletContext();
servletContext.setAttribute("count",100);//全局域:当前应用
return "result";
}
result.html
获取(接收)域信息
<p th:text="${msg}"></p>
<p th:text="${user}"></p>
<p th:text="${application.count}"></p>
回顾:域对象
请求域:每一次请求都有一个请求域对象,当请求结束的时候对应的请求域对象也就销毁了
会话域:会话域是从客户端连接上服务器开始,客户端关闭,这一整个过程中发生的所有请求都在同一个会话域中;而不同的客户端是不能共用会话域的。
应用域:项目部署后只会有一个应用域对象,所有客户端都是共同访问同一个应用域对象,在该项目的所有动态资源中也是共用一个应用域对象。
六、属性域 (ModelView原理) ★ BindingAwareModelMap
我们将数据存入模型,SpringMVC 会帮我们把模型数据存入请求域,也被称为暴露到请求域。
SpringMVC 传入的 Model、ModelMap、Map类型的参数,
其实本质上都是 BindingAwareModelMap 类型的。
1、使用 Model 类型的形参
@RequestMapping("/useModel")
public String useModel(Model model){
//request.setAttribute("msg","username cannot be null"); //请求请求
model.addAttribute("msg","username cannot be null(model)");
return "result";
}
2、使用 Map 类型的形参
@RequestMapping("/useMap")
public String useMap(Map map){
//request.setAttribute("msg","username cannot be null"); //请求请求
map.put("msg","username cannot be null(map)");
return "result";
}
3、使用 ModelMap 类型的形参
@RequestMapping("/useModelMap")
public String useModel(ModelMap modelMap){
//request.setAttribute("msg","username cannot be null"); //请求请求
modelMap.addAttribute("msg","username cannot be null(modelMap)");
return "result";
}
4、使用 ModelAndView 对象
@RequestMapping("/useModelAndView")
public ModelAndView useModelAndView(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg","username cannot be null(ModelAndView)");
modelAndView.setViewName("result");
return modelAndView;
}
关于底层,Model(模型) 的本质:
使用Model、Map、ModelMap来传递数据,方法的返回值类型是String。但 SpringMVC的底层都会使用 ModelAndView 来存储数据和视图。
不是使用Model、Map、ModelMap、ModelAndView,底层都是在请求域传递数据,底层都调用了request.setAttribute(key,value)。
七、表单数据回显 (回顾Thymeleaf)
Day57.表述层(MVC)、Thymeleaf: 逻辑视图、对象图(OGNL)、分支迭代..._焰火青年·的博客-CSDN博客
Day51.HTML、标签、表单、CSS_焰火青年·的博客-CSDN博客
准备实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Tiger {
private Integer tigerId;
private String tigerName;
private Double tigerSalary;
private Season season;//季节
private List<Friend> friendList = new ArrayList<>();//朋友
}
public class Season {//季节
private Integer seasonId;
private String seasonName;
}
public class Friend {
private Integer friendId;
private String friendName;
}
1、回显简单文本标签
@Controller
@Slf4j
@RequestMapping("/tiger")
public class TigerController {
//回显文本框
@RequestMapping("/showTiger1")
public String showTIger1(Model model){
Tiger tiger = new Tiger();
tiger.setTigerId(1);
tiger.setTigerName("杰瑞");
tiger.setTigerSalary(1000.1);
model.addAttribute("tiger1",tiger);
return "tiger";
}
<h3>修改表单数据1:文本框</h3><!--文本框--><!--name:key,value:value-->
<form>
编号:<input type="text" th:value="${tiger1.tigerId}"><br>
昵称:<input type="text" th:value="${tiger1.tigerName}"><br>
薪水:<input type="text" th:value="${tiger1.tigerSalary}"><br>
<input type="submit" th:value="提交">
</form>
2、回显单选框和下拉框
关键在于页面显示,后台Controller中将数据放入Model然后转发跳转到前台页面,回显即可
单选框 th:checked 下拉列表 th:selected
//回显单选框、下拉列表
@RequestMapping("/showTiger2")
public String showTIger2(Model model){
Tiger tiger = new Tiger();
tiger.setTigerId(1);
tiger.setTigerName("杰瑞");
tiger.setTigerSalary(1000.1);
tiger.setSeason(new Season(3,"Autumn"));
//季节集合
List<Season> seasonList = new ArrayList<>();
seasonList.add(new Season(1,"Spring"));
seasonList.add(new Season(2,"Summer"));
seasonList.add(new Season(3,"Autumn"));
seasonList.add(new Season(4,"Winter"));
model.addAttribute("seasonList",seasonList);
model.addAttribute("tiger1",tiger);
return "tiger";
}
<h3>修改表单数据2:单选框 | 下拉列表</h3><!--单选框-->
<form>
编号:<input type="text" th:value="${tiger1.tigerId}"><br>
昵称:<input type="text" th:value="${tiger1.tigerName}"><br>
薪水:<input type="text" th:value="${tiger1.tigerSalary}"><br>
<!--单选框-->
季节单选框:<input type="radio" th:each="season:${seasonList}"
th:value="${season.seasonId}"
th:text="${season.seasonName}"
th:checked="${season.seasonId}==${tiger1.season.seasonId}"> <br>
<!--下拉列表-->
季节下拉框:<select>
<option th:each="season:${seasonList}"
th:value="${season.seasonId}"
th:text="${season.seasonName}"
th:selected="${season.seasonId}==${tiger1.season.seasonId}"></option> <br>
</select>
<input type="submit" th:value="提交">
</form>
3、回显多选框
//回显多选框
@RequestMapping("/showTiger3")
public String showTiger3(Model model){
Tiger tiger = new Tiger();
tiger.setTigerId(1);
tiger.setTigerName("杰瑞");
tiger.setTigerSalary(1000.1);
tiger.setSeason(new Season(3,"Autumn"));
tiger.getFriendList().add(new Friend(1,"Monkey"));
tiger.getFriendList().add(new Friend(4,"Mickey"));
model.addAttribute("tiger1",tiger);
//季节集合
List<Season> seasonList = new ArrayList<>();
seasonList.add(new Season(1,"Spring"));
seasonList.add(new Season(2,"Summer"));
seasonList.add(new Season(3,"Autumn"));
seasonList.add(new Season(4,"Winter"));
model.addAttribute("seasonList",seasonList);
//朋友集合
List<Friend> friendList = new ArrayList<>();
friendList.add(new Friend(1,"Monkey"));
friendList.add(new Friend(2,"Donkey"));
friendList.add(new Friend(3,"Turkey"));
friendList.add(new Friend(4,"Mickey"));
model.addAttribute("friends",friendList);
return "tiger";
}
<h3>修改表单数据3:多选框</h3><!--下拉框-->
<form>
编号:<input type="text" th:value="${tiger1.tigerId}"><br>
昵称:<input type="text" th:value="${tiger1.tigerName}"><br>
薪水:<input type="text" th:value="${tiger1.tigerSalary}"><br>
<!--单选框-->
季节单选框:<input type="radio" th:each="season:${seasonList}"
th:value="${season.seasonId}"
th:text="${season.seasonName}"
th:checked="${season.seasonId}==${tiger1.season.seasonId}"> <br>
<!--下拉列表-->
季节下拉框:<select>
<option th:each="season:${seasonList}"
th:value="${season.seasonId}"
th:text="${season.seasonName}"
th:selected="${season.seasonId}==${tiger1.season.seasonId}"></option>moviemgr
</select> <br>
<!--多选框-->
<input type="checkbox" th:each="friend:${friends}"
th:value="${friend.friendId}"
th:text="${friend.friendName}"
th:checked="${tiger1.friendList.contains(friend)}"> <br>
<input type="checkbox" th:each="friend:${friends}"
th:value="${friend.friendId}"
th:text="${friend.friendName}"
th:checked="${#lists.contains(tiger1.friendList,friend)}"> <br>
<input type="submit" th:value="提交">
</form>
</form>