菜鸟学Struts2——零配置(Convention )

时间:2022-04-02 04:42:23

  又是周末,继续Struts2的学习,之前学习了,Struts的原理,Actions以及Results,今天对对Struts的Convention Plugin进行学习,如下图:

菜鸟学Struts2——零配置(Convention )

Struts Convention支持零配置进行开发,也就是约定约定优于配置的方式。

(1)环境准备

使用Convention Plugin进行开发,需要引入struts2-convention-plugin,完整的pom.xml依赖如下:

 <dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.31</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-convention-plugin</artifactId>
<version>2.3.31</version>
</dependency>

(2)Action约定

convention有自己定义的struts-plugin.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 order="20">
<bean type="com.opensymphony.xwork2.UnknownHandler" name="convention" class="org.apache.struts2.convention.ConventionUnknownHandler"/> <bean type="org.apache.struts2.convention.ActionConfigBuilder" name="convention" class="org.apache.struts2.convention.PackageBasedActionConfigBuilder"/>
<bean type="org.apache.struts2.convention.ActionNameBuilder" name="convention" class="org.apache.struts2.convention.SEOActionNameBuilder"/>
<bean type="org.apache.struts2.convention.ResultMapBuilder" name="convention" class="org.apache.struts2.convention.DefaultResultMapBuilder"/>
<bean type="org.apache.struts2.convention.InterceptorMapBuilder" name="convention" class="org.apache.struts2.convention.DefaultInterceptorMapBuilder"/>
<bean type="org.apache.struts2.convention.ConventionsService" name="convention" class="org.apache.struts2.convention.ConventionsServiceImpl"/> <bean type="com.opensymphony.xwork2.config.PackageProvider" name="convention.packageProvider" class="org.apache.struts2.convention.ClasspathPackageProvider"/>
<bean type="com.opensymphony.xwork2.config.PackageProvider" name="convention.containerProvider" class="org.apache.struts2.convention.ClasspathConfigurationProvider"/> <constant name="struts.convention.actionConfigBuilder" value="convention"/>
<constant name="struts.convention.actionNameBuilder" value="convention"/>
<constant name="struts.convention.resultMapBuilder" value="convention"/>
<constant name="struts.convention.interceptorMapBuilder" value="convention"/>
<constant name="struts.convention.conventionsService" value="convention"/> <constant name="struts.convention.result.path" value="/WEB-INF/content/"/>
<constant name="struts.convention.result.flatLayout" value="true"/>
<constant name="struts.convention.action.suffix" value="Action"/>
<constant name="struts.convention.action.disableScanning" value="false"/>
<constant name="struts.convention.action.mapAllMatches" value="false"/>
<constant name="struts.convention.action.checkImplementsAction" value="true"/>
<constant name="struts.convention.default.parent.package" value="convention-default"/>
<constant name="struts.convention.action.name.lowercase" value="true"/>
<constant name="struts.convention.action.name.separator" value="-"/>
<constant name="struts.convention.package.locators" value="action,actions,struts,struts2"/>
<constant name="struts.convention.package.locators.disable" value="false"/>
<constant name="struts.convention.package.locators.basePackage" value=""/>
<constant name="struts.convention.exclude.packages" value="org.apache.struts.*,org.apache.struts2.*,org.springframework.web.struts.*,org.springframework.web.struts2.*,org.hibernate.*"/>
<constant name="struts.convention.relative.result.types" value="dispatcher,velocity,freemarker"/>
<constant name="struts.convention.redirect.to.slash" value="true"/>
<constant name="struts.convention.action.alwaysMapExecute" value="true"/>
<constant name="struts.mapper.alwaysSelectFullNamespace" value="true"/>
<!-- <constant name="struts.convention.action.includeJars" /> -->
<constant name="struts.convention.action.fileProtocols" value="jar" /> <constant name="struts.convention.classes.reload" value="false" /> <constant name="struts.convention.exclude.parentClassLoader" value="true" /> <package name="convention-default" extends="struts-default">
</package>
</struts>

struts-plugin.xml是会被struts加载的,struts默认回加载"struts-default.xml,struts-plugin.xml,struts.xml";这些XML。这里需要关注的是上面的24行-36行。

Convention默认扫描的包含strutsstruts2action 或 actions的包,在这些包中实现了com.opensymphony.xwork2.Action或者是名字以Action结尾(上面struts-plugin.xml第26行的配置)的类型会被当作Action处理。下面这些类都会被当作Action处理:

 com.example.actions.MainAction
