如何使用Convention
1. 将struts-Convention-plugin-2.1.6.jar文件复制到WEB-INF/lib路径下
2. 对于Convention插件而言,它会自动搜索位于action,actions,struts,struts2包下的所有java类,Convention插件会把如下两种java类当成Action处理:
1) 所有实现了com.opensymphony.xwork2.Action的java类
2) 所有类名以Action结尾的java类
3. Convention插件还允许设置如下三个常量:
1) struts.Convention.exclude.packges:指定不扫描哪些包下的java类,位于这些包结构下的java类将不会自动映射成Action;
2) struts.convention.package.locators:Convention插件使用该常量指定的包作为搜寻Action的根包。对于actions.fore.LoginAction类,按约定原本应映射到/fore/login;如果将该常量设为fore,则该Action将会映射到/login
3) struts.convention.action.packages:Convention插件以该常量指定包作为根包来搜索Action类。Convention插件除了扫描action,actions,struts,struts2四个包的类以外,还会扫描该常量指定的一个或多个包,Convention会试图从中发现Action类。
注意:struts.convention.package.locators和struts.convention.action.packages两个常量的作用比较微妙,开发者在利用这两个常量时务必小心。
如:下面Action所在包被映射的命名空间如下:
com.fun.actions.LoginAction 映射到 /
com.fun.actions.myoffice.CarInfoAction 映射到 /myoffice
com.fun.struts.myoffice.EntINfoAction 映射到 /myofiice
4. 映射Action的name时,遵循如下两步规则:
1) 如果该Action类名包含Action后缀,将该Action类名的Action后缀去掉。否则不做任何处理。
2) 将Action类名的驼峰写法(每个单词首字母大写、其他字母小写的写法)转成中画线写法(所有字母小写,单词与单词之间以中画线隔开)
如:LoginAction映射的Acion的name属性为login,GetBooks映射的Action的name的属性为get-books,AddEmployeeAction映射的Action的name属性为add-employee
5. 默认情况下。Convention总会到WEB应用的WEB-INF/content路径下定位物理资源,定位资源的约定是:actionRUL+resultCODE+suffix。当某个逻辑视图找不到对应的试图资源时,Convention会自动视图使用ActionURL+suffix作为物理视图资源。
如:actions.fore.LoginAction 返回success字符串时,Convention优先考虑使用WEB-INF/content/fore目录下的login-success.jsp作为视图资源。如果找不到该文件,login.jsp也可作为对应的试图资源。如果返回input字符串,Convention会将WEB-INF/content/fore里面查找login-input.jsp
6. 为了看到struts2应用里的Action等各种资源的影射情况,struts2提供了Config Browser插件。使用方法,将struts2-config-browser-plugin-2.1.6.jar文件复制到struts2应用的WEB-INF/lib目录中。
打开首页地址:http://localhost:8080/应用名字/config-browser/actionNames.action这里可以看到Config Browser插件的首页。
注意:这里不管开发者是否使用struts.xml文件进行配置,一样可以看到struts的配置信息。
7.Action链的约定
如果希望一个Action处理结束后不是进入一个试图页面,而是进行另一个Action形成的Action链。通过Convention插件则只需遵守如下三个约定即可。
1) 第一个Action返回的逻辑视图字符串没有对应的视图资源
2) 第二个Action与第一个Action处在同一个包下
3) 第二个Action影射的URL为:firstActionURL+resultCODE
如,第一个Action为OneAction,里面有个方法返回为“two”,那么就得保证,WEB-INF/content/下没有one.jsp或one-two.jsp 对于第二个action 它的名字应该是OneTwoAction,而对应的url应该是:“one-two.action”
注意:由于Convention插件根据Action和jsp页面来动态生成映射的,因此不管是Acion的改变,还是JSP页面的改变都需要Convention插件重新加载映射。那么只要我们为struts2应用配置如下两个常量就可以了。
< !--配置struts2应用于开发模式--!>
<constant name=”struts.devMode” value=”true”/>
< !—配置Convention插件自动重加载映射--!>
<constant name=”struts.convention.classes.reload” value=”true”/>
几个重要的常量
struts.convention.action.disableJarScanning---是否从包中搜索Action
struts.convention.action.package--------Convention插件以该常量指定包作为根包
struts.convention.result.path ---设置Convention插件定位视图资源的根路径。默认值为/WEB-INF/content
struts.convention.result.flatLayout—如果是为false则可以将试图放置Action对应的目录下,无需放入WEB-INF/content
8. Convention的Annotation
1) 与Action相关的两个Annotation是@Action 和@Actions
2) @Action中可指定一个value属性。类似于指定<action name=””/>属性值
3) @Action中还可以指定一个params属性,该属性是一个字符串数组,用于该Acion指定的参数名和参数值。params属性应遵守如下格式:{“name1”,”value1”,”name2”,”value2”}
4) @Actions 也用于修饰Action类里的方法,用于将该方法映射到多个URL.@Actions用于组织多个@Action.因此它可将一个方法映射成多个逻辑Action。
如:
- package com.fun.actions;
- import org.apache.struts2.convention.annotation.Action;
- import org.apache.struts2.convention.annotation.Actions;
- import com.fun.service.LoginService;
- import com.opensymphony.xwork2.ActionSupport;
- publicclass LoginActionextends ActionSupport {
- private String str;
- @Actions({
- @Action(value="login1",params={"str","这是已经注入的了!"}),
- @Action(value="login2")
- })
- public String login(){
- return"str";
- }
- @Action(value="ggg")
- public String abc(){
- return"abc";
- }
- public String getStr() {
- return str;
- }
- publicvoid setStr(String str) {
- this.str = str;
- }
- }
我们可以通过/login1.action访问,而在访问时,str这个属性已经有值,为str=”这是已经注入的!” 返回的视图是login1-str.jsp
当我们用/login2.action访问时,str的值为null。返回的视图为 login2-str.jsp
而我们通过/ggg.action调用的是abc()方法,返回的视图为/ggg-abc.jsp
9. 与Result配置相关的Annotation
1)@ResultPath @Result 和Results
2)@Results用于组织多个@Result因此它只需指定一个value属性值,该value属性值为多个@Result
3)@Result相当于struts.xml文件中的<result/>元素的做哟欧诺个。使用@Result必须指定一个name属性,相当于<result name=””/>另外,它还有几个可选的属性。
☆ type 相当于<result type=””/>指定返回视图资源的类型
☆ location 相当于<result>…..</result>中间部分,用于指定实际视图位置
☆ params:该属性相当于<result/>元素里多个<param../>子元素的作用,用于为该Result指定参数值。该属性应满足{“name1”,”value1”,”name2”,”value2”}格式
4)@Result有以下两种用法
1 Action级的Result映射:以@Actions组合多个@Action后修饰的Action类。这种Result映射对该Action里的所有方法都有效。
2方法级Result映射:将多个@Result组成数组后作为@Action的results属性值。这种Result映射仅对被修饰的方法有效。
5)@ResultPath则用于修饰包和Action类,用于改变被修饰Action所对应的物理视图资源的根路径。举例说:默认情况下,Convention都会到WEB-INF/content路径下找物理视图资源,一旦我们使用@ResultPath(“/abc”)修饰该Action,系统将回到abc目录下寻找物理视图资源。举例:在默认情况下,Convention都会到WEB-INF/content路径下需找物理视图资源,一旦我们使用@ResultPath(“/abc”)修饰该Action,系统会到abc目录下寻找物理视图资源。
10. 与包和命名空间相关的Annotation:
@Namespace:修饰Action类或其所在的包。该Annotation中指定一个value属性值,用于指定被修饰的Action所在的命名空间
@Namespaces:修饰Action类或其所在的包,用于组合多个@Namespace
@ParentPackage: 用于指定被修饰的Action所在包的夫包。
11. 异常处理相关的Annotation
@ExceptionMappings 用于组织多个@ExceptionMapping,因此它只需指定一个value属性值,该value属性值为多个@ExceptionMapping。
@ExceptionMapping 用于定义异常类和物理视图之间的对应关系,也相当于struts.xml文件里<exception-mapping../>元素的作用 使用时,必须注意以下两个属性:
exception: 用于指定异常类
result : 用于指定逻辑视图
@ExceptionMpping有如下两种用法
Action级的异常定义:以@ExceptionMappings组合多个@ExceptionMapping后修饰的Action类。这种异常定义对Action中的所有方法有效
方法级的异常定义: 将多个@ExceptionMapping组成数组后作为@Action的exceptionMappings属性值,这种异常定义仅对被修饰的方法有效。
12.拦截器配置相关的Annotation
与拦截器配置的Annotation有@InterceptorRef、@InterceptorRefs和@DefaultInterceptorRef
@InterceptorRefs用于组织多个@InterceptorRef,因此它只需要指定一个value属性值,该value属性值为多个@InterceptorRef
@InterceptorRef用于为指定Action引用lanjieq或者是拦截器栈。也就相当于strut.xml中位于<action../>元素内部的<interceptor-ref../>子元素的作用。使用@InterceptorRefAnnotation时,必须制定一个value属性,用于指定所引用的拦截器或拦截器栈的名字。相当于<interceptor-ref../>子元素里name属性的作用。
Struts2零配置之Configuration by Convention(一)
随着struts2的不断升级,Struts开始使用convention-plugin代替codebehind-plugin来实现struts的零配置。所谓的零配置并不是任何配置都不需要,而是采用约定大于配置的方式。
在web开发过程中,根据convention-plugin的默认约定,我们不再需要在Struts.xml中配置任何信息。
首先,让我们先来看一下基于convention-plugin实现的Struts"零配置"的HelloWorld。
struts.xml
- <?xmlversion="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>
- <packagename="default"namespace="/"extends="struts-default"/>
- </struts>
<?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" />
</struts>
我的HelloWorld
- package com.example.actions;
- import com.opensymphony.xwork2.ActionSupport;
- public class HelloWorldextends ActionSupport {
- private staticfinallong serialVersionUID = -6662538623355755690L;
- private String message;
- public String getMessage() {
- return message;
- }
- public String execute() {
- if (System.currentTimeMillis() %2 ==0) {
- message = "It's 0";
- return "zero";
- }
- message = "It's 1";
- return SUCCESS;
- }
- }
package com.example.actions;
import com.opensymphony.xwork2.ActionSupport;
public class HelloWorld extends ActionSupport {
private static final long serialVersionUID = -6662538623355755690L;
private String message;
public String getMessage() {
return message;
}
public String execute() {
if (System.currentTimeMillis() % 2 == 0) {
message = "It's 0";
return "zero";
}
message = "It's 1";
return SUCCESS;
}
}
对于一个简单的HelloWorld来讲,struts.xml里面的配置简直精简到了极致。不需要再写一堆一堆的<action>配置了。而我们需要做的只是加入一个struts2-convention-plugin-x.x.x.x.jar。
之所以在HelloWorld中不需要任何配置,是因为struts2-convention-plugin进行了以下一系列的约定。
-
Action location by package naming conventionscom.example. action.Main Actioncom.example. actions.products.Display (implements com.opensymphony.xwork2.Action)com.example. struts.company.details.ShowCompanyDetails Actioncom.example. struts2.company.details.ShowCompanyDetailsAction
- <constantname="struts.convention.package.locators"value="action,actions,struts,struts2"/>
<constant name="struts.convention.package.locators" value="action,actions,struts,struts2"/>
Convention plugin在上述的包及其子包中查找后缀为Action、或者实现了com.opensymphony.xwork2.Action的类。你可以通过设置
struts.convention.action.suffix属性来修改这个配置。Convention plugin默认的配置如下:
- <constantname="struts.convention.action.suffix"value="Action"/>
<constant name="struts.convention.action.suffix" value="Action"/>
- Result (JSP, FreeMarker, etc) location by naming conventions
当在浏览器中输入http://localhost:8080/hello-world访问时,页面会跳转到WEB-INF/content/hello-world.jsp。
默认情况下, Convention plugin假设所有的results存放在WEB-INF/content/下。可以通过设置struts.convention.result.path进行修改。Convention plugin默认的配置如下:
- <constantname="struts.convention.result.path"value="/WEB-INF/content/"/>
<constant name="struts.convention.result.path" value="/WEB-INF/content/"/>
Convention plugin即使在找不到对应的action的情况下,也可以通过Action的URL(这里是/hello-world)找到对应的结果(/hello-world.jsp)。
- Class name to URL naming convention
com.example.actions.MainAction -> /main
com.example.actions.products.Display -> /products/display
com.example.struts.company.details.ShowCompanyDetailsAction -> /company/details/show-company-details
以com.example.struts.company.details.ShowCompanyDetailsAction对应的Action URL为例,Convention plugin会将com.example.struts.company.details.ShowCompanyDetailsAction的struts后的子包转换成命名空间“/company/details/”,然后ShowCompanyDetailsAction中的“Action”后缀去掉,并将驼峰式的命名大写变小写,并在之间加上“-”(当然“-”也是Convention plugin默认的)最终形成/company/details/show-company-details。这就是类名和Action URL之间的“约定”。
- Package name to namespace convention
com.example.actions.MainAction -> /
com.example.actions.products.Display -> /products
com.example.struts.company.details.ShowCompanyDetailsAction -> /company/details
Convention plugin默认将actions、action、struts、struts2作为root Package,那么com.example.actions.MainAction的命名空间即为“/”,而com.example.actions.products.Display的命名空间为“/products”。
Struts2注解配置之@Action(二)
当注解配置能够简化繁杂的xml,你是否想过也要使用注解?
最近对原有项目的框架使用的Struts2进行升级。很早以前就想尝试注解的方式进行配置。但是由于项目稳定性和改配置方式可能带来的问题一直没有进行。但是这不妨碍我们程序员求知的心。哈哈~~~~。
言归正传,开始Struts2最常用的几个注解的学习吧。
-
使用@Action注解改变Convention plug约定的action与url之间的映射关系。
废话少说代码说事儿。
- package com.example.actions;
- import org.apache.struts2.convention.annotation.Action;
- import com.opensymphony.xwork2.ActionSupport;
- public class HelloWorld2extends ActionSupport {
- @Action("/different/url")
- public String execute() {
- return SUCCESS;
- }
- }
package com.example.actions;
import org.apache.struts2.convention.annotation.Action;
import com.opensymphony.xwork2.ActionSupport;
public class HelloWorld2 extends ActionSupport {
@Action("/different/url")
public String execute() {
return SUCCESS;
}
}
本例中在String execute()方法上使用了@Action("/different/url"),它改变了Action 与Action URL之间的映射关系,而这种改变并不是“OverWrite”而是在原来约定的基础上增加了另外一种调用方式。
原本在没有@Action("/different/url")注解的情况下,我们可以在浏览器中输入:http://应用服务器ip:端口/应用/hello-world2,即可访问到com.example.actions.HelloWorld2,并最终显示http://应用服务器ip:端口/应用/hello-world2.jsp页面。(当然这里也可能是html等页面)。
在@Action("/different/url")注解的情况下,除了上述的访问方式外,我们还可以在浏览器中输入:http://应用服务器ip:端口/应用
/different/url,也可访问到com.example.actions.HelloWorld2,但最终显示http://应用服务器ip:端口/应用/different/url.jsp页面。
-
使用@Action注解解决一个ACTION中的一个方法,响应多个不同的URL.
实际项目开发过程中有很大的几率碰到Action的处理相同,但是最终跳转的页面不同的情况。将@Actions和@Action组合起来用即可解决这样的需求。
还是先上代码
- package com.example.actions;
- import org.apache.struts2.convention.annotation.Action;
- import org.apache.struts2.convention.annotation.Actions;
- import com.opensymphony.xwork2.ActionSupport;
- public class HelloWorld3extends ActionSupport {
- private String message;
- public String getMessage() {
- return message;
- }
- @Actions( { @Action("/one/url"),@Action("/another/url") })
- public String execute() {
- message = "经过HelloWorld3的处理";
- return SUCCESS;
- }
- }
package com.example.actions;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Actions;
import com.opensymphony.xwork2.ActionSupport;
public class HelloWorld3 extends ActionSupport {
private String message;
public String getMessage() {
return message;
}
@Actions( { @Action("/one/url"), @Action("/another/url") })
public String execute() {
message = "经过HelloWorld3的处理";
return SUCCESS;
}
}
本例中在String execute()方法上使用了@Actions和@Action注解。其中@Actions注解包含@Action("/one/url")和@Action("/another/url")注解。这样的注解除了可以通过http://应用服务器ip:端口/应用/hello-world3访问com.example.actions.HelloWorld3,并最终显示http://应用服务器ip:端口/应用/hello-world3.jsp之外,还有两种访问方式:
即:
通过http://应用服务器ip:端口/应用/one/url,访问com.example.actions.HelloWorld3,并最终显示http://应用服务器ip:端口/应用/one/url.jsp。
通过http://应用服务器ip:端口/应用/another/url,访问com.example.actions.HelloWorld3,并最终显示http://应用服务器ip:端口/应用/another/url.jsp。
这样就达到了一个ACTION中的一个方法,响应多个不同的URL的效果。
- 使用@Action注解解决一个ACTION中的多个方法,其中每个方法响应不同的URL.
再上一个代码示例:
- package com.example.actions;
- import org.apache.struts2.convention.annotation.Action;
- import com.opensymphony.xwork2.ActionSupport;
- public class HelloWorld4extends ActionSupport {
- private String message;
- public String getMessage() {
- return message;
- }
- @Action("/H4/url")
- public String execute() {
- message = "HelloWorld4 execute()!";
- return SUCCESS;
- }
- @Action("url")
- public String doSomething() {
- message = "HelloWorld4 doSomething()!";
- return SUCCESS;
- }
- }
package com.example.actions;
import org.apache.struts2.convention.annotation.Action;
import com.opensymphony.xwork2.ActionSupport;
public class HelloWorld4 extends ActionSupport {
private String message;
public String getMessage() {
return message;
}
@Action("/H4/url")
public String execute() {
message = "HelloWorld4 execute()!";
return SUCCESS;
}
@Action("url")
public String doSomething() {
message = "HelloWorld4 doSomething()!";
return SUCCESS;
}
}
本例中在String execute()方法上使用了@Action("H4/url")注解。在StringdoSomething()方法中使用了@Action("url")。前者可以通过 http://应用服务器ip:端口/应用/H4/url访问com.example.actions.HelloWorld4中的execute()方法,并最终显示http://应用服务器ip:端口/应用/H4/url.jsp。后者是通过http://应用服务器ip:端口/应用/url来访问com.example.actions.HelloWorld4中的doSomething()方法,并最终显示 http://应用服务器ip:端口/应用/url .jsp。
这个例子里面需要注意的是@Action("/H4/url")和@Action("url")的不同,在“url”前并没有“/”这意味着"url"是基于HelloWorld4的命名空间的。假设HelloWorld4所在的包是com.example.actions.aaa,那么,只有通过http://应用服务器ip:端口/应用/aaa/url才可以访问到com.example.actions.aaa.HelloWorld4,并最终显示http://应用服务器ip:端口/应用/aaa/url.jsp。而“/H4/url”是基于“/”命名空间的。
Struts2注解配置之@Results和@Result(三)
在Struts2注解配置之@Action(二)中对于结果页面我还是采用Convention Plugin的约定,但是这一节我需要利用@Results和@Result改变一下这种约定。以及@Results和@Result对类和方法进行注解后所产生的效果。
还是先看一段代码:
- package com.example.actions;
- import org.apache.struts2.convention.annotation.Action;
- import org.apache.struts2.convention.annotation.Result;
- import org.apache.struts2.convention.annotation.Results;
- import com.opensymphony.xwork2.ActionSupport;
- @Results( { @Result(name ="global", location ="/global.jsp") })
- public class HelloWorld5extends ActionSupport {
- @Action(value = "/H5/url", results = {@Result(name = SUCCESS, location ="/H5/success.jsp"),
- @Result(name ="failure", location ="/H5/fail.jsp") })
- public String execute() {
- if (System.currentTimeMillis() %3 ==0) {
- return "failure";
- } else if (System.currentTimeMillis() %3 ==1) {
- return SUCCESS;
- } else {
- return "global";
- }
- }
- @Action("globalTest")
- public String global() {
- return "global";
- }
- @Action(value = "globalOverWrite", results = { @Result(name ="global", location ="/H5/globalOverWrite.jsp") })
- public String globalOverWrite() {
- return "global";
- }
- }
package com.example.actions;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import com.opensymphony.xwork2.ActionSupport;
@Results( { @Result(name = "global", location = "/global.jsp") })
public class HelloWorld5 extends ActionSupport {
@Action(value = "/H5/url", results = { @Result(name = SUCCESS, location = "/H5/success.jsp"),
@Result(name = "failure", location = "/H5/fail.jsp") })
public String execute() {
if (System.currentTimeMillis() % 3 == 0) {
return "failure";
} else if (System.currentTimeMillis() % 3 == 1) {
return SUCCESS;
} else {
return "global";
}
}
@Action("globalTest")
public String global() {
return "global";
}
@Action(value = "globalOverWrite", results = { @Result(name = "global", location = "/H5/globalOverWrite.jsp") })
public String globalOverWrite() {
return "global";
}
}
- 使用@Result注解改变Convention Plugin的约定跳转页面。
在代码的String execute()方法上进行了 @Action(value = "/H5/url", results = { @Result(name = SUCCESS, location = "/H5/success.jsp"),
@Result(name = "failure", location = "/H5/fail.jsp") })注解。如果@Action(...)没有results = { @Result(name = SUCCESS, location = "/H5/success.jsp"),
@Result(name = "failure", location = "/H5/fail.jsp") },那么依据Convention Plugin的约定,结果页面会是/H5/url.jsp。加上红色字体的部分后,execute()方法执行后,会根据红色字体的配置,将结果跳转到对应的页面。
- 对Action类添加@Result注解,@Result将被Action类中的所有方法所共享。
- 对Action类中的方法添加@Result注解,@Result将只作用于被添加的方法。Action类方法上添加的@Result优先级高于Action类上添加的@Result。(前者覆盖后者)
再仔细观察上述代码的globalOverWrite()方法,该方法也跳转到名字为“global”的页面。但是在该方法上使用了@Action(value = "globalOverWrite", results = { @Result(name = "global", location = "/H5/globalOverWrite.jsp") })注解。并且其中@Result(...)注解中也有一个名字为“global”的结果页面定义。此时,该方法的结果页面就会跳转到/H5/globalOverWrite.jsp页面而不是在类上进行注解时候的“/global.jsp”页面。
Struts2注解配置之@Namespace(四)
还是先看一段代码:
- package com.example.actions;
- import org.apache.struts2.convention.annotation.Action;
- import org.apache.struts2.convention.annotation.Namespace;
- import com.opensymphony.xwork2.ActionSupport;
- @Namespace("/custom")
- public class HelloWorld6extends ActionSupport {
- @Action("/H6/url")
- public String execute() {
- return SUCCESS;
- }
- @Action("url")
- public String doSomething() {
- return SUCCESS;
- }
- }
package com.example.actions;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import com.opensymphony.xwork2.ActionSupport;
@Namespace("/custom")
public class HelloWorld6 extends ActionSupport {
@Action("/H6/url")
public String execute() {
return SUCCESS;
}
@Action("url")
public String doSomething() {
return SUCCESS;
}
}
- 名称空间注释允许操作类名称空间改变而不是使用Convention Plugin约定的Java包的名称。
这是什么原因呢?
关键在于@Action("/H6/url")。此处“/H6/url”是对Action的名称空间进行了完全限定。实验证明@Namespace("/custom")注解对名称空间进行完全限定的不起作用。
- 针对某个Action类进行@Namespace注释后,该注释的效果将应用于该类中所有未完全限定的action URLs
此回合操作验证了一个问题,@Namespace注解已经作用到doSomething()方法上。
仔细观察每一个细节。该方法上有@Action("url")注解。它“url”的前面没有“/”。这是未完全限定的action URL啊。这样正好说明了针对某个Action类进行@Namespace注释后,该注释的效果将应用于该类中所有未完全限定的action URLs。
这样我们在浏览器中输入http://应用服务器ip:端口/应用/cutsom/url访问时,成功。跳转页面为“/custom/url.jsp”。
近日在CSND头条中爆出Struts2高危漏洞造成大规模的信息泄露的消息,让我们这些从事javaweb软件开发,并且应用struts2的人惊出一身冷汗。Struts漏洞影响巨大,受影响站点以电商、银行、门户、政府居多。而且一些自动化、傻瓜化的利用工具开始出现,填入地址可直接执行服务器命令,读取数据甚至直接关机等操作...
我们的很多项目都是基于Struts2的,这也让我们必须对此做出及时正确的响应。及时升级Struts2是最快最能解决根本问题的方式。困难在于各个项目的Struts2原有版本都不尽相同。
本文记录Struts2-2.3.4升级到2.3.15.1并且最少化改动已有工程代码的情况下的步骤
1.删除的jar包
jsonplugin-0.30.jar(此jar由struts2-json-plugin-2.3.15.1.jar代替,如果以前采用过其他jsonplugin插件的话)
2.添加的jar包
commons-lang3-3.1.jar
struts2-json-plugin-2.3.15.1.jar
3.替换的jar包
将原有低版本的ognl-x.x.x.jar替换为ognl-3.0.6.jar
将原有低版本的struts2-core-x.x.x.x.jar替换为struts2-core-2.3.15.1.jar
将原有低版本的xwork-core-x.x.x.x.jar替换为xwork-core-2.3.15.1.jar
将原有低版本的javassist-x.x.x.jar替换为javassist-3.11.0.GA.jar
4.xwork-conversion.properties
注释掉java.lang.Enum=com.opensymphony.xwork2.util.EnumTypeConverter
5.替换工程中所有*.xml Struts配置文件中type="redirect-action"为type="redirectAction",并将xml的头部信息修改为:
- <!DOCTYPE struts PUBLIC
- "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
- "http://struts.apache.org/dtds/struts-2.3.dtd">
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
6.修改struts.xml中返回类型为json的处理类相关的配置。(如果你的工程原来采用的是其他的json类型处理插件的话)
将其中片段修改成如下状态:
- <result-types>
- <!-- 添加的自定义类型JSON对象 -->
- <!--
- <result-type name="json" class="com.googlecode.jsonplugin.JSONResult" />
- -->
- <result-typename="json"class="org.apache.struts2.json.JSONResult"/>
- </result-types>
<result-types>
<!-- 添加的自定义类型JSON对象 -->
<!--
<result-type name="json" class="com.googlecode.jsonplugin.JSONResult" />
-->
<result-type name="json" class="org.apache.struts2.json.JSONResult" />
</result-types>
7.所有涉及到jsonplugin-0.30.jar的类由struts2-json-plugin-2.3.15.1.jar中的对应类替换。(如果你的工程原来采用的是其他的json类型处理插件的话)
8.struts2标签库的升级
将原有的struts-tag.tld升级为最新。