java框架之Struts2(1)-簡介及入門

簡介

Struts2 是一個基於 MVC 設計模式的 Web 應用框架,它本質上至關於一個 servlet,在 MVC 設計模式中,Struts2 做爲控制器 (Controller) 來創建模型與視圖的數據交互。html

Struts2 是 Struts1 的下一代產品,是在 struts1和 WebWork 的技術基礎上進行了合併的全新的 Struts2 框架。其全新的 Struts2 的體系結構與 Struts1 的體系結構差異巨大。java

Struts2 以 WebWork 爲核心,採用攔截器的機制來處理用戶的請求,這樣的設計也使得業務邏輯控制器可以與ServletAPI徹底脫離開,因此 Struts2 能夠理解爲 WebWork 的更新產品。web

雖然從 Struts1到 Struts2 有着太大的變化,可是相對於 WebWork,Struts2 的變化很小。spring

開發環境官網下載,下面示例使用版本爲 struts-2.3.37,點擊可直接下載 。express

快速開始

導包

這裏能夠直接導入解壓目錄下 apps/struts2-blank.war 中全部 jar 。apache

Hello Struts2

代碼

一、編寫 Action 類:設計模式

package com.zze.action;

public class HelloAction {
    public String execute() {
        System.out.println("hello Struts 2");
        return "hello";
    }
}
com.zze.action.HelloAction

二、新建要跳轉到的 jsp 頁:瀏覽器

<%--
  Created by zze.
  Date: 2019/1/22
  Time: 10:48
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Hello</title>
</head>
<body>
<h3>hello Struts2</h3>
</body>
</html>
WEB-INF/hello.jsp

三、在 src 下新建以下配置文件:tomcat

<?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>
    <!--配置 Strut 2 的包-->
    <package name="test1" extends="struts-default" namespace="/">
        <!--配置 Action-->
        <action name="hello" class="com.zze.action.HelloAction">
            <result name="hello">/WEB-INF/hello.jsp</result>
        </action>
    </package>
</struts>
struts.xml

四、在 web.xml 中配置核心過濾器:app

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

五、部署到 tomcat,運行:

執行流程

一、首先瀏覽器請求 localhost:8080/hello 。

二、在 web.xml 中配置的核心過濾器會攔截到請求。

三、攔截器會解析 url,在 struts.xml 中根據 package 標籤上的 namespace 屬性和  action 標籤上的 name 找到對應請求路徑的 action。

四、執行對應 action 標籤對應 Action 類對象的 execute 方法。

五、execute 方法返回字符串,這個字符串與 action 標籤下的 result 標籤的 name 匹配。

六、返回匹配到的 result 標籤中定義的路徑對應的 jsp。

七、瀏覽器接收、渲染。

配置文件的加載順序

已經知道 Struts2 的入口就是核心過濾器 org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter ,在程序啓動時會執行過濾器的 init 方法,及會執行核心過濾器的 init 方法:

 1 public void init(FilterConfig filterConfig) throws ServletException {
 2     InitOperations init = new InitOperations();
 3     Dispatcher dispatcher = null;
 4     try {
 5         FilterHostConfig config = new FilterHostConfig(filterConfig);
 6         init.initLogging(config);
 7         dispatcher = init.initDispatcher(config);
 8         init.initStaticContentLoader(config, dispatcher);
 9 
10         prepare = new PrepareOperations(dispatcher);
11         execute = new ExecuteOperations(dispatcher);
12         this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
13 
14         postInit(dispatcher, filterConfig);
15     } finally {
16         if (dispatcher != null) {
17             dispatcher.cleanUpAfterInit();
18         }
19         init.cleanup();
20     }
21 }
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter#init

而 Struts2 相關的配置文件就是在第 7 行的 init.initDispatcher(config) 中加載的:

1 public Dispatcher initDispatcher( HostConfig filterConfig ) {
2     Dispatcher dispatcher = createDispatcher(filterConfig);
3     dispatcher.init();
4     return dispatcher;
5 }
org.apache.struts2.dispatcher.ng.InitOperations#initDispatcher

