Struts2學習---基本配置,action,動態方法調用,action接收參數

首先咱們先來直接配置,而後再來說原理: 
第一步:jar包的引入: 
咱們能夠到struts2的官網上下載: 
http://struts.apache.org/download.cgi#struts2513css

而後解壓將裏面的app文件夾下的示例war文件解壓,將裏面的struts.xml複製到咱們新建立的src目錄下(特別說一下,struts2最新的Struts 2.5.13版本壓縮包裏面沒有示例的blank示例文件,我是在2.3.34裏面得到的)html

配置文件大概是這樣的:java

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
       <constant name="struts.enable.DynamicMethodInvocation" value="false" />
    <constant name="struts.devMode" value="true" />

    <package name="default" namespace="/" extends="struts-default">
        <action name="hello">
            <result>
              /Hello.jsp
            </result>
        </action>
    </package>
</struts>    

 以上的配置文件是通過個人修改的,因此比較簡潔,由於咱們第一步實現action並無那麼複雜。web

第二步,咱們須要在web.xml中配置過濾器,將struts組件插入進來。 
配置文件大概是這樣:apache

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>testStruts2</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

而後咱們在根目錄下建立一個jsp文件:瀏覽器

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">

    <title>My JSP 'index.jsp' starting page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
  </head>

  <body>
    hello<br>
  </body>
</html>

裏面不須要太多東西,咱們只是作一個簡單的測試。tomcat

而後咱們將項目部署到tomcat中,啓動。安全

而後用瀏覽器訪問: 
http://localhost:8080/testStruts2/hello 
瀏覽器就會跳轉到咱們寫好的Hello.jsp頁面。服務器

咱們接着講原理app

首先,瀏覽器發出一個url,這個url首先發送到服務器,也就是咱們的tomcat,發到tomcat事後,將交給web.xml,而後進入過濾器,經過過濾器將這個請求發送給StrutsPrepareAndExecuteFilter來處理,

StrutsPrepareAndExecuteFilter調用主配置文件struts.xml中的namespace看是否與namespace吻合,找到與之吻合的package,而後找對應的action的name,而後轉到對應的頁面。

其實上面過程還省略了一些過程: 

就是一個請求到了action的name的時候並不會直接轉到咱們的頁面,而是會轉到action對應的類,

上面的struts省略了這一步,可是struts2幫咱們默認執行了這一個過程,若是咱們補充這個過程的話應該這樣:

<action name="hello" class="testStruts2.HelloAction">
package testStruts2;

import com.opensymphony.xwork2.ActionSupport;

public class HelloAction extends ActionSupport{
    public String  execute() {
        return SUCCESS;
    }
}

在struts2的主配置文件action中添加一個class=「」,並在項目的testStruts2中添加一個action類,這個action類能夠有三種方法來寫,可是都要包含execute方法。 
咱們給出剩下的兩種action類書寫方式:

package testStruts2;

import com.opensymphony.xwork2.ActionSupport;

public class HelloAction{
    public String  execute() {
        return "success";
    }
}
package testStruts2;

import com.opensymphony.xwork2.ActionSupport;

public class HelloAction implements Action{
    public String  execute() {
        return SUCCESS;
    }
}

以上的兩種方法,一個是不繼承和實現任何方法,可是包含一個execute方法,返回一個success字符串,另外一個實現Action方法,返回SUCCESS。
Action裏面已經封裝了一些變量,因此實現這個接口的類能夠直接返回SUCCESS,同時咱們還要知道ActionSupport也實現了Action,而且裏面還封裝了大量的方法,這個之後咱們將慢慢用到。
以上三種action書寫方式,建議使用第一種,由於咱們之後將要常用到ActionSupport裏面封裝的方法。

通過上面這個的Action返回一個success,而後StrutsPrepareAndExecuteFilter,將action裏面的result裏的頁面返回給瀏覽器。

 

若是留意的同窗,還會發現咱們從官網下載下來的blank範例裏面action裏面還有些其餘的屬性,對就是method。

動態方法調用:

定義一個action並不必定實現Action接口,同時也能夠不執行execute方法,咱們只要將action裏面的method屬性改成要執行的方法就行,就像這樣:

<action name="hello" class="testStruts2.HelloAction" method="ADD">

同時咱們action裏面的方法也要改成ADD,可是返回值類型必定要爲String

package testStruts2;
public class HelloAction {
    public String ADD() {
        return "success";
    }
}

這樣對於不一樣的請求,咱們能夠根據須要在同一個Action類中用不一樣的方法處理。 
這樣能夠減小建立Action類,而且安全,可是也會形成一個Action類太過龐雜。 
動態方法調用有三種方式,上面的算式一種。

 

繼續咱們來講第二種: 
用「!」歎號方式(不推薦使用) 
這種方法怎麼使用呢?

<action name="helloadd" class="testStruts2.HelloAction" >
    <result>
        /Hello.jsp
    </result>
</action>

就是這樣,理論上咱們再Action類中含有execute方法不會產生什麼影響,可是若是咱們將Action類中的方法改成String Add()呢?
就會報錯,因此就用到可!了,咱們的url地址應該爲:
http://localhost:8080/testStruts2/hello/helloadd!ADD
這樣就會找到ADD方法了。
可是還要注意一點的是咱們要將動態方法調用打開:

<constant name="struts.enable.DynamicMethodInvocation" value="true" />

這裏默認是關閉的,咱們將它改成true就好了。

第三種就是通配符配置了: 

首先咱們須要將上面的DMI改成false(不改也能夠運行,可是建議改)。

