1. 程式人生 > >Struts2 快速筆記1

Struts2 快速筆記1

路線:

  1. Struts2的概述、Struts2的入門、Struts2常見的配置、Struts2的Action的編寫
  2. Struts2的資料的封裝、結果頁面配置
  3. Struts2的值棧和OGNL表示式
  4. Struts2的標籤庫

基礎

定義:基於MVC的模式的WEB層框架,Struts2和Struts1的架構完全不同。

常見的Web層框架:Struts2、WebWork、SpringMVC等。

從Servlet到框架的變化:傳統的請求處理是對每一個請求進行相應的Servlet的處理,會產生許多的Servlet;WEB層的框架是基於前端控制器模型對請求進行處理的分發(過濾器)來設計的。

img

環境

下載:https://struts.apache.org/ 練習版本:2.3.34

Struts2解壓目錄

  • apps:Struts提供的應用案例,幾個WAR包
  • docs:開發文件,API
  • lib:開發框架的JAR包
  • src:原始碼

使用:建立WEB專案,引入JAR包,配置

執行過程的順序:當用戶訪問某一個Action的時候,先經過核心過濾器,在核心過濾器中執行一組攔截器(這組攔截器實現部分功能),執行目標Action,根據Action的返回值,進行頁面跳轉。

img

Struts配置檔案的載入順序:

  • init_DefaultProperties() ----載入default.properties

  • init_TraditionalXmlConfigurations(); ----載入struts-default.xml、struts-plugin.xml、struts.xml

  • init_LegacyStrutsProperties(); ----載入struts.properties

  • init_CustomConfigurationProviders(); ----載入配置提供類

  • init_FilterInitParameters() ; // [6] ----載入web.xml中過濾器初始化引數

  • init_AliasStandardObjects() ; // [7] ----載入Bean物件

  • 載入順序

    • default.properties

    • struts-default.xml

    • struts-plugin.xml

    • struts.xml

    • struts.properties

    • web.xml

    注意:後配置的常量的值會覆蓋先配置的常量的值。

 

配置

  1. Package包,Struts中的包,為了更好地管理

    • name
    • extends:一般繼承自struts-default,實現更多功能
    • namespace:名稱空間,與action標籤中的name共同標記為訪問路徑,先查詢有名稱的如“aaa”,再找“/”,最後查詢預設的“ ”;
    • abstract:為true即可被繼承
  2. action

    • name:訪問的名,相當於Servlet的名字,和namespace決定請求訪問路徑
    • class:對應執行的類
    • method:class類中執行的方法,預設為execute
    • converter:用於設定某些型別轉換器
  3. 常量:在Struts2的框架中,提供了非常多的常量:default.properties中。

    • struts.i18n.encoding=UTF-8 ----Struts2中所有的post請求的中文亂碼不用處理。

    • struts.action.extension=action, ----Struts2請求的預設的副檔名。預設副檔名是.action或者什麼都不寫。

    • 在Struts中可以在Struts.xml,Struts.properties,web.xml三個地方修改常量配置。
      1546417771859

  4. action的三種編寫方式

    • POJO類:普通的一個Java類,寫一個public的execute方法,返回一個string的值
    • 實現Action介面,Action介面提供execute方法和5個返回常量,如SUCCESS/ERROR/LOGIN等
    • 繼承ActionSupport類:推薦,同樣實現了Action的介面,還實現了一類驗證等其他功能的介面
  5. action的三種訪問方式

    • 通過method訪問

      1546437949481

    • 使用萬用字元訪問

      1546437965281

    • 動態訪問

      1546437928235

總結:Struts的執行過程:請求API----核心過濾器(StrutsPrepareAndExecuteFilter)-----執行一組攔截器(完成部分的功能)-----Action-------Result.


 

Struts2 常見API

Struts2的Servlet的API訪問

struts中的action中,沒有Servlet的request和response物件,可視作是解耦的。實際開發中,經常使用到Servlet的API,如session,response等物件。

Servlet是單例的,多個程式訪問同一個Servlet只會建立一個Servlet的例項。Action是多例的,一次請求,建立一個Action的例項(不會出現執行緒安全的問題)