com.example.actions.products.Display (implements com.opensymphony.xwork2.Action)
com.example.struts.company.details.ShowCompanyDetailsAction

strutsstruts2action 或 actions下面的子包会被当作命名空间(namespace)

 com.example.actions.MainAction -> /
com.example.actions.products.Display -> /products
com.example.struts.company.details.ShowCompanyDetailsAction -> /company/details

Action类的驼峰命名规则将被“-”分隔(上面struts-plugin.xml第32行配置)如下:

 com.example.actions.MainAction -> /main
com.example.actions.products.Display -> /products/display
com.example.struts.company.details.ShowCompanyDetailsAction -> /company/details/show-company-details

下面是一个Action约定的例子(创建3个Action分别对应上面3种规则):

 package yaolin.core.action;
/**
* /out.action
* @author yaolin
*/
public class OutAction { // 对应第一种规则
public String execute() {
return "success";
}
}
 package yaolin.core.action.ns;
/**
* ns子包名作为命名空间
* /ns/in.action
* @author yaolin
*/
public class InAction { // 对应第二种规则 public String execute() {
return "input";
} // /ns/in!play.action
public String play() {
return "play";
}
}
 package yaolin.core.action.ns;
/**
* ns子包名作为命名空间
* /ns/nil-oay.action
* @author yaolin
*/
public class NilOayAction { // 对应第三种规则 public String execute() {
return "input";
}
}

创建struts.xml 开启“!”方法匹配(这里非必要,用于匹配play方法)

 <!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
</struts>

创建对应result的jsp页面(上面struts-plugin.xml第24行指定了jsp文件的根路径问“/WEB-INF/content”)

菜鸟学Struts2——零配置(Convention )

(2)Result约定

Result约定是在action名字之后加上“-result”,即如果InAction方法返回的是"input",那么jsp的名称为"in-input"(“in-input.jsp”),如果方法放回的是“success”则既可以匹配“in.jsp”也可以匹配“in-success.jsp”,如下表:

URL

Result

File that could match

Result Type

/hello

success

/WEB-INF/content/hello.jsp

Dispatcher

/hello

success

/WEB-INF/content/hello-success.htm

Dispatcher

/hello

success

/WEB-INF/content/hello.ftl

FreeMarker

/hello-world

input

/WEB-INF/content/hello-world-input.vm

Velocity

/test1/test2/hello

error

/WEB-INF/content/test/test2/hello-error.html

Dispatcher

详见Struts源码,如下:

 org.apache.struts2.convention.ConventionUnknownHandler#handleUnknownResult
public Result handleUnknownResult(ActionContext actionContext, String actionName,ActionConfig actionConfig, String resultCode) throws XWorkException { PackageConfig pkg = configuration.getPackageConfig(actionConfig.getPackageName());
String ns = pkg.getNamespace();
String pathPrefix = determinePath(actionConfig, ns); Result result = scanResultsByExtension(ns, actionName, pathPrefix, resultCode, actionContext); if (result == null) {
// Try /idx/action/index.jsp
Map<String, ResultTypeConfig> resultsByExtension = conventionsService.getResultTypesByExtension(pkg);
for (String ext : resultsByExtension.keySet()) {
if (LOG.isTraceEnabled()) {
String fqan = ns + "/" + actionName;
LOG.trace("Checking for [#0/index.#1]", fqan, ext);
}
String path = string(pathPrefix, actionName, "/index", nameSeparator, resultCode, ".", ext);
result = findResult(path, resultCode, ext, actionContext, resultsByExtension);
if (result != null) {
break;
}
path = string(pathPrefix, actionName, "/index.", ext);
result = findResult(path, resultCode, ext, actionContext, resultsByExtension);
if (result != null) {
break;
}
}
} if (result == null && resultCode != null) {
//try to find an action to chain to. If the source action is "foo" and
//the result is "bar", we will try to find an action called "foo-bar"
//in the same package
String chainedTo = actionName + nameSeparator + resultCode;
ActionConfig chainedToConfig = pkg.getActionConfigs().get(chainedTo);
if (chainedToConfig != null) {
if (LOG.isTraceEnabled()) {
LOG.trace("Action [#0] used as chain result for [#1] and result [#2]", chainedTo, actionName, resultCode);
}
ResultTypeConfig chainResultType = pkg.getAllResultTypeConfigs().get("chain");
result = buildResult(chainedTo, resultCode, chainResultType, actionContext);
}
}
return result;
}

