1.1 redirect
重定向,服務器收到請求後發送一個狀態碼給客戶端,讓客戶端再從新請求,而且第一次請求中Request裏的數據消失。因此redirect至關於客戶端向服務器發出兩次請求,第一次請求的數據不會轉發給第二次請求,URL地址會變化兩次。java
1.2 forward
轉發(前往),服務器內部的重定向,在Servlet中經過RequestDispatcher轉發給另外一個程序處理請求,請求的數據依然在。因此forward至關於客戶端向服務器發送一次請求,服務器處理兩次,請求數據不會消失且URL地址只變化一次。spring
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類的APIsession
package 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.
應用:mvc
@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處理業務邏輯 List<Message> messages = 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關鍵字,而後處理。
應用:app
@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"; } }
從上面咱們能夠看出redirect不能傳遞數據,但咱們可使用其它方案傳遞數據。主要有:框架
3.1 經過URL模板進行重定向
方式以下:jsp
@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"。
該方法簡單有效,但傳遞數據值簡單,若數據複雜則可以使用下面的方式傳遞數據ide
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 取出參數