Struts2框架入門

来源:https://www.cnblogs.com/cailijia52o/archive/2018/03/31/8679629.html
-Advertisement-
Play Games

Struts2框架 一、什麼是Struts2 Struts2是一個基於MVC設計模式的Web應用框架,它本質上相當於一個servlet,在MVC設計模式中,Struts2作為控制器(Controller)來建立模型與視圖的數據交互。Struts 2是Struts的下一代產品,是在 struts 1和 ...


Struts2框架

一、什麼是Struts2

  Struts2是一個基於MVC設計模式的Web應用框架,它本質上相當於一個servlet,在MVC設計模式中,Struts2作為控制器(Controller)來建立模型與視圖的數據交互。Struts 2是Struts的下一代產品,是在 struts 1和WebWork的技術基礎上進行了合併的全新的Struts 2框架。其全新的Struts 2的體繫結構與Struts 1的體繫結構差別巨大。Struts 2以WebWork為核心,採用攔截器的機制來處理用戶的請求,這樣的設計也使得業務邏輯控制器能夠與ServletAPI完全脫離開,所以Struts 2可以理解為WebWork的更新產品。雖然從Struts 1到Struts 2有著太大的變化,但是相對於WebWork,Struts 2的變化很小。

                                            

  -------------百度百科

二、快速搭建環境

  1、下載官方的jar包
    官網:
https://struts.apache.org/

  2、將其中核心j包中app文件中的struts-blank尾碼名改為zip,併進行解壓其中的lib文件夾中的jar包為運行struts2的基本jar包

  3、創建新工程,將基本jar包拷入新建工程中的lib文件夾

  

  4、在web.xml文件中配置核心過濾器

<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>

  其中<filter-class>中過濾器名是根據StrutsPrepareAndExecuteFilter類所在路徑來配置的

  

  5、配置用於跳轉的頁面,此頁面是用於跳轉到Action中

<body>
       <h3>快速入門</h3>
       <a href="${pageContext.request.contextPath}/hello.action">跳轉</a>
  </body>

  6、編寫Action

package com.clj.action;
/**
 * Struts框架都使用Action類處理用戶的請求
 * @author Administrator
 *
 */
public class HelloAction {    
    /**
     * Action類中的方法簽名有要求,必須這麼做
     * public 公共的
     * 必須有返回值,必須String類型
     * 方法名稱可以是任意的,但是不能有參數列表
     * 頁面的跳轉:1.return 字元串 2.需要在struts.xml配置文件中,配置跳轉的頁面
     */
    public String sayHello(){
        //編寫代碼接收請求的參數
        System.out.println("Hello Struts2!");
        return "success";
    }
    /**
     * 演示的method方法的預設值
     * 當配置文件中沒有配置指定的method方法,他會預設執行Action中的execute方法
     * @return
     */
    public String execute(){
        System.out.println("method方法的預設值是execute");
        return null;
    }
}

 

  7、設置Action配置文件

      配置文件是一個xml文件,命名強製為struts2.xml,否則當伺服器開啟時無法識別不是該文件名的配置文件,該文件建立在src下

      其中,其約束條件可以在struts2-blank\WEB-INF\src\java的struts2.xml文件中可以找到

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>
    <!-- 包結構 ,包名不能重覆 -->
    <package name="default" namespace="/" extends="struts-default">
        <!-- 配置Action -->
        <action name="hello" class="com.clj.action.HelloAction" method="sayHello">
            <!-- 配置跳轉的頁面,路經的寫法:在Struts2框架中,不管是轉發還是重定向,都不需要加項目名 
                name表示結果頁面邏輯視圖名稱
                 type 結果類型(轉發類型,預設值是轉發,也可以設置其他的值)
            -->    
            <result name="success">/jsp/success.jsp</result>
        </action>
     </package>
</struts>

  8、此時訪問跳轉頁面,即可執行execute方法

  總結:這裡當執行跳轉頁面時,會根據配置文件中的action 中的 name屬性進行匹配,找到有name為hello 匹配到HelloAction類中的sayHello方法,通過方法反射等進行解析,根據方法的返回值“success”進行頁面的跳轉,過渡到success.jsp中。值得註意的是,其package包名不能重覆!