三種方式

  1. 完全解耦方式:這種方式只能獲得代表request、session、application的資料的Map集合,不能操作這些物件的本身的方法。

    // 獲取Servlet的API
        ActionContext actionContext = ActionContext.getContext();
        Map<String, Object> map = actionContext.getParameters(); // 類似於request.getParametersMap(),返回一個map
        for (String key : map.keySet()) {
            String[] values = (String[]) map.get(key);
            System.out.println(key + " ... " + Arrays.toString(values));
        }
        // 二、向域物件中存入資料
        actionContext.put("reqName", "reqValue22");// 相當於request.setAttribute();
        actionContext.getSession().put("sessName", "sessValue22"); // 相當於session.setAttribute();
        actionContext.getApplication().put("appName", "appValue22"); // 相當於application.setAttribute();
    
        return "demo1Success";
    
  2. 原生API:注意:這種方式可以操作域物件的資料,同時也可以獲得物件的方法。

    // 獲取Servlet的API
        HttpServletRequest request = ServletActionContext.getRequest();
        Map<String, String[]> map = request.getParameterMap(); 
        for (String key : map.keySet()) {
            String[] values = (String[]) map.get(key);
            System.out.println(key + " ... " + Arrays.toString(values));
        }
        // 二、向域物件中存入資料
        request.setAttribute("reqName", "reqValue22");
        request.setAttribute("sessName", "sessValue22"); 
        ServletActionContext.getServletContext().setAttribute("appName", "appValue22"); 
        return "demo1Success";
    
  3. 介面注入方式:

    public class RequestDemo2 extends ActionSupport implements ServletRequestAware, ServletContextAware{
    	private ServletContext context;
    	private HttpServletRequest request;
    	
    	//action是多例的,所以成員變數不會存線上程安全問題
    	@Override	
    	public String execute() {
    		
    		Map<String, String[]> map = request.getParameterMap(); 
    		
    		
    		for (String key : map.keySet()) {
    			String[] values = (String[]) map.get(key);
    			System.out.println(key + " ... " + Arrays.toString(values));
    		}
    		// 二、向域物件中存入資料
    		request.setAttribute("reqName", "reqValue33");
    		request.setAttribute("sessName", "sessValue33"); 
    		context.setAttribute("appName", "appValue332"); 
    		
    		return "demo1Success";
    	}
    
    	@Override
    	public void setServletContext(ServletContext context) {
    		this.context = context;
    	}
    
    	@Override
    	public void setServletRequest(HttpServletRequest request) {
    		this.request = request;
    	}
    	
    }
    

 

Struts的資料——結果頁面的轉發

  1. 全域性結果頁面:對當前包(xml下的package)中的所有action均有效,只要返回相應的result,則可以跳轉。

    <!-- 配置Struts2的常量 -->
    <constant name="struts.action.extension" value="action"/>
    <package name="demo1" extends="struts-default" namespace="/">
        <global-results>
            <result name="demo1Success">/demo1/demo2.jsp</result>
        </global-results>
    
        <action name="requestDemo1" class="com.leehao.struts_servlet.demo1.RequestDemo1">
            <result name="demo1Success">/demo1/demo2.jsp</result>
        </action>
        <!-- 原生Servlet API -->
        <action name="requestDemo2" class="com.leehao.struts_servlet.demo1.RequestDemo2">
            <result name="demo1Success">/demo1/demo2.jsp</result>
        </action>
    
        <!--介面注入 -->
        <action name="requestDemo3" class="com.leehao.struts_servlet.demo1.RequestDemo3">
            <result name="demo1Success">/demo1/demo2.jsp</result>
        </action>
    </package>
    
  2. 區域性結果頁面:只針對當前action生效,相同配置下,區域性的先生效

  3. result的屬性配置

    • name屬性 :邏輯檢視的名稱。預設值:success
    • type屬性 :頁面跳轉的型別。
      • dispatcher :預設值,請求轉發。(Action轉發到JSP)
      • redirect :重定向。(Action定向到JSP)
      • chain :轉發。(Action轉發到Action)
      • redirectAction :重定向。(Action重定向到Action)
      • stream :Struts2中提供檔案下載的功能。

 

Struts2的資料封裝

Struts2框架是一個web層框架,web層框架(框架:軟體的半成品,完成一部分功能)。Struts2提供了資料封裝的功能。

在struts中,請求經過核心過濾器時,需要在初始化時,執行許多預設的初始攔截器來處理資料。其中,就有params/modelDriven/conversionError等,來實現引數的校驗,型別轉化和封裝等功能。

  1. 屬性驅動:提供屬性set方法的方式(不常用)

    1546499419673