(3)chain约定

如果Action的方法中返回的result中没有对应的物理视图且这个result跟这个Action类中的某个方法名一致,那么Struts,会自动转化成chain类型,规则是当前action+"-"+result(这里的"-"是上面struts-plugin.xml第32行配置)。

从上面org.apache.struts2.convention.ConventionUnknownHandler#handleUnknownResult的源码中可以看出如果result没有匹配到且“index”和默认拓展etx都没有匹配到result,那么struts会进行chain处理,如果原action是“foo”、result是“bar“,则chain为”foo-bar“,注意这里action是"action",不是Action中的方法("!"后面的),看一下下面的例子:

 package yaolin.core.action.ns;

 import org.apache.struts2.convention.annotation.Action;

 /**
* ns子包名作为命名空间
* /ns/nil-oay.action
* @author yaolin
*/
public class NilOayAction { public String foo() {
return "bar";
} // chain to
@Action("nil-oay-bar")
public String bar() {
return "foo-bar";
}
}

这里foo是NilOayAction的一个方法(非execute),则访问规则为/ns/nil-oay!foo.action,但是没有为其指定"nil-oay-bar.jsp"物理视图,而NilOayAction类中有跟result一样名字的bar函数。那么Struts会将其转化为Chain,上一个action名称,即"nil-oay"(这里不是foo,foo是方法名,不是action),再加入result,即"bar",组成"nil-oay-bar",这样会访问上面的bar()方法,bar()方法@Action("nil-oay-bar"),这时返回result="foo-bar",对应的物理视图为"/WEB-INF/content/nil-oay-bar-foo-bar.jsp",如果找不到,则会直接找"/WEB-INF/content/foo-bar.jsp"。

(4)注解

(a)Action 注解:

Annotation

Description

Actions Annotation

Group of @Action annotations, maps multiple URLs to the same action

Action Annotation

Defines the URL of an action

InterceptorRefs Annotation

Gropup of @InterceptorRef annotations

InterceptorRef Annotation

Interceptor, or interceptor stack to be applied to at action

Results Annotation

Group of @Result annotations

Result Annotation

Defines a result for an action

Namespace Annotation

Set the path of the action URL (used to overwrite the default)

ResultPath Annotation

Set where the results are located (used to overwrite the default)

ParentPackage Annotation

Set the parent package of the actions (used to overwrite the default)

ExceptionMappings

Group of @ExceptionMapping annotations

ExceptionMapping

Defines an exception mapping

(b)Workflow  注解

Annotation

Description

InputConfig Annotation

Defines what method to execute, or result to be returned if there are validation errors

(c) Interceptor 注解

Annotation

Description

After Annotation

Marks a action method that needs to be executed after the result.

Before Annotation

Marks a action method that needs to be executed before the main action method.

BeforeResult Annotation

Marks a action method that needs to be executed before the result.

(d) Validation 注解

Annotation

Description

ConversionErrorFieldValidator Annotation

Checks if there are any conversion errors for a field.

DateRangeFieldValidator Annotation

Checks that a date field has a value within a specified range.

DoubleRangeFieldValidator Annotation

Checks that a double field has a value within a specified range.

EmailValidator Annotation

Checks that a field is a valid e-mail address.

ExpressionValidator Annotation

Validates an expression.

FieldExpressionValidator Annotation

Uses an OGNL expression to perform its validator.

IntRangeFieldValidator Annotation

Checks that a numeric field has a value within a specified range.

RegexFieldValidator Annotation

Validates a regular expression for a field.

RequiredFieldValidator Annotation

Checks that a field is non-null.

RequiredStringValidator Annotation

Checks that a String field is not empty.

StringLengthFieldValidator Annotation

Checks that a String field is of the right length.

UrlValidator Annotation

Checks that a field is a valid URL.

Validation Annotation

Marker annotation for validation at Type level.

Validations Annotation

Used to group validation annotations.

VisitorFieldValidator Annotation

Invokes the validation for a property's object type.

CustomValidator Annotation

Use this annotation for your custom validator types.

(e)Type Convention 注解

Annotation

Description

Conversion Annotation

Marker annotation for type conversions at Type level.

CreateIfNull Annotation

For Collection and Map types: Create the types within the Collection or Map, if null.

Element Annotation

For Generic types: Specify the element type for Collection types and Map values.

Key Annotation

For Generic types: Specify the key type for Map keys.

KeyProperty Annotation

For Generic types: Specify the key property name value.

TypeConversion Annotation