再看到 dispatcher.init() :

 1 public void init() {
 2 
 3     if (configurationManager == null) {
 4         configurationManager = createConfigurationManager(DefaultBeanSelectionProvider.DEFAULT_BEAN_NAME);
 5     }
 6 
 7     try {
 8         init_FileManager();
 9         init_DefaultProperties(); // [1]
10         init_TraditionalXmlConfigurations(); // [2]
11         init_LegacyStrutsProperties(); // [3]
12         init_CustomConfigurationProviders(); // [5]
13         init_FilterInitParameters() ; // [6]
14         init_AliasStandardObjects() ; // [7]
15 
16         Container container = init_PreloadConfiguration();
17         container.inject(this);
18         init_CheckWebLogicWorkaround(container);
19 
20         if (!dispatcherListeners.isEmpty()) {
21             for (DispatcherListener l : dispatcherListeners) {
22                 l.dispatcherInitialized(this);
23             }
24         }
25         errorHandler.init(servletContext);
26 
27     } catch (Exception ex) {
28         if (LOG.isErrorEnabled())
29             LOG.error("Dispatcher initialization failed", ex);
30         throw new StrutsException(ex);
31     }
32 }
org.apache.struts2.dispatcher.Dispatcher#init

在上述 9-14 行就會加載  Struts2 相關配置文件,以下:

init_DefaultProperties(); // [1] 加載 struts2-core-2.3.37.jar!/org/apache/struts2/default.properties
init_TraditionalXmlConfigurations(); // [2] 加載 struts2-core-2.3.37.jar!/struts-default.xml、src:struts-plugin.xml、src:struts.xml
init_LegacyStrutsProperties(); // [3] 加載 src:struts.properties
init_CustomConfigurationProviders(); // [5] 加載配置提供類
init_FilterInitParameters() ; // [6] 加載 web.xml中 過濾器初始化參數
init_AliasStandardObjects() ; // [7] 加載 Bean 對象
總結上述,配置文件的加載順序爲:

-> default.properties

-> struts-default.xml

-> struts-plugin.xml

-> struts.xml

-> struts.properties

-> web.xml

標綠的是咱們可配置的。

注意:後配置的常量會覆蓋以前配置的常量。

配置相關

struts.xml

package標籤

package 標籤稱爲包,這個包與 Java 中的包概念不一致,它是爲了更好地管理 action 的配置。

屬性:

  • name:包的名稱,只要在一個項目中不重名便可。
  • extends:繼承一個包,一般值爲 "struts-default"。
  • namespace:名稱空間,與 action 標籤的 name 屬性共同組成訪問路徑。
    名稱空間匹配的優先級從高到低有以下三種:

        一、帶名稱的名稱空間:namespace="/aaa"。

        二、根名稱空間:namespace="/"。

        三、默認名稱空間:namespace=""。

  • abstract:標識當前包是用來被繼承的。

action標籤

配置 action 類。

屬性:

  • name:與 package 標籤上的 namespace 屬性共同組成訪問路徑。
  • class:Action 類的全路徑。
  • method:方法名,標識執行 Action 中哪一個方法,默認值爲 "execute" 。
  • converter:用於配置類型轉換器。  

constant標籤

配置常量。

屬性:

  • name:常量名。
  • value:常量值。

include標籤

分模塊開發時使用,用來引入其它配置文件。

屬性:

  • file:要引入的配置文件路徑,如:"com/zze/config/demo1/struts.xml"。

常量配置

默認常量

在 Struts2 中提供了很是多默認的常量,在 "struts2-core-2.3.37.jar!/org/apache/struts2/default.properties" 中,以下:

#
# $Id$
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#  http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#
### START SNIPPET: complete_file

### Struts default properties
###(can be overridden by a struts.properties file in the root of the classpath)
###

### This can be used to set your default locale and encoding scheme
# struts.locale=en_US
struts.i18n.encoding=UTF-8

### if specified, the default object factory can be overridden here
### Note: short-hand notation is supported in some cases, such as "spring"
###       Alternatively, you can provide a com.opensymphony.xwork2.ObjectFactory subclass name here
# struts.objectFactory = spring

### specifies the autoWiring logic when using the SpringObjectFactory.
### valid values are: name, type, auto, and constructor (name is the default)
struts.objectFactory.spring.autoWire = name