<action name="hello_*" class="testStruts2.HelloAction" method="{1}">
        <result>
              /Hello_{1}.jsp

        </result>
  </action>

而後就是這樣:用*代替未知的url
這裏的{1}表示第一個 * 表明的內容 使用通配符可能有好幾個 * ,咱們能夠根據*的順序用{2}{3}…依次表示
http://localhost:8080/testStruts2/hello/hello_ADD.action用這個url來訪問咱們的ADD方法,

當咱們須要其餘DELETE(刪除的時候) 
只須要輸入http://localhost:8080/testStruts2/hello/hello_DELETE.action 
並在Action類裏面添加DELETE方法和添加響應的Hello_DELETE.jsp頁面。

使用通配符簡化了咱們好多的配置,原來須要在配置文件中配置好多個action,如今只須要用通配符就能夠解決這些,只須要添加響應的Action類(方法)和jsp頁面就好了。

 

<action name="*_*" class="testStruts2.{1}HelloAction" >
    <result> /{1}_{2}_hello.jsp</result>
</action>

 

上面的是兩個通配符的範例,若是請求是這樣:
http://localhost:8080/testStruts2/hello/hello_DELETE.action
它就可以根據{1}找到對應的Action類,根據{2}找到對應的方法。
是否是很簡便?(這樣的作法叫作約定優於配置

 

action接收參數:

   咱們怎麼樣用struts接受客戶端發過來的參數呢?下面列舉四種方法: 

  ①屬性參數輸入

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
       <constant name="struts.enable.DynamicMethodInvocation" value="false" />
    <constant name="struts.devMode" value="true" />

    <package name="default" namespace="/" extends="struts-default">

        <action name="user" class="testStruts1.userAction">
            <result>
              /user.jsp
            </result>
        </action>
    </package>
</struts>    

上面是配置文件,沒什麼好說的,和以前大同小異。 

咱們接下來看看Action類:

package testStruts1;

import com.opensymphony.xwork2.ActionSupport;

public class userAction extends ActionSupport{
    String username;
    public userAction() {
    }

    public userAction(String username) {
        super();
        this.username = username;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String execute() {
        System.out.println(username);
        return SUCCESS;
    } 
}

首先這個類要符合javabean的命名規則,咱們再Action類中添加了一個username屬性,並含有它的set get方法,並在execute裏面將接收到的username輸出到控制檯來證明實驗。

當咱們將項目部署到服務器上後,在瀏覽器中輸入一下URl: 
http://localhost:8080/testStruts1/user.action?username=aa 
控制檯便會將接受到的username參數輸出。

咱們能夠看到上面使用Action類的屬性來接收參數的,struts經過咱們給出的set get 方法幫助咱們完成賦值。

②一樣咱們也能夠定義一個實體類來來接收這些信息(官方叫DomainModel): 

例如 
這個是咱們提交的信息:

<form action="login" method="post">
        用戶名:<input type="text" name="user.username"><br>
        密碼<input type="password" name="user.password"><br>
    <input type="submit" value="登陸">
    </form>
/*input裏面必定要使用user.username和user.password和實體類對應,或者使用struts2提供的標籤,不然會出錯(不要問我是怎麼知道的 哭臉.jpg)*/

這個是實體類:

package entity;

public class User {
    String username;
    String password;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}
package testStruts1;

import com.opensymphony.xwork2.ActionSupport;

import entity.User;

public class userAction extends ActionSupport{
    User user;//不須要new對象,struts2幫咱們完成了

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public String execute() {
        if(user.getUsername().equals("username")&&user.getPassword().equals("password")) {
            return SUCCESS;
        }
        return ERROR;
    } 
}
/*struts.xml*/
 <action name="login" class="testStruts1.userAction">
            <result name="success">
              /user.jsp
            </result>
            <result name="error">
            /error.jsp
            </result>
  </action>

 ③還有一種使用DTO(date transfer object)數據傳輸對象來進行傳輸。 
這種方式主要是應對提交的參數和咱們的實體對象不匹配的情況:

好比用戶註冊的時候會輸入第二次密碼來進行確認,咱們將接受兩個密碼,因此在這個類中咱們接收三個參數:username ,password,confirmPassword。 

而後在Action類的execute方法中使用DTO對象來對User對象進行賦值:

User user = new User();//這裏就須要咱們實例化了,由於struts實例化的機會被下面的玩意搶了。
  DTO dto ;
 public String execute(){
     user.setUserName(dto.getUserName());  
     user.setUserPassword(dto.getUserPassword());  
     //後面再利用user實例來進行一系列的操做。
}

固然如今咱們有更爲先進的技術就是咱們徹底能夠用js來在客戶端確認是否相同,而後將數據傳輸過來。

 

④還有一種叫方法:ModelDriven

public class userAction extends ActionSupport implements ModelDriven<User>{
    User user = new User();//這裏須要本身new對象
    @Override
    public User getModel() {

        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }

    public User getModel() {
        return user;
    }

    public String execute() {
        if(user.getUsername().equals("username")&&user.getPassword().equals("password")) {
            return SUCCESS;
        }
        return ERROR;
    } 
}

就是這樣,實現ModelDriven接口,並實現getModel方法,直接得到這個模型對象user。怎麼實現這樣的原理的呢?
是經過一個缺省的攔截器ModelDrivenInterceptor這裏面判斷一個Action對象是否實現ModelDriven,若是實現就返回這個User對象,並將User對象push到valueStack中(valueStack後邊介紹)。

相關文章
相關標籤/搜索