胖哥學SpringMVC:簡單跳轉專題

胖先森發表於2018-03-14

簡單跳轉專題

個人建議重新練習一遍搭建的過程,如果感覺麻煩你可以直接複製上一個工程,但是需要修改pom.xml中的一點資訊

<groupId>com.hanpang.springmvc</groupId>
<artifactId>springmvc-demo01</artifactId>
<version>0.0.1-SNAPSHOT</version>
複製程式碼

1.核心配置類和載入類

package com.hanpang.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages="com.hanpang.**.web")
public class WebConfig {

}
複製程式碼
package com.hanpang.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class[] {WebConfig.class};
	}

	@Override
	protected Class<?>[] getServletConfigClasses() {
		return null;
	}

	@Override
	protected String[] getServletMappings() {
		return new String[] {"/"};
	}



}
複製程式碼

2.JavaWeb階段的跳轉方式

請注意SpringMVC的方法中的形參,框架給我們完成了例項化的操作

package com.hanpang.web;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller//告知其是一個控制器
public class Demo01Controller {

	@RequestMapping(path="/test01")
	public ModelAndView 傳統方式跳轉_請求轉發(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
		System.out.println("預設對形參的進行了例項化操作");
		request.getRequestDispatcher("/WEB-INF/jsp/demo01.jsp").forward(request, response);
		return null;
	}

	@RequestMapping(path="/test02")
	public ModelAndView 傳統方式跳轉_重定向(HttpServletRequest request,HttpServletResponse response) throws IOException {
		System.out.println("預設對形參的進行了例項化操作");
		response.sendRedirect(request.getContextPath()+"/view/result01.jsp");
		return null;
	}
}
複製程式碼

NOTE: 這種方式我們幾乎不再使用了,只是只是簡單的演示和回顧一下,至少我們可以使用這種方式獲取Servlet API!!!

3.Controller跳轉到JSP的方式演示

在示例最後的時候,我們會加入JSP的檢視解析器,開始階段我們還是按照傳統的方式,有一個循序漸進的過程

package com.hanpang.web;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller//告知其是一個控制器
public class Demo01Controller {

	@RequestMapping(path="/test03")
	public ModelAndView 預設情況下是請求轉發(){
		ModelAndView mav = new ModelAndView();
		mav.setViewName("/WEB-INF/jsp/demo01.jsp");
		return mav;
	}
	@RequestMapping(path="/test04")
	public ModelAndView 設定重定向的方式(){
		ModelAndView mav = new ModelAndView();
		mav.setViewName("redirect:/view/result01.jsp");
		//或者
		//mav.setViewName(UrlBasedViewResolver.REDIRECT_URL_PREFIX+"/view/result01.jsp");
		return mav;
	}

}
複製程式碼

感覺跟Java Web階段的方式差不多,只是重定向的時候設定了一個簡單的字首

4.Controller跳轉到Controller的方式演示

類似於從一個Servlet調到另一個Servlet

package com.hanpang.web;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller//告知其是一個控制器
public class Demo01Controller {

	@RequestMapping(path="/test05")
	public ModelAndView 直接設定對映路徑即可(){
		ModelAndView mav = new ModelAndView();
		mav.setViewName("/test03");
		return mav;
	}

	@RequestMapping(path="/test06")
	public ModelAndView 設定重定向(){
		ModelAndView mav = new ModelAndView();
		mav.setViewName("redirect:/test04");
		return mav;
	}


}
複製程式碼

5.加入JSP的檢視解析器

上面的演示過程中,我們發現ModelAndView中setViewName是用來完成跳轉的,這裡面傳遞的資料是字串,但是處理方式不太一樣,當跳轉的路徑有字首redirect:的時候,那麼處理方式不一樣.

還有,如果我們有多個類似/WEB-INF/jsp/demo01.jsp形式的字串的時候,我們發現公共的部分很多,SpringMVC給我們提供了一個專門處理 Controller請求轉發JSP頁面 的類.