### indicates to the struts-spring integration if Class instances should be cached
### this should, until a future Spring release makes it possible, be left as true
### unless you know exactly what you are doing!
### valid values are: true, false (true is the default)
struts.objectFactory.spring.useClassCache = true

### ensures the autowire strategy is always respected.
### valid values are: true, false (false is the default)
struts.objectFactory.spring.autoWire.alwaysRespect = false

### By default SpringObjectFactory doesn't support AOP
### This flag was added just temporally to check if nothing is broken
### See https://issues.apache.org/jira/browse/WW-4110
struts.objectFactory.spring.enableAopSupport = false

### if specified, the default object type determiner can be overridden here
### Note: short-hand notation is supported in some cases, such as "tiger" or "notiger"
###       Alternatively, you can provide a com.opensymphony.xwork2.util.ObjectTypeDeterminer implementation name here
### Note: By default, com.opensymphony.xwork2.util.DefaultObjectTypeDeterminer is used which handles type detection
###       using generics. com.opensymphony.xwork2.util.GenericsObjectTypeDeterminer was deprecated since XWork 2, it's
###       functions are integrated in DefaultObjectTypeDeterminer now.
###       To disable tiger support use the "notiger" property value here.
#struts.objectTypeDeterminer = tiger
#struts.objectTypeDeterminer = notiger

### Parser to handle HTTP POST requests, encoded using the MIME-type multipart/form-data
# struts.multipart.parser=cos
# struts.multipart.parser=pell
# struts.multipart.parser=jakarta-stream
struts.multipart.parser=jakarta
# uses javax.servlet.context.tempdir by default
struts.multipart.saveDir=
struts.multipart.maxSize=2097152

### Load custom property files (does not override struts.properties!)
# struts.custom.properties=application,org/apache/struts2/extension/custom

### How request URLs are mapped to and from actions
#struts.mapper.class=org.apache.struts2.dispatcher.mapper.DefaultActionMapper

### Used by the DefaultActionMapper
### You may provide a comma separated list, e.g. struts.action.extension=action,jnlp,do
### The blank extension allows you to match directory listings as well as pure action names
### without interfering with static resources, which can be specified as an empty string
### prior to a comma e.g. struts.action.extension=, or struts.action.extension=x,y,z,,
struts.action.extension=action,,

### Used by FilterDispatcher
### If true then Struts serves static content from inside its jar.
### If false then the static content must be available at <context_path>/struts
struts.serve.static=true

### Used by FilterDispatcher
### This is good for development where one wants changes to the static content be
### fetch on each request.
### NOTE: This will only have effect if struts.serve.static=true
### If true -> Struts will write out header for static contents such that they will
###             be cached by web browsers (using Date, Cache-Content, Pragma, Expires)
###             headers).
### If false -> Struts will write out header for static contents such that they are
###            NOT to be cached by web browser (using Cache-Content, Pragma, Expires
###            headers)
struts.serve.static.browserCache=true

### Set this to false if you wish to disable implicit dynamic method invocation
### via the URL request. This includes URLs like foo!bar.action, as well as params
### like method:bar (but not action:foo).
### An alternative to implicit dynamic method invocation is to use wildcard
### mappings, such as <action name="*/*" method="{2}" class="actions.{1}">
struts.enable.DynamicMethodInvocation = false

### Set this to true if you wish to allow slashes in your action names.  If false,
### Actions names cannot have slashes, and will be accessible via any directory
### prefix.  This is the traditional behavior expected of WebWork applications.
### Setting to true is useful when you want to use wildcards and store values
### in the URL, to be extracted by wildcard patterns, such as
### <action name="*/*" method="{2}" class="actions.{1}"> to match "/foo/edit" or
### "/foo/save".
struts.enable.SlashesInActionNames = false

### Disables support for action: prefix
struts.mapper.action.prefix.enabled = false

### Blocks access to actions in other namespace than current with action: prefix
struts.mapper.action.prefix.crossNamespaces = false

### use alternative syntax that requires %{} in most places
### to evaluate expressions for String attributes for tags
struts.tag.altSyntax=true