三、struts2執行流程為:

從客戶端發送請求過來 先經過前端控制器(核心過濾器StrutsPrepareAndExecuteFilter)過濾器中執行一組攔截器(一組攔截器 就會完成部分功能代碼)執行目標Action,在Action中返回一個結果視圖,根據Result的配置進行頁面的跳轉.

 

 

四、Action書寫方式

  方式一:POJO類

/**
 * 三種action書寫方式之POJO類
 * 沒有任何繼承和實現
 * @author Administrator
 *
 */
public class Demo1Action {
    /**
     * execute是預設方法
     * return null:他不會跳轉
     * @return
     */
    public String execute(){
        System.out.println("Demo1Action就是一個POJO類");
        return null;
    }
}

  方式二:實現Action的介面

import com.opensymphony.xwork2.Action;

/**
 * 三種action書寫方式之實現Action的介面,Action是框架提供的介面
 * @author Administrator
 *
 */
public class Demo2Action implements Action{

    @Override
    public String execute() throws Exception {
        // TODO Auto-generated method stub
        System.out.println("Demo2Actions實現了Action的介面");
        //Action介面中定義了 public static final String SUCCESS = "success";
        return SUCCESS;
    }
    
}

  其中Action有自定義的字元串常量,實現Action的介面返回值就可調用它的常量

  方式三:繼承ActionSupport類

import com.opensymphony.xwork2.ActionSupport;

/**
 *  三種action書寫方式之編寫ActionSupport類
 *  ActionSupport類已經實現了Action和一些其他介面
 * @author Administrator
 *
 */
public class Demo3Action extends ActionSupport{

    
    public String execute() throws Exception {
        System.out.println("Demo3Action繼承了ActionSupport類。。");
        //不跳轉
        return NONE;
    }
     
}

五、struts2中常量的配置

  1.這裡先看看當框架執行時配置文件載入的順序

  查看StrutsPrepareAndExecuteFilter:(核心過濾器)兩個功能 :預處理  執行 

  在預處理功能中 init 方法中會有載入配置文件的代碼:

    dispatcher.init();

            init_DefaultProperties(); // [1] ---- 載入org.apache.struts.default.properties.配置的是struts2的所有常量.

            init_TraditionalXmlConfigurations(); // [2] ---- 載入struts-default.xmlstruts-plugin.xmlstruts.xml

            init_LegacyStrutsProperties(); // [3] ---- 載入用戶自定義struts.properties

            init_CustomConfigurationProviders(); // [5] ---- 載入Struts2定義Bean.

            init_FilterInitParameters() ; // [6] ---- 載入web.xml

            init_AliasStandardObjects() ; // [7] ---- 用戶自定義Bean

     結論:

       

    * 先載入default.properties文件,在org/apache/struts2/default.properties文件,都是常量。

       * 又載入struts-default.xml配置文件,在核心的jar包最下方,struts2框架的核心功能都是在該配置文件中配置的。

       * 再載入struts.xml的配置文件,在src的目錄下,代表用戶自己配置的配置文件

          * 最後載入web.xml的配置文件

 

    * 後載入的配置文件會覆蓋掉之前載入的配置文件(在這些配置文件中可以配置常量)

            因此: 後配置的常量 覆蓋先配置的常量.

       2、查看常量

  

  3、修改常量

  註意:修改常量不能在default.properties文件中修改,可以在struts.xml或者web.xml文件中

   1)在struts.xml中

  <!-- 編寫常量 -->
    <constant name="struts.action.extension" value="action,,"></constant>

  struts2中訪問action預設尾碼為action或者不寫,這個配置可以進行更改

   2)在web.xml中

 <filter>
      <filter-name>struts2</filter-name>
      <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
      <!-- 編寫常量 -->
      <init-param>
          <param-name>struts.action.extension</param-name>
          <param-value>action,,</param-value>
      </init-param>
  </filter>

