关于经典开源框架STRUTS2的使用
2011-08-22 12:42
344 查看
关于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文件中的关键代码:
另外还有一种常用的方式,同样很受欢迎,即将action名改为以 类名+!+动作名 的方式来动态调用aciton类中的方法,其动作名就是指定的方法名。在这种方式下,struts.xml的配置为一般型的配置:
以下是一个登陆框的完整示例:
view:index.jsp
web.xml
最后,说一下Action.java类,对于Action.java的成员变量,我需要特意说明一下:Action类中必须要声明与前台交互的数据,并且数据的标示符与前台定义的要相同,另外要定义setter和getter函数,因为Action与前台打交道就是通过filter和拦截器来控制这几个值,当前台传来值时,拦截器就调用setter方法来设置对应的成员值。
Action.java可以继承默认的SupportAction类作为其父类,SupportAction中实现了一些一般情形的响应,继承之后,就可以使用其中方法或者重写其中方法来达到自己的需求。(在这里,我没有继承SupportActoin类)。
当然的,代码的分层结构还不够好,因为Action中依然有许多的逻辑处理,在标准的SSH框架中,DbDao上面还有一层Service类,来处理脱离数据库之外的逻辑,因为这里暂且只介绍了Struts2,所以分层并不是很标准。
。所以打算不管如何,这篇文章还是要写的,曾经不知在哪看到过这样一句话:”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文件中的关键代码:
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>对于逻辑视图与物理视图对应关系的配置文件,其文件名默认为struts.xml,当放在src目录下,如果放在同web.xml的同目录下是不会起作用的,运行时期会出很多难以预料的错误。关于其配置方式,有很多种,可以专门写一篇博文来讨论了,在这里,我暂且用我认为较简单而且易用的方式,其内容如下:
<struts> <package name="com.struts2.projection.action" extends="struts-default"> <action name="*" class="com.struts2.projection.action.Action" method="{1} "> <result name="success">success.jsp</result> <result name="error">error.jsp</result> </action> </package> </struts>这种方式是通过指定通配符的方式,”*“意思是对于前台传来的所有.action消息,都将分配给com.struts2.projection.action.Action类来处理,这是个自定义类,至于具体再分配给哪个方法,由method = "{1}"来指示,其意思是指定前面action的name属性中第一个*号所代表的单词为该action对应的方法名,如:前台传来login.action,则对应的处理方法为login(),传来regist.action,则对应的处理方法为regist();
另外还有一种常用的方式,同样很受欢迎,即将action名改为以 类名+!+动作名 的方式来动态调用aciton类中的方法,其动作名就是指定的方法名。在这种方式下,struts.xml的配置为一般型的配置:
<struts> <package name="com.struts2.projection.action" extends = "struts-default"> <action name="login" class="com.struts2.projection.action.Action"> <result name="error">/error.jsp</result> <result name="success">/success.jsp</result> </action> </package> </struts>如此依然可以实现动态调用,但对ACTION类的要求是,其必须有一个默认的excute()方法。这种方法在前台为ajax框架或类似的框架如extjs中经常被很多人青睐。还有很多其它不常用的方式在此就不详细阐述。
以下是一个登陆框的完整示例:
view:index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%> <%@ taglib prefix="s" uri="/struts-tags" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <s:form action = "login" method="login"> <s:textfield name="username" label="user name"></s:textfield> <s:textfield name="userpassword" label="user password"></s:textfield> <s:submit value="login"></s:submit> <s:submit value="regist" onclick="regist()"></s:submit> </s:form> <script type="text/javascript"> function regist() { targetForm = document.forms[0]; targetForm.action = "regist.action"; } </script> </body> </html>
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" 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"> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>struts.xml
<?xml version="1.0" encoding="UTF-8"?>control:Action.java
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0 dtd"
>
<struts> <package name="com.struts2.projection.action" extends="struts-default"> <action name="*" class="com.struts2.projection.action.Action" method="{1} "> <result name="success">success.jsp</result> <result name="error">error.jsp</result> </action> </package> </struts>
package com.struts2.projection.action; import java.sql.*; import com.opensymphony.xwork2.ActionContext; import com.struts2.projection.dao.DbDao; public class Action { private String userpassword; private String username; public String getUserpassword() { return userpassword; } public void setUserpassword(String userpassword) { this.userpassword = userpassword; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String regist() throws ClassNotFoundException, SQLException { String driver = "com.mysql.jdbc.Driver"; String url = "jdbc:mysql://localhost:3306/test_db"; String user = "root"; String pass = "900622"; DbDao dao = DbDao.instance(driver,url,user,pass); ActionContext actionContext = ActionContext.getContext(); if(username.replace(" ", "").equals("") || userpassword.replace(" ", "").equals("")) { actionContext.put("tip", "客户端提示:user name or user password can not be blank!"); return "error"; } String insertSql = "insert into user_information(username,userpassword) values('"+ username +"','"+ userpassword +"')"; System.out.println(username+";"+userpassword); dao.insert(insertSql); actionContext.put("tip", "服务器提示: regist success!"); return "error"; } public String login() throws ClassNotFoundException, SQLException { String driver = "com.mysql.jdbc.Driver"; String url = "jdbc:mysql://localhost:3306/test_db"; String user = "root"; String pass = "900622"; DbDao dao = DbDao.instance(driver,url,user,pass); ActionContext actionContext = ActionContext.getContext(); String sql = "select userpassword from user_information where username = '" + username + "'"; ResultSet resultSet = dao.query(sql); if(resultSet.next()) { if(resultSet.getString("userpassword").equals(userpassword)) { Integer counter=(Integer)actionContext.getApplication().get("counter"); if(counter == null) { counter=1; } else { counter++; } actionContext.getApplication().put("counter", counter); actionContext.getSession().put("user", this.getUsername()); return "success"; } else { actionContext.put("tip", "服务器提示:password error!so login failed!"); return "error"; } } else { actionContext.put("tip", "服务器提示:user name not exist!"); return "error"; } } }Model:DbDao.java
package com.struts2.projection.dao; import java.sql.*; public class DbDao { private static DbDao dao; private Connection conn; private String driver; private String url; private String username; private String pass; private DbDao() {} private DbDao(String driver,String url, String username,String pass) { this.driver = driver; this.url = url; this.username = username; this.pass = pass; } public static DbDao getDao() { return dao; } public static void setDao(DbDao dao) { DbDao.dao = dao; } public String getDriver() { return driver; } public void setDriver(String driver) { this.driver = driver; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPass() { return pass; } public void setPass(String pass) { this.pass = pass; } public void getConnection() throws ClassNotFoundException, SQLException { if(conn == null) { Class.forName(this.driver); conn = DriverManager.getConnection(url, username, pass); } } public static DbDao instance(String driver,String url, String username,String pass) { if(dao == null) { dao = new DbDao(driver,url,username,pass); } return dao; } public boolean insert(String sql) throws ClassNotFoundException, SQLException { getConnection(); Statement statement = conn.createStatement(); if(statement.executeUpdate(sql) != -1) { return false; } return true; } public ResultSet query(String sql) throws ClassNotFoundException, SQLException { getConnection(); Statement statement = conn.createStatement(); return statement.executeQuery(sql); } public void delete(String sql) throws ClassNotFoundException, SQLException { getConnection(); Statement statement = conn.createStatement(); statement.executeUpdate(sql); } public void update(String sql) throws ClassNotFoundException, SQLException { getConnection(); Statement statement = conn.createStatement(); statement.executeUpdate(sql); } }
最后,说一下Action.java类,对于Action.java的成员变量,我需要特意说明一下:Action类中必须要声明与前台交互的数据,并且数据的标示符与前台定义的要相同,另外要定义setter和getter函数,因为Action与前台打交道就是通过filter和拦截器来控制这几个值,当前台传来值时,拦截器就调用setter方法来设置对应的成员值。
Action.java可以继承默认的SupportAction类作为其父类,SupportAction中实现了一些一般情形的响应,继承之后,就可以使用其中方法或者重写其中方法来达到自己的需求。(在这里,我没有继承SupportActoin类)。
当然的,代码的分层结构还不够好,因为Action中依然有许多的逻辑处理,在标准的SSH框架中,DbDao上面还有一层Service类,来处理脱离数据库之外的逻辑,因为这里暂且只介绍了Struts2,所以分层并不是很标准。
相关文章推荐
- 关于经典开源框架STRUTS2的使用
- 关于经典开源框架STRUTS2的使用
- 关于经典开源框架STRUTS2的使用
- 关于xUtils开源框架的具体使用详情
- 关于使用腾讯 Bugly 平台 Tinker开源热修复框架的 项目集成
- 为何不使用spring、struts2、easyjweb等开源框架
- 关于android-common开源框架的使用
- 为何不使用spring、struts2、easyjweb等开源框架
- 为何不使用spring、struts2、easyjweb等开源框架
- 关于ShineButton的开源框架的使用
- 为何不使用spring、struts2、easyjweb等开源框架
- 【特别报道:关于国津软件的某对手ITSM产品使用的“开源框架+剽窃国津代码”之开发模式】 (注:“国聿软件公司”名称变更为“国津软件公司”之后,“国聿”成为国津软件公司的一个注册商标品牌.) 我们
- 为何不使用spring、struts2、easyjweb等开源框架
- 为何不使用spring、struts2、easyjweb等开源框架
- 【经典必学】常用开源框架中设计模式使用分析
- 为何不使用spring、struts2、easyjweb等开源框架
- 为何不使用spring、struts2、easyjweb等开源框架
- 为何不使用spring、struts2、easyjweb等开源框架
- 为何不使用spring、struts2、easyjweb等开源框架
- 为何不使用spring、struts2、easyjweb等开源框架