1546499802552

  1. 屬性驅動:頁面中提供表示式方式。

    public class UserAction2 extends ActionSupport {
    	//一個私有的物件,名字和頁面相同,表示直接將資料注入到該物件中
    	//struts生成一個User的物件,封裝資料,將值賦給當前action的物件屬性中,必須有getUser方法,否則只能生成一個屬性的物件。
    	private User user;	
    	public User getUser() {
    		return user;
    	}
    	public void setUser(User user) {
    		this.user = user;
    	}
    	@Override
    	public String execute() throws Exception {		
    		System.out.println(user);		
    		return NONE;
    	}	
    }
    
    --------------------------------jsp-----------------------------------------
    <h3>方式二:屬性驅動,通過頁面表示式</h3>
    <form action="${pageContext.request.contextPath }/userAction2.action" method="post">
    	姓名:<input name="user.username" type="text"><br/>
    	密碼:<input name="user.password" type="password"><br/>
    	生日:<input name="user.birthday" type="text"><br/>
    	年齡:<input name="user.age" type="text"><br/>
    	工資:<input name="user.salary" type="text"><br/>
    	<input type="submit" value="提交"><br/>
    </form>
    
  2. 模型驅動

    模型驅動方式最常用的方式:

    • 缺點:只能同時向一個物件中封裝資料。

    • 使用第二種可以向多個物件中同時封裝資料

    public class UserAction3 extends ActionSupport implements ModelDriven<User>{	
    	private User user = new User();  //必須手動初始化	
    	//模型驅動的方法
    	@Override
    	public User getModel() {		
    		return user;
    	}
    	@Override
    	public String execute() throws Exception {			
    		System.out.println(user);		
    		return NONE;
    	}	
    }
    ----------------------------jsp------------------------------
    <h3>方式三:模型驅動方法</h3>
    <form action="${pageContext.request.contextPath }/userAction3.action" method="post">
    	姓名:<input name="username" type="text"><br/>
    	密碼:<input name="password" type="password"><br/>
    	生日:<input name="birthday" type="text"><br/>
    	年齡:<input name="age" type="text"><br/>
    	工資:<input name="salary" type="text"><br/>
    	<input type="submit" value="提交"><br/>
    </form>
    
  3. Input邏輯檢視錯誤

    INPUT的邏輯檢視的配置,Action介面中提供了五個邏輯檢視的名稱:

    • SUCCESS
    • ERROR
    • LOGIN
    • INPUT :input****在某些攔截器中會使用。
    • NONE

    示例圖:![圖一 INPUT邏輯檢視的配置](assets/圖一 INPUT邏輯檢視的配置.bmp)

    Struts複雜資料模型的封裝

    在實際開發中,有可能遇到批量向資料庫中插入記錄,需要在頁面中將資料封裝到集合中。

    1. 向集合List中封裝

      public class ProductAction1 extends ActionSupport {	
      	private List<Product> products;
      	//必須設定set,get方法
      	public List<Product> getProducts() {
      		return products;
      	}
      	public void setProducts(List<Product> products) {
      		this.products = products;
      	}
      	@Override
      	public String execute() throws Exception {
      		for (Product product : products) {
      			System.out.println(product);
      		}
      		return NONE;
      	}
      }
      ---------------------jsp------------------------------------------
      <h3>一:List型別資料集合</h3>
      <form action="${pageContext.request.contextPath }/productAction1.action" method="post">
      	名稱:<input name="products[0].pname" type="text">
      	價格:<input name="products[0].price" type="text"><br/>
      	名稱:<input name="products[1].pname" type="text">
      	價格:<input name="products[1].price" type="text"><br/>
      	名稱:<input name="products[2].pname" type="text">
      	價格:<input name="products[2].price" type="text"><br/>
      	<input type="submit" value="提交"><br/>
      </form>
      
    2. 向Map中封裝

      public class ProductAction2 extends ActionSupport {	
      	private Map<String, Product> map;
      	//必須設定set,get方法	
      	public Map<String, Product> getMap() {
      		return map;
      	}
      	public void setMap(Map<String, Product> map) {
      		this.map = map;
      	}
      	@Override
      	public String execute() throws Exception {
      		for (Entry<String, Product> entry : map.entrySet()) {
      			System.out.println(entry.getKey() + " " + entry.getValue());
      		}
      		return NONE;
      	}
      }
      -----------------------------JSP------------------------------------------
      <h3>二:MAP型別資料集合</h3>
      <form action="${pageContext.request.contextPath }/productAction2.action" method="post">
      	名稱:<input name="map['one'].pname" type="text">
      	價格:<input name="map['one'].price" type="text"><br/>
      	名稱:<input name="map['two'].pname" type="text">
      	價格:<input name="map['two'].price" type="text"><br/>
      	名稱:<input name="map['three'].pname" type="text">
      	價格:<input name="map['three'].price" type="text"><br/>
      	<input type="submit" value="提交"><br/>
      </form>