六、Action的訪問方式

  1、傳統方式:配置method屬性

    1)Action類代碼

import com.opensymphony.xwork2.ActionSupport;

/**
 * 編寫的客戶的Action的類
 * @author Administrator
 *
 */
public class CustomerAction extends ActionSupport {
    //保存客戶
    public String save(){
        System.out.println("保存客戶");
        return NONE;
    }
    //刪除客戶
    public String delete(){
        System.out.println("刪除客戶");
        return NONE;
    }
}    

   2)配置文件配置

 <!-- 演示Action的訪問,傳統方式 -->
     <package name="demo2" namespace="/" extends="struts-default">
         <action name="saveCust" class="com.clj.action2.CustomerAction" method="save"/>
         <action name="delCust" class="com.clj.action2.CustomerAction" method="delete"/>    
     </package>

  2、通配符的配置

   1)Action類

import com.opensymphony.xwork2.ActionSupport;
/**
 * 通配符的方式
 * @author Administrator
 *
 */
public class LinkmanAction extends ActionSupport{
    //保存客戶
    public String save(){
        System.out.println("保存聯繫人。。");
        return "saveOk";
    }
    //刪除客戶
    public String delete(){
        System.out.println("刪除聯繫人。。");
        return "delOk";
    }
}

   2)配置文件

 <!-- 演示Action的訪問,通配符方式 -->
     <package name="demo3" namespace="/" extends="struts-default">

   <!--這裡的{1}代表統配第一個*;name=linkman_*_*...methd=”{1}”{1}表示匹配第一個*{2}表示通配第二個*,即數字表示*的位置,通過通配符調用指定方法-->

         <action name="linkman_*" class="com.clj.action2.LinkmanAction" method="{1}">
             <result name="saveOk">/jsp/success.jsp</result>
             <result name="delOk">/jsp/success.jsp</result>
         </action>
     </package>

   3、動態方法訪問

   1)開啟動態訪問常量(註意:常量的配置都是定義在包外)

<!-- 開啟動態方法訪問 -->
    <constant name="struts.enable.DynamicMethodInvocation" value="true"></constant>

   2)Action類

import com.opensymphony.xwork2.ActionSupport;

/**
 * 動態方法訪問
 * @author Administrator
 *
 */
public class UserAction extends ActionSupport{
    //保存客戶
        public String save(){
            System.out.println("保存用戶。。");
            return NONE;
        }
        //刪除客戶
        public String delete(){
            System.out.println("刪除用戶。。");
            return NONE;
        }
}

   3)配置文件

 <!-- 演示Action的訪問,動態方法訪問方式 -->
     <package name="demo4" namespace="/" extends="struts-default">
         <action name="user" class="com.clj.action2.UserAction"/>
     </package>

   4)功能變數名稱書寫方式

<h3>動態方法訪問</h3>
     <a href="${pageContext.request.contextPath}/user!save.action">保存聯繫人</a></br>
     <a href="${pageContext.request.contextPath}/user!delete.action">刪除聯繫人</a></br>

 七、struts2中數據的之接收數據

  struts2怎麼傳值呢,這裡由兩種種方式

  1.定義一個jsp,利用表單進行數據傳輸

          <form action="${pageContext.request.contextPath}/demo1Action.action" method="post">
              姓名:<input type="text" name="username"/></br>
              密碼:<input type="password" name="psssword"/></br>
              <input type="submit" value="註冊"/>
          </form></br>

  2.編寫Action

   1)方式一:完全解耦合的方式

package com.clj.demo1;

import java.util.Arrays;
import java.util.Map;
import java.util.Set;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
/**
 * 完全解耦合的方式,使用Servlet的API
 * 通過操作ActionContexte類的方法來獲取Servlet API
 * @author Administrator
 *
 */
