《Spring實戰》讀書筆記--SpringMVC之forward與redirect 轉

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類的API

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.

應用:

@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框架,所以forwardredirect的處理結果一樣,方式更爲簡單。SpringMVC中的InternalResourceViewResolver視圖解析器會識別redirectforward關鍵字,然後處理。
應用:

@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 取出參數

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章