### when set to true, Struts will act much more friendly for developers. This
### includes:
### - struts.i18n.reload = true
### - struts.configuration.xml.reload = true
### - raising various debug or ignorable problems to errors
###   For example: normally a request to foo.action?someUnknownField=true should
###                be ignored (given that any value can come from the web and it
###                should not be trusted). However, during development, it may be
###                useful to know when these errors are happening and be told of
###                them right away.
struts.devMode = false

### when set to true, resource bundles will be reloaded on _every_ request.
### this is good during development, but should never be used in production
### struts.i18n.reload=false

### Standard UI theme
### Change this to reflect which path should be used for JSP control tag templates by default
struts.ui.theme=xhtml
struts.ui.templateDir=template
### Change this to use a different token to indicate template theme expansion
struts.ui.theme.expansion.token=~~~
#sets the default template type. Either ftl, vm, or jsp
struts.ui.templateSuffix=ftl

### Configuration reloading
### This will cause the configuration to reload struts.xml when it is changed
### struts.configuration.xml.reload=false

### Location of velocity.properties file.  defaults to velocity.properties
struts.velocity.configfile = velocity.properties

### Comma separated list of VelocityContext classnames to chain to the StrutsVelocityContext
struts.velocity.contexts =

### Location of the velocity toolbox
struts.velocity.toolboxlocation=

### used to build URLs, such as the UrlTag
struts.url.http.port = 80
struts.url.https.port = 443
### possible values are: none, get or all
struts.url.includeParams = none

### Load custom default resource bundles
# struts.custom.i18n.resources=testmessages,testmessages2

### workaround for some app servers that don't handle HttpServletRequest.getParameterMap()
### often used for WebLogic, Orion, and OC4J
struts.dispatcher.parametersWorkaround = false

### configure the Freemarker Manager class to be used
### Allows user to plug-in customised Freemarker Manager if necessary
### MUST extends off org.apache.struts2.views.freemarker.FreemarkerManager
#struts.freemarker.manager.classname=org.apache.struts2.views.freemarker.FreemarkerManager

### Enables caching of FreeMarker templates
### Has the same effect as copying the templates under WEB_APP/templates
### struts.freemarker.templatesCache=false

### Enables caching of models on the BeanWrapper
struts.freemarker.beanwrapperCache=false

### See the StrutsBeanWrapper javadocs for more information
struts.freemarker.wrapper.altMap=true

### maxStrongSize for MruCacheStorage for freemarker, when set to 0 SoftCacheStorage which performs better in heavy loaded application
### check WW-3766 for more details
struts.freemarker.mru.max.strong.size=0

### configure the XSLTResult class to use stylesheet caching.
### Set to true for developers and false for production.
struts.xslt.nocache=false

### Whether to always select the namespace to be everything before the last slash or not
struts.mapper.alwaysSelectFullNamespace=false

### Whether to allow static method access in OGNL expressions or not
struts.ognl.allowStaticMethodAccess=false

### Whether to throw a RuntimeException when a property is not found
### in an expression, or when the expression evaluation fails
struts.el.throwExceptionOnFailure=false

### Logs as Warnings properties that are not found (very verbose)
struts.ognl.logMissingProperties=false

### Caches parsed OGNL expressions, but can lead to memory leaks
### if the application generates a lot of different expressions
struts.ognl.enableExpressionCache=true

### Indicates if Dispatcher should handle unexpected exceptions by calling sendError()
### or simply rethrow it as a ServletException to allow future processing by other frameworks like Spring Security
struts.handle.exception=true
### END SNIPPET: complete_file
struts2-core-2.3.37.jar!/org/apache/struts2/default.properties

下面描述部分配置的含義:

struts.i18n.encoding=UTF-8 # 處理了 POST 請求中文亂碼
struts.multipart.saveDir= # 上傳文件默認保存位置
struts.multipart.maxSize=2097152 # 上傳文件最大大小
struts.action.extension=action,, # 請求路徑默認後綴爲 action 或空白

修改常量