public class demo1Action extends ActionSupport{
    public String execute() throws Exception{
        //完全解耦合的方式
        ActionContext context=ActionContext.getContext();
        //獲取到請求的參數,獲取到所有請求的參數
        Map<String,Object> map=context.getParameters();
        //遍歷獲取數據
        Set<String> keys=map.keySet();
        for(String key:keys){
            //通過key獲取到值
            String[] values=(String[]) map.get(key);
            //預設情況下,struts已經將字元編碼轉成了UTF-8,無需考慮中文亂碼
            System.out.println(key+":"+Arrays.toString(values));
        }
        //如果向request對象中存入值
        context.put("msg","小東東");
        //獲取其他map集合
        context.getSession().put("msg","小蒼");
        context.getApplication().put("msg","小澤");
        return SUCCESS;
        
    }
}

  2)方式二:原生的Servlet API

package com.clj.demo1;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

/**
 * 原生的Servlet API
 * @author Administrator
 *
 */
public class demo2Action extends ActionSupport{
    public String execute() throws Exception{
        //獲取到request對象
        HttpServletRequest request=ServletActionContext.getRequest();
        request.setAttribute("msg","小東東");
        request.getSession().setAttribute("msg","美美");
        ServletActionContext.getServletContext().setAttribute("msg", "小風");     
        return SUCCESS;
    }
}

八、結果視圖處理

  1、關於全局頁面

       為什麼要設置全局頁面?因為在同一個包下,有時候多個action中所獲得的結果視圖是同一個,這要每個action配置會覺得冗餘,此時可以配置個全局頁面來共用

    列子:假如當action中方法返回值是success,此時就可無需配置<result>標簽,它會自動跳轉到success.jsp中

<!-- 配置全局的結果頁面,必須定義在當前包下 -->
    <global-results>
        <!-- type:轉發類型 
                 dispatcher:轉發,預設值,Action->jsp
                 redirect:  重定向,Action->jsp
                 chain:     多個action之間跳轉,Action->Action(轉發)
                 redirectAction:多個action之間跳轉,Action->Action(重定向)
                 stream:文件下載
        -->
        <result name="success" type="dispatcher">/jsp/success.jsp</result>
    </global-results>

  2.、結果頁面的類型

        * 結果頁面使用<result>標簽進行配置,包含兩個屬性

        > name  -- 邏輯視圖的名稱

        > type  -- 跳轉的類型,值一些,需要掌握一些常用的類型。常見的結果類型去struts-default.xml中查找。

            * dispatcher        -- 轉發.type的預設值.Action--->JSP

            * redirect          -- 重定向. Action--->JSP

            * chain             -- 多個action之間跳轉.從一個Action轉發到另一個Action.  Action---Action

            * redirectAction    -- 多個action之間跳轉.從一個Action重定向到另一個Action. Action---Action

            * stream            -- 文件下載時候使用的

     演示重定向

    action

package com.clj.demo1;

import com.opensymphony.xwork2.ActionSupport;

/**
 * 演示重定向
 * @author Administrator
 *
 */
public class demo3Action extends ActionSupport{
    public String save(){
        System.out.println("保存");
        return SUCCESS;
    }
    public String update(){
        System.out.println("更新成功");
        return NONE;
    }
}

   配置文件

<!-- 演示重定向到Action -->
        <action name="demo3Action_*" class="com.clj.demo1.demo3Action" method="{1}">
            <result name="success" type="redirectAction">demo3Action_update</result>
        </action>

九、關於struts2框架數據的封裝

  封裝數據是為了便於開發,降低維護成本,這裡有兩種方式進行數據的封裝。

  > 提供對應屬性的set方法進行數據的封裝。

            * 表單的哪些屬性需要封裝數據,那麼在對應的Action類中提供該屬性的set方法即可。

            * 表單中的數據提交,最終找到Action類中的setXxx的方法,最後賦值給全局變數。

  1、方式一:屬性驅動

       1)屬性驅動寫法方式一:在action類中直接寫從頁面中提交的屬性數據

         jsp:

 <h3>屬性驅動的方式(直接在Action中編寫屬性)</h3>
         <!-- aciton接收表單值時屬性要提供set方法 -->
         <form action="${pageContext.request.contextPath}/regist1.action" method="post">
              姓名:<input type="text" name="username"/></br>
              密碼:<input type="password" name="password"/></br>
              年齡:<input type="text" name="age"/></br>
              <input type="submit" value="註冊"/>
          </form></br>

  action:

