3.3 请求转发、重定向
之前的案例,我们发现request域中的值可以传到jsp页面中,也就是通过视图解析器跳转到视图的底层是请求转发。
如果我们跳转时不想使用视图解析器,可以使用原生HttpServletRequest进行请求转发或HttpServletResponse进行重定向:
1、控制器
//原生方式进行请求转发 @RequestMapping("/hello8") public void myForward1(HttpServletRequest request, HttpServletResponse response) throws Exception{ request.setAttribute("name","张三"); //请求转发 request.getRequestDispatcher("/helloMVC.jsp").forward(request,response); } //原生方式进行重定向 @RequestMapping("/hello9") public void myForward2(HttpServletRequest request,HttpServletResponse response) throws IOException { request.setAttribute("name","张三"); response.sendRedirect("helloMVC.jsp"); }
2、jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>MVC</title> </head> <body> <h1>你好啊,${requestScope.name}</h1> </body> </html>
3、访问
SpringMVC还提供了一种更简单的请求转发和重定向的写法:
@RequestMapping("/hello10") public String myForward3(HttpServletRequest request){ request.setAttribute("name","张三"); // 请求转发 return "forward:helloMVC"; // 重定向 // return "redirect:helloMVC"; }
四、SpringMVC注解
4.1 @Controller、@RequestMapping
@Controller
作用:标记控制器,将控制器交给Spring容器管理。
位置:类上方
@RequestMapping
作用:给控制器方法设置请求路径
位置:方法或类上方。用于类上,表示类中的所有控制器方法都是以该地址作为父路径。
属性:
- value/path:请求路径(只写一个属性时默认为请求路径)
- method:指定请求方式
- params:规定必须发送的请求参数
- headers:规定请求必须包含的请求头
/* 访问路径为 localhost:8080/annotation1 支持post和get请求 请求时必须带有name参数 */ @RequestMapping(path = "/annotation1", method = {RequestMethod.GET,RequestMethod.POST}, params = {"name"}) public String annotation1(String name,Map map){ map.put("name", name); System.out.println(name); return "helloMVC"; }
4.2 @RequestParam
作用:在控制器方法中获取请求参数
位置:方法参数前
属性:
- name:指定请求参数名称
- defaultValue: 为参数设置默认值
- required:设置是否是必须要传入的参数
/* 定义请求的参数名为name,默认值为张三,不是必须的参数 */ @RequestMapping("/annotation2") public String annotation2(@RequestParam(name = "name",defaultValue = "张三",required = false) String name,Map map){ map.put("name", name); return "helloMVC"; }
4.3 @ReuqestHeader、@CookieValue
@RequestHeader
作用:在控制器方法中获取请求头数据
位置:方法参数前
@CookieValue
作用:在控制器方法中获取Cookie数据
位置:方法参数前
/* 获取User-Agent请求头 获取JSESSIONID的Cookie值 */ @RequestMapping("/annotation3") public void annotation3(@RequestHeader("User-Agent") String userAgent, @CookieValue("JSESSIONID") String jSessionId){ System.out.println(userAgent); System.out.println(jSessionId); }
4.4 @SessionAttributes
作用:将Model模型中的数据存到session域中,model模型的数据域是request。
位置:类上方
@Controller @SessionAttributes("name") public class MyController { @RequestMapping("/hello") public String t1(Model model){ // model中保存name数据 model.addAttribute("name","张三"); return "helloMVC"; } }
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <html> <head> <title>MVC</title> </head> <body> <h1>你好啊,${sessionScope.name}</h1> </body> </html>
访问:
4.5 @ModelAttribute
作用1:设置指定方法在控制器其他方法前执行
位置:方法上方
@Controller public class MyController { @ModelAttribute public void before(){ System.out.println("前置方法"); } @RequestMapping("/hello1") public void hello1(){ System.out.println("hello1方法执行"); } }
访问:http://localhost:8080/hello1
作用2:从Model模型中获取数据给参数赋值,提前预热数据。
位置:方法参数前
@Controller public class MyController { // 前置方法向Model中设置数据 @ModelAttribute public void before(Model model){ model.addAttribute("name","张三"); } // 该参数不是从请求中获取,而是从Model中获取 @RequestMapping("/hello2") public void t1(@ModelAttribute("name") String name){ System.out.println(name); } }
访问:http://localhost:8080/hello2
4.6 RESTful风格介绍
RESTful风格是一种URL路径的设计风格。在RESTful风格的URL路径中,网络上的任意数据都可以看成一个资源,它可以是一段文本、一张图片,也可以是一个Java对象。而每个资源都会占据一个网络路径,无论对该资源进行增删改查,访问的路径是一致的。
传统URL:
- 查找id为1的学生:
http://localhost:8080/student/findById?id=30- 删除id为1的学生:
http://localhost:8080/student/deleteById?id=30RESTful风格URL:
- 查找id为30的学生:
http://localhost:8080/student/30- 删除id为30的学生:
http://localhost:8080/student/30
那么如何区分对该资源是哪一种操作?通过请求方式不同,判断进行的是什么操作。
之前我们学过两种请求方式,GET请求和POST请求,而访问RESTful风格的URL一共有四种请求方式:
- GET请求:查询操作
- POST请求:新增操作
- DELETE请求:删除操作
- PUT请求:修改操作
RESTful风格URL:
- 查找id为30的学生:
http://localhost:8080/student/30 GET方式请求- 删除id为30的学生:
http://localhost:8080/student/30 DELETE方式请求
RESTful风格的优点:
结构清晰、符合标准、易于理解、扩展方便。
4.7 APIFOX工具的使用
视频链接:21分钟学会Apifox_哔哩哔哩_bilibili
4.8 @PathVariable
作用:在RESTful风格的URL中获取占位符的值
位置:方法参数前
属性:
- value:获取哪个占位符的值作为参数值,如果占位符和参数名相同,可以省略该属性。
package com.zj.controller; import com.zj.pojo.Student; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @Controller @RequestMapping("/student") // 模拟学生的增删改查控制器 public class StudentController { // 路径中的{id}表示占位符,最后会封装到方法的参数中使用 // 删除学生 @DeleteMapping(value = "/{id}") public void deleteStudent(@PathVariable("id") int id){ System.out.println("删除id为"+id+"的学生"); } // 如果占位符和参数名相同,可以省略@PathVariable的value属性 // 根据id查询学生 @GetMapping(value = "/{id}") public void findStudentById(@PathVariable int id){ System.out.println(id); System.out.println("根据id查询学生"); } // 新增学生 @PutMapping(value = "/{id}") public void addStudent(@PathVariable int id, Student student){ System.out.println(id); System.out.println(student); System.out.println("新增学生"); } // 修改学生 @DeleteMapping(value = "/{id}") public void updateStudent(@PathVariable int id, Student student){ System.out.println(id); System.out.println(student); System.out.println("修改学生"); } }
访问方式:
- 新增学生:POST http://localhost:8080/student/1?name=张三&sex=男
- 修改学生:PUT http://localhost:8080/student/1?name=李四&sex=男
- 删除学生:DELETE http://localhost:8080/student/1
- 查询学生:GET http://localhost:8080/student/1
4.9 HiddentHttpMethodFilter
由于浏览器form表单只支持GET与POST请求,而DELETE、PUT请求并不支持,SpringMVC有一个过滤器,可以将浏览器的POST请求改为指定的请求方式,发送给的控制器方法。
用法如下:
1、在web.xml中配置过滤器
<!-- 请求方式过滤器 --> <filter> <filter-name>httpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>httpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
2、编写控制器方法
package com.zj.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; @Controller public class MyController { @DeleteMapping("/delete") public void testDelete(){ System.out.println("删除方法"); } @PutMapping("/put") public void testPut(){ System.out.println("修改方法"); } }
3、表单
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>DELETE、PUT提交</title> </head> <body> <!-- 删除 --> <%-- 提交DELETE、PUT请求,表单必须提交方式为post --%> <%-- 表单中有一个隐藏域,name值为_method,value值为提交方式 --%> <form action="/delete" method="post"> <input type="hidden" name="_method" value="DELETE"> <input type="submit" value="删除"> </form> <hr/> <!-- 修改 --> <form action="/put" method="post"> <input type="hidden" name="_method" value="PUT"> <input type="submit" value="修改"> </form> </body> </html>