請注意我的描述: 如果發現你傳遞的字串沒有設定任何字首標識,那麼預設情況下使用配置JSP檢視解析器處理,並且完成請求轉發的操作

  • 註解:配置核心配置類

    package com.hanpang.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.ViewResolver;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.view.InternalResourceViewResolver;
    import org.springframework.web.servlet.view.JstlView;
    
    @Configuration
    @EnableWebMvc
    @ComponentScan(basePackages="com.hanpang.**.web")
    public class WebConfig {
    
    	@Bean//例項化
    	public ViewResolver viewResolver() {
    		InternalResourceViewResolver jspViewResolver = new InternalResourceViewResolver();
    		jspViewResolver.setViewClass(JstlView.class);//springmvc支援jstl標籤
    		jspViewResolver.setPrefix("/WEB-INF/");
    		jspViewResolver.setSuffix(".jsp");
    
    		return jspViewResolver;
    	}
    
    }
    複製程式碼

    **NOTE:**請注意方法上的註解@Bean

    方法等價於XML中的程式碼如下

        <bean id="jspResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/"/>
            <property name="suffix" value=".jsp"/>
            <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        </bean>
    複製程式碼
  • 改進Controller跳轉JSP程式碼

    該檢視解析器只能針對於JSP的請求轉發,對重定向無效,請注意程式碼的註釋內容

    	@RequestMapping(path="/test03")
    	public ModelAndView 預設情況下是請求轉發(){
    		ModelAndView mav = new ModelAndView();
    		//mav.setViewName("/WEB-INF/jsp/demo01.jsp");
    
    		//改進後:預設情況下,會使用JSP檢視解析器處理,
    		// prefix+"jsp/demo01"+suffix => /WEB-INF/jsp/demo01.jsp
    		mav.setViewName("jsp/demo01");//發現字串沒有字首修飾
    		return mav;
    	}
    	@RequestMapping(path="/test04")
    	public ModelAndView 設定重定向的方式(){
    		ModelAndView mav = new ModelAndView();
    		//解析器對重定向無效
    		mav.setViewName("redirect:/view/result01.jsp");
    		return mav;
    	}
    複製程式碼
  • 改進Controller跳轉Controller程式碼

    @RequestMapping(path="/test05")
    public ModelAndView 直接設定對映路徑即可(){
      ModelAndView mav = new ModelAndView();
      mav.setViewName("/test03");
      return mav;
    }
    複製程式碼

    當配置完JSP檢視解析器後,對上述的程式碼再次進行測試,檢視訪問結果有驚喜

    胖哥學SpringMVC:簡單跳轉專題

    符合我們之前說的"/test03"是一個字串,預設情況下會使用JSP檢視解析器進行處理,那麼如何改進呢?

    可以設定字首"forward:",改進程式碼如下:

    @RequestMapping(path="/test05")
    public ModelAndView 直接設定對映路徑即可(){
      ModelAndView mav = new ModelAndView();
      mav.setViewName("forward:/test03");
      //或者
      //mav.setViewName(UrlBasedViewResolver.FORWARD_URL_PREFIX+"/test03");
      return mav;
    }
    複製程式碼

    當發現字串使用forward:修飾後,處理情況改變為從Controller請求轉換到另一個Controller,而如果做到重定向的話,程式碼如下:

    @RequestMapping(path="/test06")
    public ModelAndView 設定重定向(){
      ModelAndView mav = new ModelAndView();
      mav.setViewName("redirect:/test04");
      return mav;
    }
    複製程式碼

6.InternalResourceViewResolver 附錄

InternalResourceViewResolver:它是URLBasedViewResolver的子類,所以URLBasedViewResolver支援的特性它都支援。

  • 在實際應用中InternalResourceViewResolver也是使用的最廣泛的一個檢視解析器,那麼InternalResourceViewResolver有什麼自己獨有的特性呢?

單從字面意思來看,我們可以把InternalResourceViewResolver解釋為內部資源檢視解析器,這就是InternalResourceViewResolver的一個特性。

InternalResourceViewResolver會把返回的檢視名稱都解析為InternalResourceView物件,InternalResourceView會把Controller處理器方法返回的模型屬性都存放到對應的request屬性中,然後通過RequestDispatcher在伺服器端把請求forword重定向到目標URL。

比如在InternalResourceViewResolver中定義了prefix=/WEB-INF/,suffix=.jsp,然後請求的Controller處理器方法返回的檢視名稱為test,那麼這個時候InternalResourceViewResolver就會把test解析為一個InternalResourceView物件,先把返回的模型屬性都存放到對應的HttpServletRequest屬性中,然後利用RequestDispatcher在伺服器端把請求forword到/WEB-INF/test.jsp。這就是InternalResourceViewResolver一個非常重要的特性,我們都知道存放在/WEB-INF/下面的內容是不能直接通過request請求的方式請求到的,為了安全性考慮,我們通常會把jsp檔案放在WEB-INF目錄下,而InternalResourceView在伺服器端跳轉的方式可以很好的解決這個問題。下面是一個InternalResourceViewResolver的定義,根據該定義當返回的邏輯檢視名稱是test的時候,InternalResourceViewResolver會給它加上定義好的字首和字尾,組成“/WEB-INF/test.jsp”的形式,然後把它當做一個InternalResourceView的url新建一個InternalResourceView物件返回。

相關文章