package com.clj.demo2;

import com.opensymphony.xwork2.ActionSupport;
/**
 * 屬性驅動
 * 方式一:將Action當做JavaBean類
 * @author Administrator
 *
 */
public class regist1 extends ActionSupport{
    private String username;
    private String password;
    private Integer age;
    //傳值,用set,不需要要用get
    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String execute() throws Exception{
        System.out.println(username+" "+password+" "+age);
        return NONE;
    }
}

    2)屬性驅動寫法方式二:將提交的數據封裝到一個類中

    jsp

<h3>屬性驅動的方式(把數據封裝到javaBean中)</h3>
          <!-- 註意:頁面的編寫風格為OGNL表達寫法 -->
             <form action="${pageContext.request.contextPath}/regist2.action" method="post">
                 <!-- 這裡的"user"是根據Aciton中封裝屬性的類的名稱屬性而定(private User user;) -->
              姓名:<input type="text" name="user.username"/></br>
              密碼:<input type="password" name="user.password"/></br>
              年齡:<input type="text" name="user.age"/></br>
              <input type="submit" value="註冊"/>
          </form></br>

      javabean

package com.clj.demo2;

public class User {
    private String username;
    private String password;
    private Integer age;
    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;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "User [username=" + username + ", password=" + password
                + ", age=" + age + "]";
    }
    
}

   action

package com.clj.demo2;

import com.opensymphony.xwork2.ActionSupport;
/**
 * 屬性驅動的方式,將數據封裝到javaBean中
 * @author Administrator
 *
 */
public class regist2 extends ActionSupport{
    //註意:屬性驅動的方式,需要提供get和set方法
    private User user;
    
    public User getUser() {
        return user;
    }

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

    public String execute(){
        System.out.println(user);
        return NONE;
    }
}  

  * 註意:只提供一個set方法還不夠,必須還需要提供user屬性的get和set方法!!!

        > 先調用get方法,判斷一下是否有user對象的實例對象,如果沒有,調用set方法把攔截器創建的對象註入進來,接下直接調用get方法獲取傳過來的參數

  拓展:

  1.將數據封裝到list中

    jsp

 

<h3>向List集合封裝數據(預設情況下,採用屬性驅動的方式)</h3>
          <!-- 採用OGNL表達式 -->
          <form action="${pageContext.request.contextPath}/regist4.action" method="post">
                 <!-- 這裡的"user"是根據Aciton中封裝屬性的類的名稱屬性而定(private User user;) -->
              姓名:<input type="text" name="list[0].username"/></br>
              密碼:<input type="password" name="list[0].password"/></br>
              年齡:<input type="text" name="list[0].age"/></br>
              
              姓名:<input type="text" name="list[1].username"/></br>
              密碼:<input type="password" name="list[1].password"/></br>
              年齡:<input type="text" name="list[1].age"/></br>
              <input type="submit" value="註冊"/>
          </form></br>

 

    action

 

 

package com.clj.demo2;

import java.util.List;

import com.opensymphony.xwork2.ActionSupport;
/**
 * 屬性驅動的方式,把數據封裝List集合中
 * @author Administrator
 *
 */
public class regist4 extends ActionSupport{
    private List<User> list;

    public List<User> getList() {
        return list;
    }

    public void setList(List<User> list) {
        this.list = list;
    }
    public String execute() throws Exception{
        for(User user:list){
            System.out.println(user);
        }
        return NONE;
    }
    
}

 

  2.將數據封裝到Map集合中

   jsp

<h3>向Map集合封裝數據(預設情況下,採用屬性驅動的方式)</h3>
          <!-- 採用OGNL表達式 -->
          <form action="${pageContext.request.contextPath}/regist5.action" method="post">
                 <!-- 這裡的"user"是根據Aciton中封裝屬性的類的名稱屬性而定(private User user;) -->
              姓名:<input type="text" name="map['one'].username"/></br>
              密碼:<input type="password" name="map['one'].password"/></br>
              年齡:<input type="text" name="map['one'].age"/></br>
              
              姓名:<input type="text" name="map['two'].username"/></br>
              密碼:<input type="password" name="map['two'].password"/></br>
              年齡:<input type="text" name="map['two'].age"/></br>
              <input type="submit" value="註冊"/>
          </form></br>

   action

