我见q许多项目开发者实现自׃有的MVC框架。这些开发者ƈ不是因ؓ(f)惛_C同于Struts的某些功能,而是q没有意识到怎么L展Struts。通过开发自qMVC框架Q你可以掌控全局Q但同时q也意味着你必M出很大的代h(hun)Q在目计划很紧的情况下也许Ҏ(gu)׃可能实现?BR>
Struts不但功能强大也易于扩展。你可以通过三种方式来扩展Struts:
1.PlugInQ在应用启动或关闭时L行某业务逻辑Q创Z自己的PlugInc?BR>
2.RequestProcessorQ在h处理阶段一个特定点Ʋ执行某业务逻辑Q创Z自己的RequestProcessor。例如:(x)你想l承RequestProcessor来检查用L(fng)录及(qing)在执行每个请求时他是否有权限执行某个动作?BR>
3.ActionServletQ在应用启动或关闭或在请求处理阶D|执行某业务逻辑Q(h)承ActionServletcR但是必M只能在PligIn和RequestProcessor都不能满你的需求时候用?BR>
本文?x)列举一个简单的Struts应用来示范如何用以上三U方式扩展Struts。在本文末尾资源区有每种方式的可下蝲样例源代码。Struts Validation 框架?Tiles 框架是最成功两个的Struts扩展例子?BR>
我是假设读者已l熟(zhn)Struts框架q知道怎样使用它创建简单的应用。如想了(jin)解更多有关Struts的资料请参见资源区?BR>
PlugIn
Ҏ(gu)Struts文Q“PlugIn是一个须在应用启动和关闭旉被通知的模块定制资源或服务配置包”。这是_(d)你可以创Z个类Q它实现PlugIn的接口以便在应用启动和关闭时做你惌的事?BR>
假如创徏?jin)一个web应用Q其中用Hibernate做ؓ(f)持久化机Ӟ当应用一启动Q就需初始化HinernateQ这样在web应用接收到第一个请求时QHibernate已被配置完毕q待命。同时在应用关闭时要关闭Hibernate。跟着以下两步可以实现Hibernate PlugIn的需求?BR>
1.创徏一个实现PlugIn接口的类Q如下:(x)
public class HibernatePlugIn implements PlugIn{
private String configFile;
// This method will be called at application shutdown time
public void destroy() {
System.out.println("Entering HibernatePlugIn.destroy()");
//Put hibernate cleanup code here
System.out.println("Exiting HibernatePlugIn.destroy()");
}
//This method will be called at application startup time
public void init(ActionServlet actionServlet, ModuleConfig config)
throws ServletException {
System.out.println("Entering HibernatePlugIn.init()");
System.out.println("Value of init parameter " +
getConfigFile());
System.out.println("Exiting HibernatePlugIn.init()");
}
public String getConfigFile() {
return name;
}
public void setConfigFile(String string) {
configFile = string;
}
}
<struts-config>
...
<!-- Message Resources -->
<message-resources parameter=
"sample1.resources.ApplicationResources"/>
<!-- Declare your plugins -->
<plug-in className="com.sample.util.HibernatePlugIn">
<set-property property="configFile"
value="/hibernate.cfg.xml"/>
</plug-in>
</struts-config>
public void process(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
// Wrap multipart requests with a special wrapper
request = processMultipart(request);
// Identify the path component we will
// use to select a mapping
String path = processPath(request, response);
if (path == null) {
return;
}
if (log.isDebugEnabled()) {
log.debug("Processing a '" + request.getMethod() +
"' for path '" + path + "'");
}
// Select a Locale for the current user if requested
processLocale(request, response);
// Set the content type and no-caching headers
// if requested
processContent(request, response);
processNoCache(request, response);
// General purpose preprocessing hook
if (!processPreprocess(request, response)) {
return;
}
// Identify the mapping for this request
ActionMapping mapping =
processMapping(request, response, path);
if (mapping == null) {
return;
}
// Check for any role required to perform this action
if (!processRoles(request, response, mapping)) {
return;
}
// Process any ActionForm bean related to this request
ActionForm form =
processActionForm(request, response, mapping);
processPopulate(request, response, form, mapping);
if (!processValidate(request, response, form, mapping)) {
return;
}
// Process a forward or include specified by this mapping
if (!processForward(request, response, mapping)) {
return;
}
if (!processInclude(request, response, mapping)) {
return;
}
// Create or acquire the Action instance to
// process this request
Action action =
processActionCreate(request, response, mapping);
if (action == null) {
return;
}
// Call the Action instance itself
ActionForward forward =
processActionPerform(request, response,
action, form, mapping);
// Process the returned ActionForward instance
processForwardConfig(request, response, forward);
}
<controller>
<set-property property="locale" value="false"/>
</controller>
<controller>
<set-property property="contentType" value="text/plain"/>
</controller>
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 1);
<controller>
<set-property property="noCache" value="true"/>
</controller>
<action path="/newcontact" type="com.sample.NewContactAction"
name="newContactForm" scope="request">
<forward name="sucess" path="/sucessPage.do"/>
<forward name="failure" path="/failurePage.do"/>
</action>
<form-bean name="newContactForm"
type="org.apache.struts.action.DynaActionForm">
<form-property name="firstName"
type="java.lang.String"/>
<form-property name="lastName"
type="java.lang.String"/>
</form-bean>
<action forward="/Login.jsp" path="/loginInput"/>
<action include="/Login.jsp" path="/loginInput"/>
public class CustomRequestProcessor
extends RequestProcessor {
protected boolean processPreprocess (
HttpServletRequest request,
HttpServletResponse response) {
HttpSession session = request.getSession(false);
//If user is trying to access login page
// then don't check
if( request.getServletPath().equals("/loginInput.do")
|| request.getServletPath().equals("/login.do") )
return true;
//Check if userName attribute is there is session.
//If so, it means user has allready logged in
if( session != null &&
session.getAttribute("userName") != null)
return true;
else{
try{
//If no redirect user to login Page
request.getRequestDispatcher
("/Login.jsp").forward(request,response);
}catch(Exception ex){
}
}
return false;
}
protected void processContent(HttpServletRequest request,
HttpServletResponse response) {
//Check if user is requesting ContactImageAction
// if yes then set image/gif as content type
if( request.getServletPath().equals("/contactimage.do")){
response.setContentType("image/gif");
return;
}
super.processContent(request, response);
}
}
<controller>
<set-property property="processorClass"
value="com.sample.util.CustomRequestProcessor"/>
</controller>
<web-app >
<servlet>
<servlet-name>action=</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<!-- All your init-params go here-->
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app >