1.forward与redirect介绍
1.1 redirect
重定向,服务器收到请求后发送一个状态码给客户端,让客户端再重新请求,并且第一次请求中Request里的数据消失。所以redirect相当于客户端向服务器发出两次请求,第一次请求的数据不会转发给第二次请求,URL地址会变化两次。1.2 forward
转发(前往),服务器内部的重定向,在Servlet中通过RequestDispatcher转发给另一个程序处理请求,请求的数据依然在。所以forward相当于客户端向服务器发送一次请求,服务器处理两次,请求数据不会消失且URL地址只变化一次。2.Servlet与SpringMVC中的forward与redirect
2.1 Servlet中的forward与redirect
Servlet中的HttpServletResponse类中有sendRedirect(String location)方法直接重定向到URL为location的地址。 应用:public class DeleteOneServlet extends HttpServlet { private static final long serialVersionUID = 1L; private ContentService contentService = new ContentService(); @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 从页面中获取数据 String id = req.getParameter("id"); // 调用Servive执行业务逻辑 contentService.deleteOne(id); // 重定向 resp.sendRedirect("/list.action"); }}
Servlet可以通过HttpServletRequest类的getRequestDispatcher(String path)获得RequestDispatcher对象,该通过该对象的forward(ServletRequest request, ServletResponse response)方法转发请求与相应给任何资源(如Servlet、HTML file、JSP file)。
RequestDispatcher类的APIpackage javax.servlet;public interface RequestDispatcher{ public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException; public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException;}API上的介绍:Defines an object that receives requests from the client and sends them to any resource (such as a servlet, HTML file, or JSP file) on the server. The servlet container creates the RequestDispatcher object, which is used as a wrapper around a server resource located at a particular path or given by a particular name.This interface is intended to wrap servlets, but a servlet container can create RequestDispatcher objects to wrap any type of resource.
应用:
@WebServlet(name = "query", urlPatterns = "/query.action")public class QueryServlet extends HttpServlet { private static final long serialVersionUID = 1L; private ContentService contentService = new ContentService(); @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 从页面获取参数 String command = req.getParameter("command"); String description = req.getParameter("description"); // 调用Service处理业务逻辑 Listmessages = contentService.query(command, description); // 向页面传递值 req.setAttribute("messages", messages); req.setAttribute("command", command); req.setAttribute("description", description); // 转发到视图中 req.getRequestDispatcher("/WEB-INF/jsp/back/list.jsp").forward(req, resp); }}
2.2 SpringMVC中的Servlet
SpringMVC是基于Servlet的Web MVC框架,所以forward与redirect的处理结果一样,方式更为简单。SpringMVC中的InternalResourceViewResolver视图解析器会识别redirect与forward关键字,然后处理。 应用:@Controller@RequestMapping(value="/springMVC")public class UserController { @RequestMapping(value="/login") public String login() { return "login"; } @RequestMapping(value="/upload", method=RequestMethod.POST) public String fileUpload(@RequestPart(value="file") MultipartFile multipartFile) throws Exception{ String path = "E:/java/fileupload/" + multipartFile.getOriginalFilename(); multipartFile.transferTo(new File(path)); // 重定向 return "redirect:/springMVC/index"; // 转发 return "foward:/springMVC/index"; } }
3. SpringMVC重定向传递数据
从上面我们可以看出redirect不能传递数据,但我们可以使用其它方案传递数据。主要有:
- 通过URL模板以路径变量或查询参数形式传递数据
- 通过flash属性传递数据
3.1 通过URL模板进行重定向
方式如下:@Controller@RequestMapping(value="/springMVC")public class UserController { @RequestMapping(value="/index/{name}",method=RequestMethod.GET) public String index(@PathVariable(value="name") String name, @RequestParam(value="id") int id) { System.out.println(name + id); return "login"; } @RequestMapping(value="/data/{id}",method=RequestMethod.GET) public String data(@PathVariable(value="id") int id, Model model) { model.addAttribute("id", id); model.addAttribute("name", "Tom"); return "redirect:/springMVC/index/{name}"; }}
使用模板方式时,若使用了占位符则变为路径参数,否则变为请求变量。所以以上重定向URL路径变为"/springMVC/index/Tom?id=5"。
该方法简单有效,但传递数据值简单,若数据复杂则可使用下面的方式传递数据3.2 使用flash属性
Spring提供了RedirectAttributes设置flash属性的方法重定向传递参数。 原理:在重定向执行之前,所有的flash属性会复制到session中。在重定向后,放在Session中的flash属性会被取出,放到Model中。注:RedirectAttributes类继承自Model类。 方式如下:@Controller@RequestMapping(value="/springMVC")public class UserController { @RequestMapping("/doLogin") public String doLogin(RedirectAttributes attr) { Users u1=new Users(); u1.setName("zhangsan"); u1.setPassWord("123"); attr.addFlashAttribute("u1", u1); return "redirect:toMain4"; } @RequestMapping("toMain1") public String toMain(@ModelAttribute("u1") Users u) { System.out.println("1---"+u.getName()); return "success"; } @RequestMapping("toMain2") public String toMain2(HttpServletRequest request) { Users u = (Users) RequestContextUtils.getInputFlashMap(request).get("u1"); System.out.println("2---"+u.getName()); return "success"; } @RequestMapping("toMain3") public String toMain3(Model model) { Users u = (Users)model.asMap().get("u1"); System.out.println("3---"+u.getName()); return "success"; } @RequestMapping("toMain4") public String toMain4(ModelMap model) { Users u = (Users)model.get("u1"); System.out.println("4---"+u.getName()); return "success"; }}
总结:
A:Redirect等于客户端向服务器发出两次request,同时也接受到两次response,Forward却只是一次request一次response,相比之下,Forward性能更高。
B:Forward能够存储request Scope的Attribute而Redirect却不行。
C:Forward的同时URL并不会变。D:Forward需要在Servlet中需要通过一个Dispatcher来实现。E :Redirect能够防止某些情况下客户端Refresh造成的一些未知后果(例如连续删除)1、使用 RedirectAttributes 的 addAttribute()方法设置参数,则参数将直接拼接在转发url后面,然后可以在通过request.getParameter("userName")) 和 直接通过spring mvc配置参数映射接收到参数
2、使用 RedirectAttributes 的 addFlashAttribute()方法设置参数,则参数不会出现在转发url中,可以通过@ModelAttribute、RequestContextUtils、Model、modelMap 取出参数