package com.clj.demo2;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.opensymphony.xwork2.ActionSupport;
/**
 * 屬性驅動的方式,把數據封裝Map集合中
 * @author Administrator
 *
 */
public class regist5 extends ActionSupport{
    private Map<String,User> map=new HashMap<String,User>(); 
    
    public Map<String, User> getMap() {
        return map;
    }

    public void setMap(Map<String, User> map) {
        this.map = map;
    }

    public String execute() throws Exception{
        System.out.println(map);
        return NONE;
    }
    
}

 

 

  2、方式二:模型驅動

    1)手動實例化javabean

 

private User user=new User();

 

    2)實現ModelDriven<T>介面,實現getModel()的方法,在getModel()方法中返回javaBean

    jsp

<h3>模型驅動</h3>
             <form action="${pageContext.request.contextPath}/regist3.action" method="post">
                 <!-- 這裡的"user"是根據Aciton中封裝屬性的類的名稱屬性而定(private User user;) -->
              姓名:<input type="text" name="username"/></br>
              密碼:<input type="password" name="password"/></br>
              年齡:<input type="text" name="age"/></br>
              <input type="submit" value="註冊"/>
          </form></br>

 

    action代碼

package com.clj.demo2;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
/**
 * 模型驅動的方式
 * 1.實現ModelDrivern介面
 * 2.必須手動實列化對象(需要自己new好)
 * @author Administrator
 */
public class regist3 extends ActionSupport implements ModelDriven<User>{
    //必須手動實例化
    private User user=new User();
    //獲取模型對象
    public User getModel() {
        // TODO Auto-generated method stub
        return user;
    }
    public String execute() throws Exception{
        System.out.println(user);
        return NONE;
    }
    
}

十、struts2之攔截器

  1、什麼是攔截器?

  java里的攔截器是動態攔截Action調用的對象。它提供了一種機制可以使開發者可以定義在一個action執行的前後執行的代碼,也可以在一個action執行前阻止其執行,同時也提供了一種可以提取action中可重用部分的方式。在AOP(Aspect-Oriented Programming)中攔截器用於在某個方法或欄位被訪問之前,進行攔截然後在之前或之後加入某些操作。

                                                                        ---------360百科

     攔截器的利用是struts2框架的一個特點,即面向切麵編程

  2、編寫一個攔截器

   1)定義一個攔截器類

package com.itheima.interceptior;

import com.google.common.collect.AbstractIterator;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;



/**
 * 編寫簡單的攔截器
 * @author Administrator
 *
 */
public class DemoInterceptor extends AbstractInterceptor{
    
    /**
     * intercept用來進行攔截的
     */
    public String intercept(ActionInvocation invocation) throws Exception {
        System.out.println("Action方法執行之前");
        //執行下一個攔截器
        String result=invocation.invoke();
        System.out.println("Action方法執行之後");
        return result;
    }
}

  2) 定義一個action

package com.clj.demo3;

import com.opensymphony.xwork2.ActionSupport;

public class UserAction extends ActionSupport{
    public String execute() throws Exception{
        System.out.println("我是Action,我正常執行了");
        return NONE;
    }
}

  3) 配置文件配置

<package name="demo3" extends="struts-default" namespace="/">
         <interceptors>
             <!-- 定義了攔截器 -->
             <interceptor name="DemoInterceptor" class="com.itheima.interceptior.DemoInterceptor"/>
         </interceptors>
        <action name="userAction" class="com.clj.demo3.UserAction">
            <!-- 只要是引用自己的攔截器,預設棧的攔截器就不執行了 ,必須手動引入預設棧-->
            <interceptor-ref name="DemoInterceptor"/>
            <interceptor-ref name="defaultStack"/>
        </action>
    </package>

  3、使用攔截器驗證用戶登錄

     1) 定義一個攔截器