能夠在三個位置修改常量的值:

  • struts.xml

    直接經過 constant 標籤修改常量。

    <constant name="struts.action.extension" value="do"/>
    struts.xml
  • struts.properties

    需在 src 下新建一個 struts.properties 文件,在其中以 key=value 的形式修改常量,例:

    struts.action.extension=do
    struts.properties
  • 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>do</param-value>
        </init-param>
    </filter>
    web.xml

Action相關

Action的編寫

Action 類的編寫可有三種方式以下:

POJO

Action 類能夠是一個 POJO(簡單的 Java 類),例:

package com.zze.action;

public class HelloAction1 {
    public String execute() {
        System.out.println("hello Struts2");
        return "hello";
    }
}
com.zze.action.HelloAction1

實現Action接口

Action 類也能夠實現 Action 接口,例:

package com.zze.action;

import com.opensymphony.xwork2.Action;

/**
 * 實現接口 Action
 * Action 接口中提供了五個邏輯視圖名稱常量:
 * public static final String SUCCESS = "success";
 * public static final String NONE = "none";
 * public static final String ERROR = "error";
 * public static final String INPUT = "input";
 * public static final String LOGIN = "login";
 */
public class HelloAction2 implements Action {
    @Override
    public String execute() throws Exception {
        System.out.println("hello Struts2");
        return SUCCESS;
    }
}
com.zze.action.HelloAction2

繼承ActionSupport(推薦)

Action 類還能夠繼承  ActionSupport 類,例:

package com.zze.action;

import com.opensymphony.xwork2.ActionSupport;

public class HelloAction3 extends ActionSupport {

    @Override
    public String execute() throws Exception {
        System.out.println("hello Struts2");
        return super.execute();
    }
}
com.zze.action.HelloAction3

Action的訪問

Action 訪問配置也有三種方式,下面經過三種配置來訪問下面 Action。

package com.zze.action;

import com.opensymphony.xwork2.ActionSupport;

public class TestAction extends ActionSupport {
    public String save() {
        System.out.println("from save");
        return NONE;
    }

    public String delete(){
        System.out.println("from delete");
        return NONE;
    }

    public String select(){
        System.out.println("from select");
        return NONE;
    }

    public String update(){
        System.out.println("from update");
        return NONE;
    }
}
com.zze.action.TestAction

method配置

<?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="test" extends="struts-default" namespace="/">
        <!--localhost:8080/save-->
        <action name="save" class="com.zze.action.TestAction" method="save"></action>
        <!--localhost:8080/delete-->
        <action name="delete" class="com.zze.action.TestAction" method="delete"></action>
        <!--localhost:8080/select-->
        <action name="select" class="com.zze.action.TestAction" method="select"></action>
        <!--localhost:8080/update-->
        <action name="update" class="com.zze.action.TestAction" method="update"></action>
    </package>
</struts>
struts.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="test" extends="struts-default" namespace="/">
        <!--localhost:8080/save-->
        <!--localhost:8080/delete-->
        <!--localhost:8080/update-->
        <!--localhost:8080/select-->
        <!--method:{1} 表明 name 中第一個通配符的取值-->
        <action name="*" class="com.zze.action.TestAction" method="{1}"></action>

        <!--localhost:8080/Test_save-->
        <!--localhost:8080/Test_delete-->
        <!--localhost:8080/Test_update-->
        <!--localhost:8080/Test_select-->
        <!--通配符更抽象寫法-->
        <!--<action name="*_*" class="com.zze.action.{1}Action" method="{2}"></action>-->
    </package>
</struts>
struts.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>
    <!--
    設置常量,開啓動態方法訪問
    開啓以後可經過 <host>:<port>/<actionName>!<methodName> 訪問:
    host : ip
    port : 端口
    actionName : action 名稱
    methodName : 要訪問的方法名稱
    -->
    <constant name="struts.enable.DynamicMethodInvocation" value="true"/>
    <package name="test" extends="struts-default" namespace="/">
        <!--localhost:8080/test!save-->
        <!--localhost:8080/test!delete-->
        <!--localhost:8080/test!select-->
        <!--localhost:8080/test!delete-->
        <action name="test" class="com.zze.action.TestAction" method="{1}"></action>
    </package>
</struts>
struts.xml
相關文章
相關標籤/搜索