关于经典开源框架STRUTS2的使用

Posted on 2011-12-21 10:23  无忧consume  阅读(261)  评论(0编辑  收藏  举报

关于STRUTS的技术文章我很早就想写一篇了,只是不知道要写些什么东西,主要是以前没怎么接触过这个框架,因此打算用熟了之后再来写,可能感受会更深一些;其实等我会了之后,依然不知道要写些什么东西,因为总感觉都很简单的样子,没什么重点可述;但基于之前在《Jsp学习——filter的使用》一文中谈到了STRUTS2的原理,在最后也说道:”struts2的配置文件中没有servlet类的配置,只有一个filter的配置,由此可以看出其用filter处理所有的消息,至于如何处理前台传来的各种消息,我会在下一篇文章中详细阐述“ 。所以打算不管如何,这篇文章还是要写的,曾经不知在哪看到过这样一句话:”Writing was invented by someone who was too lazy to memorize“,用这句话来阐释我写技术博客的原因再好不过了。废话不多说了,开始进入主题了。

我在写《Jsp学习——servlet详解》这篇文章时候,使用了MVC架构模式来阐述那个DEMO,而STRUTS2也是公认的经典MVC框架,其使用一个filter和action类来充当控制层(control),使用JSP来充当视图层(view),使用DAO+SERVICE来充当模型层(model),整个执行流程大概是:浏览器收到用户的请求ACTION,发送到服务器端,FILTER将接收到的ACTION与特定视图关联(关联的物理视图和逻辑视图的关系全在配置文件中设置),之后继续将ACTION转发到指定的ACTION-CLASS中去处理,ACTION-CLASS调用MODEL层来完成所有的业务逻辑处理,之后再根据FILTER指定的视图资源跳转到对应的物理视图。

对于STURTS2的配置,由于其整个框架只使用了一个FILTER来充当核心控制器,而没有使用任何SERVLET,所以只需配置一下FILTER就行了,其配置方法与配置FILTER没太大差别,只是FILTER类是STRUTS2指定的框架中实现了的类(org.apache.struts2.dispatcher.FilterDispatcher),而不能由我们自己乱定。如下所示,在web.xml文件中的关键代码:

 

  1. <filter>  
  2.     <filter-name>struts2</filter-name>  
  3.     <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>  
  4. </filter>  
  5. <filter-mapping>  
  6.     <filter-name>struts2</filter-name>  
  7.     <url-pattern>/*</url-pattern>  
  8. </filter-mapping>  

对于逻辑视图与物理视图对应关系的配置文件,其文件名默认为struts.xml,当放在src目录下,如果放在同web.xml的同目录下是不会起作用的,运行时期会出很多难以预料的错误。关于其配置方式,有很多种,可以专门写一篇博文来讨论了,在这里,我暂且用我认为较简单而且易用的方式,其内容如下:

 

 

  1. <struts>  
  2.     <package name="com.struts2.projection.action" extends="struts-default">  
  3.         <action name="*" class="com.struts2.projection.action.Action" method="{1} ">  
  4.             <result name="success">success.jsp</result>  
  5.             <result name="error">error.jsp</result>  
  6.         </action>  
  7.     </package>   
  8. </struts>  

这种方式是通过指定通配符的方式,”*“意思是对于前台传来的所有.action消息,都将分配给com.struts2.projection.action.Action类来处理,这是个自定义类,至于具体再分配给哪个方法,由method = "{1}"来指示,其意思是指定前面action的name属性中第一个*号所代表的单词为该action对应的方法名,如:前台传来login.action,则对应的处理方法为login(),传来regist.action,则对应的处理方法为regist();

 

另外还有一种常用的方式,同样很受欢迎,即将action名改为以 类名+!+动作名  的方式来动态调用aciton类中的方法,其动作名就是指定的方法名。在这种方式下,struts.xml的配置为一般型的配置:

 

  1. <struts>  
  2.     <package name="com.struts2.projection.action" extends = "struts-default">  
  3.         <action name="login" class="com.struts2.projection.action.Action">  
  4.             <result name="error">/error.jsp</result>  
  5.             <result name="success">/success.jsp</result>   
  6.         </action>  
  7.     </package>  
  8. </struts>  

如此依然可以实现动态调用,但对ACTION类的要求是,其必须有一个默认的excute()方法。这种方法在前台为ajax框架或类似的框架如extjs中经常被很多人青睐。还有很多其它不常用的方式在此就不详细阐述。

 

以下是一个登陆框的完整示例:

view:index.jsp

 

  1. <%@ page language="java" import="java.util.*" pageEncoding="gb2312"%>  
  2. <%@ taglib prefix="s" uri="/struts-tags" %>  
  3. <%  
  4. String path = request.getContextPath();  
  5. String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  
  6. %>  
  7.   
  8. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  9. <html>  
  10.   <head>  
  11.     <base href="<%=basePath%>">  
  12.     <title>My JSP 'index.jsp' starting page</title>  
  13.     <meta http-equiv="pragma" content="no-cache">  
  14.     <meta http-equiv="cache-control" content="no-cache">  
  15.     <meta http-equiv="expires" content="0">      
  16.     <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
  17.     <meta http-equiv="description" content="This is my page">  
  18.     <!-- 
  19.     <link rel="stylesheet" type="text/css" href="styles.css"> 
  20.     -->  
  21.   </head>  
  22.   <body>  
  23.     <s:form action = "login" method="login">  
  24.         <s:textfield name="username" label="user name"></s:textfield>  
  25.         <s:textfield name="userpassword" label="user password"></s:textfield>  
  26.         <s:submit value="login"></s:submit>  
  27.         <s:submit value="regist" onclick="regist()"></s:submit>  
  28.     </s:form>   
  29.     <script type="text/javascript">  
  30.     function regist()  
  31.     {  
  32.         targetForm = document.forms[0];  
  33.         targetForm.action = "regist.action";      
  34.     }  
  35.     </script>     
  36.   </body>  
  37. </html>  


web.xml

 

 

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app version="2.5"   
  3.     xmlns="http://java.sun.com/xml/ns/javaee"   
  4.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
  5.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   
  6.     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
  7.   <welcome-file-list>  
  8.     <welcome-file>index.jsp</welcome-file>  
  9.   </welcome-file-list>  
  10.   <filter>  
  11.     <filter-name>struts2</filter-name>  
  12.     <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>  
  13.   </filter>  
  14.   <filter-mapping>  
  15.     <filter-name>struts2</filter-name>  
  16.     <url-pattern>/*</url-pattern>  
  17.   </filter-mapping>  
  18. </web-app>  

struts.xml

 

 

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE struts PUBLIC  
  3.     "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"  
  4.     "http://struts.apache.org/dtds/struts-2.0 dtd"  
  5. >  
  6. <struts>  
  7.      <package name="com.struts2.projection.action" extends="struts-default">  
  8.         <action name="*" class="com.struts2.projection.action.Action" method="{1} ">  
  9.             <result name="success">success.jsp</result>  
  10.             <result name="error">error.jsp</result>  
  11.         </action>  
  12.     </package>    
  13. </struts>  

control:Action.java

 

  1. package com.struts2.projection.action;  
  2.   
  3. import java.sql.*;  
  4.   
  5. import com.opensymphony.xwork2.ActionContext;  
  6. import com.struts2.projection.dao.DbDao;  
  7.   
  8. public class Action {  
  9.     private String userpassword;  
  10.     private String username;  
  11.       
  12.     public String getUserpassword() {  
  13.         return userpassword;  
  14.     }  
  15.     public void setUserpassword(String userpassword) {  
  16.         this.userpassword = userpassword;  
  17.     }  
  18.     public String getUsername() {  
  19.         return username;  
  20.     }  
  21.     public void setUsername(String username) {  
  22.         this.username = username;  
  23.     }  
  24.     public String regist() throws ClassNotFoundException, SQLException  
  25.     {  
  26.         String driver = "com.mysql.jdbc.Driver";  
  27.         String url = "jdbc:mysql://localhost:3306/test_db";   
  28.         String user = "root";  
  29.         String pass = "900622";  
  30.         DbDao dao = DbDao.instance(driver,url,user,pass);    
  31.         ActionContext actionContext = ActionContext.getContext();   
  32.         if(username.replace(" ", "").equals("") || userpassword.replace(" ", "").equals(""))  
  33.         {  
  34.             actionContext.put("tip", "客户端提示:user name or user password can not be blank!");  
  35.             return "error";  
  36.         }  
  37.         String insertSql = "insert into user_information(username,userpassword) values('"+ username +"','"+ userpassword +"')";  
  38.         System.out.println(username+";"+userpassword);  
  39.         dao.insert(insertSql);  
  40.         actionContext.put("tip", "服务器提示: regist success!");  
  41.         return "error";  
  42.     }  
  43.     public String login() throws ClassNotFoundException, SQLException  
  44.     {  
  45.         String driver = "com.mysql.jdbc.Driver";  
  46.         String url = "jdbc:mysql://localhost:3306/test_db";   
  47.         String user = "root";  
  48.         String pass = "900622";  
  49.         DbDao dao = DbDao.instance(driver,url,user,pass);    
  50.         ActionContext actionContext = ActionContext.getContext();   
  51.         String sql = "select userpassword from user_information where username = '" + username + "'";    
  52.         ResultSet resultSet = dao.query(sql);    
  53.             
  54.         if(resultSet.next())    
  55.         {    
  56.             if(resultSet.getString("userpassword").equals(userpassword))    
  57.             {    
  58.                 Integer counter=(Integer)actionContext.getApplication().get("counter");  
  59.                 if(counter == null)  
  60.                 {  
  61.                     counter=1;  
  62.                 }  
  63.                 else  
  64.                 {  
  65.                     counter++;  
  66.                 }  
  67.                 actionContext.getApplication().put("counter", counter);  
  68.                 actionContext.getSession().put("user", this.getUsername());  
  69.                 return "success";  
  70.             }    
  71.             else    
  72.             {    
  73.                 actionContext.put("tip", "服务器提示:password error!so login failed!");  
  74.                 return "error";  
  75.             }    
  76.         }    
  77.         else    
  78.         {    
  79.             actionContext.put("tip", "服务器提示:user name not exist!");    
  80.             return "error";  
  81.         }    
  82.     }  
  83. }  

Model:DbDao.java

  1. package com.struts2.projection.dao;  
  2. import java.sql.*;    
  3. public class DbDao {    
  4.     private static DbDao dao;    
  5.     private Connection conn;    
  6.     private String driver;    
  7.     private String url;    
  8.     private String username;    
  9.     private String pass;    
  10.         
  11.     private DbDao()    
  12.     {}    
  13.         
  14.     private DbDao(String driver,String url,    
  15.             String username,String pass)    
  16.     {    
  17.         this.driver = driver;    
  18.         this.url = url;    
  19.         this.username = username;    
  20.         this.pass = pass;    
  21.     }    
  22.     
  23.     public static DbDao getDao() {    
  24.         return dao;    
  25.     }    
  26.     
  27.     public static void setDao(DbDao dao) {    
  28.         DbDao.dao = dao;    
  29.     }    
  30.     
  31.     public String getDriver() {    
  32.         return driver;    
  33.     }    
  34.     
  35.     public void setDriver(String driver) {    
  36.         this.driver = driver;    
  37.     }    
  38.     
  39.     public String getUrl() {    
  40.         return url;    
  41.     }    
  42.     
  43.     public void setUrl(String url) {    
  44.         this.url = url;    
  45.     }    
  46.     
  47.     public String getUsername() {    
  48.         return username;    
  49.     }    
  50.     
  51.     public void setUsername(String username) {    
  52.         this.username = username;    
  53.     }    
  54.     
  55.     public String getPass() {    
  56.         return pass;    
  57.     }    
  58.     
  59.     public void setPass(String pass) {    
  60.         this.pass = pass;    
  61.     }    
  62.         
  63.     public void getConnection() throws ClassNotFoundException, SQLException    
  64.     {    
  65.         if(conn == null)    
  66.         {    
  67.             Class.forName(this.driver);    
  68.             conn = DriverManager.getConnection(url, username, pass);    
  69.         }    
  70.     }    
  71.         
  72.     public static DbDao instance(String driver,String url,    
  73.             String username,String pass)    
  74.     {    
  75.         if(dao == null)    
  76.         {    
  77.             dao = new DbDao(driver,url,username,pass);    
  78.         }    
  79.         return dao;    
  80.     }    
  81.         
  82.     public boolean insert(String sql) throws ClassNotFoundException, SQLException    
  83.     {    
  84.         getConnection();    
  85.         Statement statement = conn.createStatement();    
  86.         if(statement.executeUpdate(sql) != -1)    
  87.         {    
  88.             return false;    
  89.         }    
  90.         return true;    
  91.     }    
  92.         
  93.     public ResultSet query(String sql) throws ClassNotFoundException, SQLException    
  94.     {    
  95.         getConnection();    
  96.         Statement statement = conn.createStatement();    
  97.         return statement.executeQuery(sql);    
  98.     }    
  99.         
  100.     public void delete(String sql) throws ClassNotFoundException, SQLException    
  101.     {    
  102.         getConnection();    
  103.         Statement statement = conn.createStatement();    
  104.         statement.executeUpdate(sql);    
  105.     }    
  106.         
  107.     public void update(String sql) throws ClassNotFoundException, SQLException    
  108.     {    
  109.         getConnection();    
  110.         Statement statement = conn.createStatement();    
  111.         statement.executeUpdate(sql);    
  112.     }    
  113. }    

 

最后,说一下Action.java类,对于Action.java的成员变量,我需要特意说明一下:Action类中必须要声明与前台交互的数据,并且数据的标示符与前台定义的要相同,另外要定义setter和getter函数,因为Action与前台打交道就是通过filter和拦截器来控制这几个值,当前台传来值时,拦截器就调用setter方法来设置对应的成员值。

Action.java可以继承默认的SupportAction类作为其父类,SupportAction中实现了一些一般情形的响应,继承之后,就可以使用其中方法或者重写其中方法来达到自己的需求。(在这里,我没有继承SupportActoin类)。

当然的,代码的分层结构还不够好,因为Action中依然有许多的逻辑处理,在标准的SSH框架中,DbDao上面还有一层Service类,来处理脱离数据库之外的逻辑,因为这里暂且只介绍了Struts2,所以分层并不是很标准。

Copyright © 2024 无忧consume
Powered by .NET 8.0 on Kubernetes