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

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默认扫描的包含struts, struts2, action 或 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
而struts, struts2, action 或 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”)

(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 |
|---|---|
|
Group of @Action annotations, maps multiple URLs to the same action |
|
|
Defines the URL of an action |
|
|
Gropup of @InterceptorRef annotations |
|
|
Interceptor, or interceptor stack to be applied to at action |
|
|
Group of @Result annotations |
|
|
Defines a result for an action |
|
|
Set the path of the action URL (used to overwrite the default) |
|
|
Set where the results are located (used to overwrite the default) |
|
|
Set the parent package of the actions (used to overwrite the default) |
|
|
Group of @ExceptionMapping annotations |
|
|
Defines an exception mapping |
(b)Workflow 注解
|
Annotation |
Description |
|---|---|
|
Defines what method to execute, or result to be returned if there are validation errors |
(c) Interceptor 注解
|
Annotation |
Description |
|---|---|
|
Marks a action method that needs to be executed after the result. |
|
|
Marks a action method that needs to be executed before the main action method. |
|
|
Marks a action method that needs to be executed before the result. |
(d) Validation 注解
|
Annotation |
Description |
|---|---|
|
Checks if there are any conversion errors for a field. |
|
|
Checks that a date field has a value within a specified range. |
|
|
Checks that a double field has a value within a specified range. |
|
|
Checks that a field is a valid e-mail address. |
|
|
Validates an expression. |
|
|
Uses an OGNL expression to perform its validator. |
|
|
Checks that a numeric field has a value within a specified range. |
|
|
Validates a regular expression for a field. |
|
|
Checks that a field is non-null. |
|
|
Checks that a String field is not empty. |
|
|
Checks that a String field is of the right length. |
|
|
Checks that a field is a valid URL. |
|
|
Marker annotation for validation at Type level. |
|
|
Used to group validation annotations. |
|
|
Invokes the validation for a property's object type. |
|
|
Use this annotation for your custom validator types. |
(e)Type Convention 注解
|
Annotation |
Description |
|---|---|
|
Marker annotation for type conversions at Type level. |
|
|
For Collection and Map types: Create the types within the Collection or Map, if null. |
|
|
For Generic types: Specify the element type for Collection types and Map values. |
|
|
For Generic types: Specify the key type for Map keys. |
|
|
For Generic types: Specify the key property name value. |
|
|
Used for class and application wide conversion rules. |
接下来将用注解进行开发。
未完,待续。
菜鸟学Struts2——零配置(Convention )的更多相关文章
- Struts2 Convention Plugin ( struts2 零配置 )
Struts2 Convention Plugin ( struts2 零配置 ) convention-plugin 可以用来实现 struts2 的零配置.零配置的意思并不是说没有配置,而是通过约 ...
- 菜鸟学Struts2——Interceptors
昨天学习Struts2的Convention plugin,今天利用Convention plugin进行Interceptor学习,虽然是使用Convention plugin进行零配置开发,这只是 ...
- Struts2零配置介绍(约定访问)
从struts2.1开始,struts2 引入了Convention插件来支持零配置,使用约定无需struts.xml或者Annotation配置 需要 如下四个JAR包 插件会自动搜索如下类 act ...
- struts2 零配置
一.新建一个web项目,命名为:struts2 二.导入strut2所需的jar包 所需jar下载:http://pan.baidu.com/s/1dDxP4Z3 三.配置struts2的启动文件,在 ...
- spring+hibernate+struts2零配置整合
说句实话,很久都没使用SSH开发项目了,但是出于各种原因,再次记录一下整合方式,纯注解零配置. 一.前期准备工作 gradle配置文件: group 'com.bdqn.lyrk.ssh.study' ...
- 注解实现struts2零配置
零配置指的是不经过配置文件struts.xml配置Action 首先:导入jar struts2-convention-plugin-2.3.24.1.jar package com.action ...
- struts2零配置參考演示样例
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2 ...
- 菜鸟学Struts2——Results
在对Struts2的Action学习之后,对Struts2的Result进行学习.主要对Struts2文档Guides中的Results分支进行学习,如下图: 1.Result Types(Resul ...
- 菜鸟学Struts2——Actions
在对Struts2的工作原理学习之后,对Struts2的Action进行学习.主要对Struts2文档Guides中的Action分支进行学习,如下图: 1.Model Driven(模型驱动) St ...
随机推荐
- NoSql数据库使用半年后在设计上面的一些心得
NoSql数据库这个概念听闻许久了,也陆续看到很多公司和产品都在使用,优缺点似乎都被分析的清清楚楚.但我心里一直存有一个疑惑,它的出现究竟是为了解决什么问题? 这个疑惑非常大,为此我看了很多分析文章, ...
- 【原】Github+Hexo+NextT搭建个人博客
摘要 GitHub 是一个开源项目的托管网站,相信很多人都听过.在上面有很多高质量的项目代码,我们也可以把自己的项目代码托管到GitHub,与朋友们共享交流.GitHub Pages 是Github为 ...
- Unity游戏内版本更新
最近研究了一下游戏内apk包更新的方法. ios对于应用的管理比较严格,除非热更新脚本,不太可能做到端内大版本包的更新.然而安卓端则没有此限制.因此可以做到不跳到网页或应用商店,就覆盖更新apk包. ...
- Web Api 入门实战 (快速入门+工具使用+不依赖IIS)
平台之大势何人能挡? 带着你的Net飞奔吧!:http://www.cnblogs.com/dunitian/p/4822808.html 屁话我也就不多说了,什么简介的也省了,直接简单概括+demo ...
- 年度巨献-WPF项目开发过程中WPF小知识点汇总(原创+摘抄)
WPF中Style的使用 Styel在英文中解释为”样式“,在Web开发中,css为层叠样式表,自从.net3.0推出WPF以来,WPF也有样式一说,通过设置样式,使其WPF控件外观更加美化同时减少了 ...
- 【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇一:WPF常用知识以及本项目设计总结
篇一:WPF常用知识以及本项目设计总结:http://www.cnblogs.com/baiboy/p/wpf.html 篇二:基于OneNote难点突破和批量识别:http://www.cnblog ...
- Java compiler level does not match解决方法
从别的地方导入一个项目的时候,经常会遇到eclipse/Myeclipse报Description Resource Path Location Type Java compiler level d ...
- 创建ABPboilerplate模版项目
本文是根据角落的白板报的<通过ABPboilerplate模版创建项目>一文的学习总结,感谢原文作者角落的白板报. 1 准备 开发环境: Visual Studio 2015 update ...
- jQuery可拖拽3D万花筒旋转特效
这是一个使用了CSS3立体效果的强大特效,本特效使用jQuery跟CSS3 transform来实现在用户鼠标按下拖动时,环形图片墙可以跟随鼠标进行3D旋转动画. 效果体验:http://hovert ...
- Jexus 服务器部署导航
说明:本索引只是方便本人查找,不涉及版权问题,所有博客,还是到元博客地址访问. <script async src="//pagead2.googlesyndication.com/p ...