上一篇提出了問題,使用Struts框架比不使用struts框架的好處在哪里的問題。以及由此講述了[靜態](http://blog.csdn.net/lovesummerforever/article/details/18951649)[ActionForm和動態ActionForm](http://blog.csdn.net/lovesummerforever/article/details/18951649)。本篇就第一個問題,以一個示例對用戶信息的增刪改查來展示基本的MVC框架到strutsMVC的過程。
### 版本一 基本的MVC
首先是創建一個jsp索引頁面index.jsp,index.jsp創建一個表單。
如果我們完成添加用戶的模塊,我們提交表單的時候要把這個表單提交給一個servlet,于是我們在src自己的包中建立自己的servlet繼承HttpServlet,TestServlet同時覆蓋父類的doGet和doPost方法。
提交的的表單信息,我們可以在TestServlet中通過request.getParameter(“username”);取出來。之后把從表單中的數據提交到數據庫,我們的servlet作為控制器沒有添加到數據庫的職責,于是我們把訪問數據庫的業務邏輯放到UserManager.java類中。在這個類中實現添加用戶的任務。
~~~
package com.bjpowernode.servlet;
public class UserManager {
public void add(String username)
{
System.out.println("UserManager.add()-->>"+ username);
}
}
~~~
在TestServlet中調用UserManager中的方法。同時讓頁面轉向到添加成功的頁面add_success.jsp。
TestServlet代碼以及在web.xml中配置TestServlet.
?
~~~
<servlet>
<servlet-name>TestServlet</servlet-name>
<servlet-class>com.bjpowernode.servlet.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet</servlet-name>
<url-pattern>/servlet/TestServlet</url-pattern>
</servlet-mapping>
~~~
Testservlet代碼如下所示:
~~~
package com.bjpowernode.servlet;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
public class TestServlet extendsHttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter(“username”);
UserManager userManager = new UserManager();
userManager.add(username);
request.getRequestDispatcher(“/add_success.jsp”).forward(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
~~~
索引頁面index.jsp代碼,通過servlet/TestServlet來轉到TestServlet。
????
~~~
<form action="servlet/queryUser.action" method="post">
姓名:<input type="text" name="username"><br>
<input type="submit" value="提交"><br>
</form>
~~~
這樣采用MVC完成了用戶的添加任務。
### 版本二 通過判斷標識變量
當我們不僅要完成用戶的添加而是要完成用戶的增刪改查的時候我們可以在servlet中進行判斷,是添加還是刪除等。并且在傳遞字符串的時候要加上一個標識表示相應的操作。這樣在servlet中會有很多的if和else語句。
### 版本三 servlet模式匹配 截取字符串判斷
我們可以在配置servlet的時候配置成為匹配模式<url-pattern>*.action</url-pattern>任何的*.action的都會轉到到TestServlet,這樣我們可以截取URL來判斷轉到哪個頁面。但在TestServlet中仍然有很多的ifelse語句進行判斷。這樣我們的TestServlet代碼如下所示。
~~~
import java.io.IOException;
import java.util.List;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
public class TestServlet extendsHttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//截取url.
String requestURI = request.getRequestURI();
//System.out.println("requestURI="+ requestURI);
//截取http://localhost:8080/test_servlet/servlet/addUser.action test_servlet后面的東西。
String path = requestURI.substring(requestURI.indexOf("/", 1),requestURI.indexOf("."));
//截取得到虛目錄。/servlet/addUser
System.out.println("path="+ path);
String username = request.getParameter("username");
UserManager userManager = new UserManager();
String forward = "";
//判斷截取的path和哪個要加載的頁面相等.
if("/servlet/delUser".equals(path))
{
userManager.del(username);
forward = "del_success.jsp";
//request.getRequestDispatcher("/del_success.jsp").forward(request,response);
}else if("/servlet/addUser".equals(path))
{
userManager.add(username);
forward= "add_success.jsp";
//request.getRequestDispatcher("/add_success.jsp").forward(request,response);
}else if("/servlet/modifyUser".equals(path))
{
userManager.modify(username);
forward= "modify_success.jsp";
//request.getRequestDispatcher("/modify_success.jsp").forward(request,response);
}else if("/servlet/queryUser".equals(path))
{
List userList = userManager.query(username);
request.setAttribute("userList",userList);
forward= "query_success.jsp";
//request.getRequestDispatcher("/query_success.jsp").forward(request,response);
}else
{
throw new RuntimeException("請求失敗!");
}
request.getRequestDispatcher(forward).forward(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throwsServletException, IOException {
doGet(request,response);
}
}
~~~
UserManager代碼如下所示:
~~~
package com.bjpowernode.servlet;
import java.util.ArrayList;
import java.util.List;
public class UserManager {
public void add(String username)
{
System.out.println("UserManager.add()-->>"+ username);
}
public void del(String username)
{
System.out.println("UserManager.del()-->>"+ username);
}
public void modify(String username)
{
System.out.println("UserManager.modify()-->>"+ username);
}
public List query(String username)
{
System.out.println("UserManager.query()-->>"+ username);
List userList = new ArrayList();
userList.add("a");
userList.add("b");
userList.add("c");
return userList;
}
}
~~~
同時建立查詢成功,刪除成功,修改成功jsp頁面。
這樣在index.jsp頁面中通過表單的action屬性來轉到相應的頁面。
~~~
<body>
<form action="servlet/queryUser.action" method="post">
姓名:<input type="text" name="username"><br>
<input type="submit" value="提交"><br>
</form>
</body>
~~~
版本三的缺點是if太多,不穩定,當我們添加或者刪除一個if的時候還需要重新編譯源程序。這樣無法適應變化的需求。所以我們在此基礎上進行改進就需要去掉if語句,可以把改變的部分分離出來,變成可配置的,這樣就變得靈活的,需要改動jsp的文件名,在配置文件中配置一下就可以了。
### 版本四 if else抽象出接口和類+配置文件
首先我們把轉到的地址字符串放到一個字符串變量中,這樣TestServlet中的doGet方法,代碼如下。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
~~~
String username = request.getParameter("username");
UserManager userManager = new UserManager();
String forward = "";
//判斷截取的path和哪個要加載的頁面相等.
if("/servlet/delUser".equals(path))
{
userManager.del(username);
forward= "del_success.jsp";
}else if("/servlet/addUser".equals(path))
{
userManager.add(username);
forward= "add_success.jsp";
}elseif("/servlet/modifyUser".equals(path))
{
userManager.modify(username);
forward= "modify_success.jsp";
}else if("/servlet/queryUser".equals(path))
{
List userList = userManager.query(username);
request.setAttribute("userList",userList);
forward= "query_success.jsp";
}else
{
thrownew RuntimeException("請求失敗!");
}
request.getRequestDispatcher(forward).forward(request,response);
~~~
統一完成了轉向。當if語句是滿足某種條件,條件不同的時候轉到不同的頁面,添加有添加的邏輯,修改有修改的邏輯,這樣我們可以抽象出接口。對添加的action操作添加,對刪除的action做出刪除任務,對修改的action做出修改。把每一個if語句中的變成為類去實現,抽象出一個Action接口,接口中方法execute()方法,返回轉向路徑字符串。類圖如下所示(圖4.1)。

圖4.1
共同的Action接口,不同的實現。
Action接口代碼。
~~~
package com.bjpowernode.servlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
public interface Action {
public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception;
}
~~~
AddUserAction代碼。
~~~
package com.bjpowernode.servlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
public class AddUserActionimplements Action {
@Override
public String execute(HttpServletRequest request,HttpServletResponse response) throws Exception {
String username = request.getParameter("username");
//Stringsex = request.getParameter("sex");
//...........
//調用業務邏輯.
UserManager userManager = new UserManager();
userManager.add(username);
return"/add_success.jsp";
}
}
~~~
DelUserAction代碼。
~~~
package com.bjpowernode.servlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
public class DelUserActionimplements Action {
@Override
public String execute(HttpServletRequest request,HttpServletResponse response) throws Exception {
String username = request.getParameter("username");
//String sex = request.getParameter("sex");
//...........
//調用業務邏輯.
UserManager userManager = new UserManager();
try
{
userManager.del(username);
}catch(Exceptione)
{
return"del_error.jsp";
}
return"/del_success.jsp";
}
}
~~~
ModifyUserAction代碼。
~~~
package com.bjpowernode.servlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
public class ModifyUserActionimplements Action {
@Override
public String execute(HttpServletRequest request,HttpServletResponse response) throwsException {
String username = request.getParameter("username");
//String sex = request.getParameter("userId");
//...........等其他...
//調用業務邏輯.
UserManager userManager = new UserManager();
userManager.modify(username);
return"/modify_success.jsp";
}
}
~~~
QueryUserAction代碼。
~~~
package com.bjpowernode.servlet;
import java.util.List;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
public class QueryUserActionimplements Action {
@Override
public String execute(HttpServletRequest request,HttpServletResponse response) throwsException {
String username = request.getParameter("username");
//Stringsex = request.getParameter("userId");
//其他查詢條件.
//...........等其他...
//調用業務邏輯.
UserManager userManager = new UserManager();
List userList = userManager.query(username);
request.setAttribute("userList",userList);
return"/query_success.jsp";//轉向路徑都可以通過配置文件讀取。
}
}
~~~
這樣使用多態方式調用不同的Action,轉向代碼如下所示。
~~~
//用多態的方式.
Action action = null;
if("/servlet/delUser".equals(path))
{
action= new DelUserAction();
}else if("/servlet/addUser".equals(path))
{
action= new AddUserAction();
}else if("/servlet/modifyUser".equals(path))
{
action= new ModifyUserAction();
}else if("/servlet/queryUser".equals(path))
{
action= new QueryUserAction();
}else
{
throw new RuntimeException("請求失敗!");
}
//取得action后傳遞過去。動態調用ACtion中的execute方法。
String forward = null;
try{
forward= action.execute(request,response);
}catch (Exception e) {
e.printStackTrace();
}
//根據路徑完成轉向。
request.getRequestDispatcher(forward).forward(request, response);
~~~
上述調用不同的action,我們可以把不同的請求和對應的action配置到自己的xml文件中。配置哪個請求對應哪個Action。
~~~
<action-config>
<action path="/servlet/delUser" type="com.bjpowernode.servlet.DelUserAction">
<forward name="success">/del_success.jsp</forward>
<forward name="error">/del_error.jsp</forward>
</action>
<action path="/servlet/addUser" type="com.bjpowernode.servlet.AddUserAction">
<forward name="success">/add_success.jsp</forward>
<forward name="error">/add_error.jsp</forward>
</action>
<action path="/servlet/modifyUser" type="com.bjpowernode.servlet.ModifyUserAction">
<forward name="success">/modify_success.jsp</forward>
<forward name="error">/modify_error.jsp</forward>
</action>
<action path="/servlet/queryUser" type="com.bjpowernode.servlet.QueryUserAction">
<forward name="success">/query_success.jsp</forward>
<forward name="error">/query_error.jsp</forward>
</action>
</action-config>
~~~
這樣我們就可以讀取配置文件來進行相應的操作。每個action對應著一些信息,它的class,執行成功以及執行失敗的配置。我們在讀取配置文件的時候可以把這些放到Map對象中。代碼如下所示。
~~~
ActionMapping
{
private String path;
private String type;
Map forwardMap;
}
forwardMap
{
key="success";
value="/del_success.jsp"
key="error";
value="/del_error.jsp";
}
Map map = new HashMap();
map.put("/servlet/delUser",);
map.put("/servlet/addUser",);
map.put("/servlet/modifyUser",);
map.put("/servlet/queryUser",);
//如果是刪除的ActionMapping存儲如下:
actionMapping
{
path="/servlet/delUser";
type="com.bjpowernode.servlet.DelUserAction";
forwardMap
{
key="success",value="/del_success.jsp";
key="error",value="/del_error.jsp";
}
}
String path ="/servlet/delUser";
//根據截取的URL請求,到Map中取得本次請求對應的Action。
ActionMapping actionMapping =(ActionMappint)map.get(path);
// 取得本次請求對應的Action類的完成路徑。
String type =actionMappint.getType();//com.bjpowernode.servlet.DelUserAction
//通過反射動態實例化Action
Aciton action =(Action)class.forName(type).newInstance();
//取得action后傳遞過去。動態調用ACtion中的execute方法。
String forward =action.execute(request,response);
//根據路徑完成轉向。
request.getRequestDispatcher(forward).forward(request,response);
~~~
我們用時序圖來描述上述調用過程(如圖4.2)。???????
???????????

圖4.2
Struts就是采用上述思路。Struts框架是把上圖中前端控制器servlet進行了封裝,我們只要繼承struts的Action去調用業務邏輯和轉向。讀取配置文件的工作也是封裝到了struts框架中。前篇講解了struts框架的應用實例,我們可以進行對比。
### 版本五 采用struts框架
[采用struts框架完成登錄示例](http://blog.csdn.net/lovesummerforever/article/details/17348871)。
這樣我們對struts由來,以及struts封裝了哪些東西從而方便了程序員,不再重復的寫重復的代碼。下一篇[struts控制器DispatchAction.](http://blog.csdn.net/lovesummerforever/article/details/18967831)
- 前言
- Struts旅程(一)Struts簡介和原理
- struts旅程(二)Struts登錄示例
- Struts旅程(三)Struts表單處理器ActionForm(靜態動態)
- Struts旅程(四)MVC向struts MVC框架演變過程
- Struts旅程(五)struts控制器DispatchAction
- Struts旅程(六)Struts頁面轉發控制ActionForward和ActionMapping
- Hibernate旅程(一)Hibernate架構概述
- Hibernate旅程(二)Hibernate實例
- Hibernate旅程(三)Hibernate持久化對象的三個狀態
- Hibernate旅程(四)Hibernate對數據庫刪除、查找、更新操作
- Hibernate旅程(五)Hibernate映射--基本類映射和對象關系映射
- Hibernate旅程(六)Hibernate映射--繼承映射
- Hibernate旅程(七)Hibernate緩存機制--一級緩存
- Hibernate旅程(八)Hibernate緩存機制--二級緩存
- Hibernate旅程(九)Hibernate緩存機制--查詢緩存
- Spring旅程(一)為什么使用Spring
- Spring旅程(二)非Spring向Spring過渡-- Spring IOC容器的使用
- Spring旅程(三) AOP--Spring AOP容器基礎
- Spring旅程(四) AOP--Spring AOP實例
- SSH旅程(五)Spring運用到Hibernate中
- SSH旅程(六)Spring和struts結合(方案一)