緣起
Struts 是一個老牌的Java web framework。有多老,老到Struts1 已經停止維護了。 Struts2看似是Struts1的延伸,不過Struts2是不向下相容於Struts1。 所謂的不向下相容,並不是指Struts1與Struts2 framework不能同時存在於一個web application裡面,而是使用struts1寫的程式,沒有辦法僅僅拿掉struts1的jar檔、加上struts2的jar檔,web.xml
設一設就可以用了。 那些原本struts1寫的程式,還是需要進行相當程度的改寫。 除了將struts1的程式改為使用struts2的架構外,許許多多的連結也需要換掉。 因為struts1預設副檔名是使用.do
,struts2的副檔名是使用.action
,在昇級的時候,如果不是一次到位,就會導致系統裡面,Struts1的jar檔與Struts2的jar檔同時存在,.do
的連結指向struts1的功能,.action
的連結就會使用struts2的功能。 然而在一個已經上線的系統上,也似乎必需得這麼做,讓系統一支作業一支作業的昇級...
現在問題來了。 如果一支作業已經由struts1昇級到struts2,但是我們無法確認外部系統對內的所有的.do連結,是否已經全部換成.action。 一個折衷的辦法,就是讓.do的連結再forward到.action。 這就是我們今天要講的,如何讓指向struts1的.do連結導到struts2的.action。
請注意,以下方法適用於servlet 2.4以上 。
如何做?
Struts2 是使用filter的方式來install的,所以我們唯一要做的,只要在web.xml的地方增加forward dispatcher;struts1的action則直接使用config的方式forward到struts2的連結,就可以讓struts2在forward時觸發。
struts-config.xml.
<action path="/struts1moreaction" forward="/struts2action.action" />
strus.xml
<package name="taichitech" extends="struts-default" namespace="/" >
<action name="struts2action" class="taichitech.struts1to2.Struts2Action" method="execute">
<result name="success">/submitted2.jsp</result>
</action>
</package>
web.xml
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
我剛看了小小小?
如果看不懂到目前為止的程式碼,接下來我會有更詳細的描述。
基本上,一個系統的架設可以有很多種方法。我這裡demo的是使用Maven的方法建立的。 當然,你也可以自己直接手動將jar檔放入相關的位置。
Dependency
Struts1 與Struts2所使相關的lib檔,可以透過Maven直接設定取得。 Pom.xml的設定是這樣的:
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.16.3</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts-core</artifactId>
<version>1.3.10</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts-extras</artifactId>
<version>1.3.10</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts-taglib</artifactId>
<version>1.3.10</version>
</dependency>
Web.xml
Struts framework(不管是1或2)都有龐大的功能,與相對應的組態。這裡展示最基本的設定。這個web.xml
同時設定了 Struts1與Struts2。 其實Struts1與Struts2是可以同時放在相同一個app裡的。
web.xml
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>Servlet 2.5 Web Application</display-name>
<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>*.action</url-pattern>
<!-- Here is point -->
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet
</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/classes/struts-config.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
請注意struts2的那個filter-mapping
。在一般的教學中,struts2的設定檔都不會告訴你需要使用<dispatcher>
。這是servlet 2.4以後的規格。 預設是REQUEST
所以在一般的情況下,是不需要額外設定。 不過我們這裡的策略是讓struts1的url link(也就是*.do
) 經過struts1 framework後再forward到 struts2 framework,所以需要再額外指定<dispatcher>FORWARD</dispatcher>
讓struts2的filter可以在forward的時候被觸發。
struts-config.xml
這是struts1的預設設定檔。 它長的像是這個樣子。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd">
<struts-config>
<action-mappings>
<action path="/struts1action" type="taichitech.struts1to2.Struts1Action"
parameter="method" scope="request">
<forward name="success" path="/struts2action.action" />
</action>
<action path="/struts1moreaction" forward="/struts2action.action" />
</action-mappings>
</struts-config>
我示範了2種手法。 第一種,仍然經過struts1 action。 不過success
這個ActionForward
的path
是指向struts2的url。看,url的後綴是.action。
第2個更省事,連struts1的class也不用,直接forward到struts2。 Action
這個tag,什麼也沒做,甚至連class也不指定了,直接forward 到struts2的url。
struts.xml
Struts2的設定檔,預設檔名是struts.xml。這與一般教學是一樣的,沒什麼特別的差異。 最後會導到/submitted2.jsp
。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.devMode" value="false" />
<constant name="struts.ui.theme" value="simple" />
<package name="taichitech" extends="struts-default" namespace="/" >
<action name="struts2action" class="taichitech.struts1to2.Struts2Action" method="execute">
<result name="success">/submitted2.jsp</result>
</action>
</package>
</struts>
Action
- Struts1
Struts1 的action 範例:
public class Struts1Action extends DispatchAction {
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,
HttpServletResponse response) throws Exception {
Logger logger = LoggerFactory.getLogger(getClass());
logger.debug("Execute Struts1Action.execute");
return mapping.findForward("success");
}
}
- Struts2
Struts2 action的範例:
public class Struts2Action extends BaseAction {
public String execute() {
Logger logger = LoggerFactory.getLogger(getClass());
logger.debug("Execute Struts2Action.execute");
return Action.SUCCESS;
}
}
- index.jsp
<body>
<a href="${pageContext.request.contextPath}/struts1action.do">Here
is an .do link-</a> <br/>
<a href="${pageContext.request.contextPath}/struts1moreaction.do">Here
is an more .do link-</a>
</body>
- submitted2.jsp
<body>A page that submitted!!
</body>
由於是採用forward的方式,url還是.do
。
結論
在系統改版時,可以一次到位,將所有的struts1的action重新改成struts2、struts1的jar檔可以一次被抽換掉,當然是最好。 如果不行的話,這樣的一個折衷的保險措施是必需要的。 當然一個系統的昇版並不是那麼簡單,還有許多的的部份,例如action form
如何轉換、validation
、action error
、action message
如何修改,這些都是考驗著我們的智慧。
沒有留言 :
張貼留言