Used for class and application wide conversion rules.

接下来将用注解进行开发。

未完,待续。

菜鸟学Struts2——零配置(Convention )的更多相关文章

  1. Struts2 Convention Plugin &lpar; struts2 零配置 &rpar;

    Struts2 Convention Plugin ( struts2 零配置 ) convention-plugin 可以用来实现 struts2 的零配置.零配置的意思并不是说没有配置,而是通过约 ...

  2. 菜鸟学Struts2——Interceptors

    昨天学习Struts2的Convention plugin,今天利用Convention plugin进行Interceptor学习,虽然是使用Convention plugin进行零配置开发,这只是 ...

  3. Struts2零配置介绍(约定访问)

    从struts2.1开始,struts2 引入了Convention插件来支持零配置,使用约定无需struts.xml或者Annotation配置 需要 如下四个JAR包 插件会自动搜索如下类 act ...

  4. struts2 零配置

    一.新建一个web项目,命名为:struts2 二.导入strut2所需的jar包 所需jar下载:http://pan.baidu.com/s/1dDxP4Z3 三.配置struts2的启动文件,在 ...

  5. spring&plus;hibernate&plus;struts2零配置整合

    说句实话,很久都没使用SSH开发项目了,但是出于各种原因,再次记录一下整合方式,纯注解零配置. 一.前期准备工作 gradle配置文件: group 'com.bdqn.lyrk.ssh.study' ...

  6. 注解实现struts2零配置

    零配置指的是不经过配置文件struts.xml配置Action 首先:导入jar   struts2-convention-plugin-2.3.24.1.jar package com.action ...

  7. struts2零配置參考演示样例

    <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2 ...

  8. 菜鸟学Struts2——Results

    在对Struts2的Action学习之后,对Struts2的Result进行学习.主要对Struts2文档Guides中的Results分支进行学习,如下图: 1.Result Types(Resul ...

  9. 菜鸟学Struts2——Actions

    在对Struts2的工作原理学习之后,对Struts2的Action进行学习.主要对Struts2文档Guides中的Action分支进行学习,如下图: 1.Model Driven(模型驱动) St ...

随机推荐

  1. Makefile

    原文链接:http://www.orlion.ga/816/ 一.基本规则 对于一个拥有多个文件的c项目,编译时可能是这样的指令: gcc main.c stack.c -o main 如果编译之后又 ...

  2. wpf中textbox与textblock有什么区别

    textbox是windows.form控件,textblock是WPF控件. 功能类似,但后者功能更强,也节省系统资源 wpf是基于directx技术的系统,向后兼容性更好. textblock只用 ...

  3. POJ 3349 HASH

    题目链接:http://poj.org/problem?id=3349 题意:你可能听说话世界上没有两片相同的雪花,我们定义一个雪花有6个瓣,如果存在有2个雪花相同[雪花是环形的,所以相同可以是旋转过 ...

  4. Egret 双端接入爱贝支付遇到的问题

    首先要为 egret 工程引入第三方库: Egret 接第三方库:http://edn.egret.com/cn/index.php?g=&m=article&a=index& ...

  5. 搭建Hadoop集群 &lpar;一&rpar;

    上面讲了如何搭建Hadoop的Standalone和Pseudo-Distributed Mode(搭建单节点Hadoop应用环境), 现在我们来搭建一个Fully-Distributed Mode的 ...

  6. shop&lowbar;z 一套非常适合二次开发的php后台管理系统

    QQ群:247823727 如果你需要定制某些功能开联系群主,价格实惠,后期交接完善,有上手培训 shop_z基础thinkphp5  php7上开发运行,速度杠杠的 地址:https://gitee ...

  7. 【Java】操作mysql数据库

    package bd; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; im ...

  8. loadrunner录制成功但脚本内容为空,无任何代码&sol;&sol;脚本中包含乱码

    使用loadrunner录制脚本,录制过程中也会显示“正在录制…”,并且有(XX个事件).但是脚本录制结束之后,脚本中没有任何内容,没有代码显示. 解决方法: 在脚本录制程序VU generator中 ...

  9. 组合数模板 - Lucas

    2017-08-10 19:35:32 整理者:pprp 用于计算C(m,n) % p 代码如下: //lucas #include <iostream> using namespace ...

  10. 算法模板の数学&amp&semi;数论

    1.求逆元 int inv(int a) { ) ; return (MOD - MOD / a) * inv(MOD % a); } 2.线性筛法 bool isPrime[MAXN]; int l ...