package com.clj.interceptor;

import org.apache.struts2.ServletActionContext;

import com.heima.domain.User;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;

/**
 * 自動以攔截器,判斷當前系統是否已經登錄,如果登錄,繼續執行
 * 如果沒有登錄,跳轉到登錄頁面
 * AbstractInterceptor會攔截所有方法
 * MethodFilterInterceptor可以對指定的方法進行攔截
 * @author Administrator
 *
 */
public class UserInterceptor extends MethodFilterInterceptor{

    /**
     * 進行攔截的方法
     */
    protected String doIntercept(ActionInvocation invocation) throws Exception {
        //獲得session對象
        User user=(User) ServletActionContext.getRequest().getSession().getAttribute("existUser");
        if(user==null){
            //沒有登錄,返回字元串,後面就不會執行了
            return "login";
        }
        return invocation.invoke();
    }
    
}

   2)action

package com.itheima.action;

import java.lang.reflect.InvocationTargetException;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.struts2.ServletActionContext;

import com.heima.domain.User;
import com.itheima.service.UserService;
import com.opensymphony.xwork2.ActionSupport;

/**
 * 用戶登錄模塊控制器
 * @author Administrator
 *
 */
public class UserAction extends ActionSupport{
    /**
     * 處理登錄功能
     * @return
     */
    public String log

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在iPhone中調試,大體上與上文 安卓中的移動頁面調試 類似,區別主要是iOS系統中的一些限制,導致某些工具無法使用。 本文基於此,簡要介紹在iPhone中如何調試頁面。 最終可以實現在Mac平臺使用Safari(或結合ios_webkit_dubug_proxy使用Chrome)調試手機中Saf ...
  • 筆者最近在做一個項目的後臺,用到了EasyUI的datagrid控制項,並開啟了行內編輯功能,實際上也就是使用了edatagird這個空間,引用了edatagrid.js,一切似乎都做的順風順水,添加數據、修改數據都沒有問題,然而到刪除數據的時候居然沒有反應,折騰了好幾天也沒有任何進展。截圖如下: 前 ...
  • css: *{ margin: 0; padding: 0; /* 禁止用戶點選網頁內容 */ -webkit-touch-callout:none; -webkit-user-select:none; -khtml-user-select:none; -moz-user-select:none; ...
  • 內容:String Buffer/String Builder方法 + 兩個簡單練習是緩衝區,最後都會轉成字元串處理,有局限性###########方法添加元素: .append()插入元素: .insert(index,value)刪除元素: .delete(start,end)修改元素: .re ...
  • 從零開發項目概述 最近這一直在複習數據結構和演算法,也就是前面發出去的排序演算法 "八大基礎排序總結" , "Java實現單向鏈表" , "棧和隊列就是這麼簡單" , "十道簡單演算法題" 等等... 被虐得不要不要的,即使是非常簡單有時候繞半天,想不明白。 本來這篇博文是想留到我最後Java基礎複習完再 ...
  • 學習目的: 爬蟲有請求庫(request、selenium)、解析庫、存儲庫(MongoDB、Redis)、工具庫,此節學習安裝常用庫的安裝 正式步驟 Step1:urllib和re庫 導入時,沒有回顯,就表示安裝正確,可以正常使用 Step2:requests庫安裝 Step3:selenium庫 ...
  • Makedown === [TOC] 介紹 Makedown的創建者是 "John Gruber" Q:什麼是markdown呢? markdown和html類似是markup language(標記語言)的一種,使用特有標記語法來編排文本格式,然後通過標記語言的解釋引擎[^footnote1],將 ...
  • 前言 LZ 15年本科畢業,不知不覺3年過去了,去年底裸辭回到成都來發展,年後開始找工作,面試了幾家公司,現在整理整理做個總結,也方便規划下一個3到5年以及和廣大想要進階的Java程式員同胞們共勉。 首先談談裸辭的感受吧:走之前部門很多同事都神秘兮兮的過來問我“小伙子下一家在哪呀?”,LZ很直白:“ ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...