版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
我们所学习的技术框架有很多,例如struts1、struts2、JSF、Spring、SpringMVC、Hibernate、ibatis····在上篇博客我说了我们可能在开发的路途上会要学习这些框架,我也给出了我对框架学习的几点:
我们首先要看一下这个框架属于开发结构中的那一层。因为我们的开发都是要用分层的思想来做的,所以我们第一个就要看看我们开发分层中,各个层次之间有哪些框架。
我们从图上看到了那些框架属于哪一层的(这里还有很多框架没有涉及到)。之后我们来看一些常用的框架(这个常用相对于个人而言,我这里所说的常用针对我自己来说,如果这里我没有介绍全的话,大家可以到相关的框架官网去查阅一下资料自主学习)。
下面我就简单的介绍一些我经常使用的框架的结构和一些分析:
Struts框架(分为struts1和struts2):
一、Struts框架结构图:
优点:
1.Struts框架是一个基于mvc的框架,所以它继承了所有mvc的优点,例如:复用性好,团队开发分工明确,结构层次分明等
2.给程序开发者在servlet层上节约了大量的开发时间,应用程序开发者不再去触及大量的servlet的编写,仅仅变换为配置文件。
二、Struts1框架
1.框架的结构图:
2.Struts1框架有五个常用对象:actionservlet、actionmapping、actionform、action、actionforward
a)Actionservlet是核心控制,URL地址映射、ActionForm的匹配、Action的执行都需要这个类来进行导航
b)Actionmapping:它们可将请求URI映射到Action类,并且将Action类与ActionFormbean相关联
c)Actionform:收集表单数据
d)Action:完成所需的业务逻辑,确定要跳转的页面
e)Actionforward:用来封装转发路径的
3.Struts1框架的执行流程:
1)检索和用户匹配的ActionMapping实例,如果不存在,就返回请求路径无效的错误信息
2)如果ActionForm实例不存在,就创建一个ActionForm的对象,把客户提交的表单数据封装到ActionForm对象中。
3)根据配置信息决定是否要进行表单验证,如果需要,就调用ActionForm的validate()方法
4)如果validate()方法放回null,或者并不包含ActionMessage的ActionError对象,就表示验证成功
5)ActionServlet根据ActionMapping所包含的映射信息决定将请求转发给那个action,如果相应的action实例不存在,就先创建这个action对象,然后再调用这个action的excute()方法
6)action的execute()方法返回一个ActionForword对象,ActionServlet会把客户请求转发给ActionForword对象所指向的JSP组件
7)ActionForword对象指向JSP组件生成动态网页返回给客户
4.优点:和struts框架的优点相同
5.缺点:
1)表现层技术单一:仅能用jsp
2)与servletAPI耦合性高,难于测试(httpservletrequest、httpservletresponse)
3)严重依赖于ServletAPI(继承action,继承actionform),与struts1框架耦合性太高
这篇博客就写到这里,如果再写篇幅可能会过长,对读者的阅读造成负面影响,所以我会在下面的博客中陆续介绍我经常使用的框架,当然我也会在这些同层之间的框架的分析中加入各个框架的区别,当然在适当的地方会画一些图片来表示他们之间的知识关联性,希望读者能够我一些建议和意见。
在上篇博客中,我简单的介绍了我们分层开发中每一层中拥有的框架,而且介绍了我常用的框架struts1的结构和原理分析,那么今天我继续介绍我熟悉的框架struts2的框架的结构和原理分析。
在说struts2框架之前,我要先介绍另外一个框架webwork框架,这个框架也是一个mvc的框架,这个框架的设计思路是采用拦截链将用户的请求的数据转发到Action中,并负责将Action的处理结果转换成对用户的响应。它的这种设计思路能够和ServletAPI分离,鉴于我们的上篇博客介绍的struts1的缺点,所以webwork框架解决了struts1的这个缺点。
我们来看一下webwork框架的结构图:
有了这个流程图,我就不给大家讲解具体的原理流程了,它采用的是拦截链的机制,通过这些拦截链完成用户的相应请求,从而与servletAPI分离,当与servlet分离开的时候,也就是表明和容器解耦了;另外,我们从结构图中看到它的视图模版有jsp、FreeMarker等等,它的表示层技术比struts1框架的饱满许多。
所以,webwork框架解决了struts1框架存在的问题,而且它的设计思路是非常好的,鉴于此,struts2框架就在struts1框架的基础上引入了webwork框架的设计思路应运而生了。所以我们就能够发现struts2兼具struts1的特性而且通过引入webwork框架的设计思路解决了struts1的一些缺点。
struts2框架的大致的体系图:
从图中我们能够看出它是引入的webwork框架的设计思路,而且它也是基于mvc的一个开源的框架。之后我们来说一下struts2框架的一个执行流程(流程图和webwork框架非常类似):
浏览器发送请求,通过几层过滤器完成一些功能,之后到actionmapper中,之后将请求传到核心控制器中核心控制器filterDispatcher根据请求决定调用合适的Action调用webwork的拦截器链自动请求通用功能,如校验之类的操作回调action的execute方法,获取用户请求执行相应的业务逻辑之后返回字符串,匹配result,之后跳转到相应的视图或其他的文档之后在执行相应的拦截器链自动请求功能,随后转到web客户端。
这样我们就对struts2框架的结构上的东西做了一个简单的介绍。在上篇博客讲解了struts1框架,所以有必要在这里对他俩进行一下对比(我仅仅总结了五条我认为比较重要的,以后如果发现其他的在随时补充):
在Action实现类方面的对比(struts1的Action继承action,struts2实现接口,也可以不实现,可以定制服务)线程模式方面的对比(struts1存在线程安全问题,struts2不存在)
ServletAPI依赖方面的对比(struts1依赖servletAPI,struts2不是)可测性方面的对比(struts1难测试,依赖容器,struts2不是)封装请求参数的对比(struts1使用actionform;struts2直接写到action,并且支持pojo对象)
在上篇博客中介绍了struts2框架的原理和流程分析,可以说struts框架一路走来,改变非常大,而且让我们开发人员变得更加轻松,里面的设计理念的改变也是让我们编程人员的思路得到更大的扩展。
可以说,一个先进的技术或者框架就是要不断的进步才能永远让编程人员喜欢和使用,一个优秀的编程人员也是要不断的进步才能永远让这个世界变得更加绚丽多彩。
其实编程就是这样有意思的!
前面说了一些宏观上学习框架相关的思想方面的东西,下面继续来介绍我经常使用的框架和框架的分析,这篇博客主要介绍的是hibernate框架。
首先说hibernate框架是数据持久层的框架,这个框架是非常强大的,它让编程人员纯粹的用面向对象的方式来做开发,让编程人员所面对的都是对象。仅仅从这一点它的设计思路就是非常让编程人员喜爱的。
回想我们普通的开发流程,和客户沟通定需求,抽象出来原型,从原型中建立数据模型到库表结构的建立,之后在映射成对象模型,之后在用oo的设计思想完成后续的程序开发。但是当我们使用了hibernate框架以后,原先的设计思路就显得不再那么具有优势了。我们直接建立对象模型,之后利用hibernate框架映射成数据模型,我们不再去考虑数据库关系模型的东西,仅仅考虑的东西仅仅就是类和对象,这样的开发才是面向对象的开发,也才是最接近人类思考问题的方式。所以hibernate框架的设计思路是非常好的。
hibernate框架设计思路的优越性其实体现在了它本身的框架的原理上。hibernate封装了JDBC,减轻了开发人员在持久层的大量重复性工作,它利用了java反射机制来实现程序的透明性;它就是通过这两点才达到从对象出发而非关系数据库出发的效果。
介绍这么多理论性的东西之后我们能够感觉到hibernate框架的强大,来看看它的结构图:
在hibernate框架中有几个比较重要的接口和类:Query接口:Query负责执行各种数据库查询。它可以使用HQL语句或SQL语句两种表达方式。Configuration类:Configuration类负责配置并启动Hibernate,创建SessionFactory对象SessionFactory接口:SessionFactory接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象Session接口:Session接口负责执行被持久化对象的CRUD操作Transaction接口:Transaction接口负责事务相关的操作
hibernate框架就是在利用这几个接口来封装了JDBC,而且我们用这些接口来操作数据库变得非常简单,减少了我们在持久层的代码量。
从这个结构图和我的一些分析就能发现hibernate框架是非常强大,而且它给我们开发人员的开发带来了非常大的便利,尤其是他的设计思路还有它的“全自动”的映射对象模型和关系模型。
但是hibernate框架也有它的一些缺点:既然是封装了JDBC,所以很明显它没有JDBC的效率高,尤其是在大量的处理表更新操作的时候。它有局限性,一个持久化类不能映射多个表它应对大数量的时候显得非常笨拙,这一点没有JDBC和接下来要介绍的IBatis框架
其实一项技术或者一个框架都有它的优缺点,选择最合适的才是王道。
这篇博客主要是介绍了hibernate框架的结构和分析,阐述了hibernate框架的优缺点,【具体详细使用要等到我的框架学习的后续文章】。总的来说hibernate框架在持久层的作用非常明显,我们懂得了它的优缺点之后,才能做到我们是否是要选择这个框架作为我们持久层开发的必须的技术支撑,所以这些我常用的框架结构和分析不单单是在介绍一些框架学习的宏观知识把控,更多的是在为将来做项目开发中选择合适的技术支撑做铺垫。
后续的博客在不断更新,希望这些博客能够对读者的开发过程带来帮助,当然如果读者对我的博客有什么好的建议或者意见,请与我联系。联系方式见博客侧边栏!
先看MVC模式流程图(其实MVC设计模式就是java中的model2。):
就像图上所标识的C层主要是Servlet层控制页面跳转,M层就是具体的业务处理逻辑,而JSP就是所谓的V层。MVC是有别于我们所说的三层,我们平常所说的三层是UI层、BLL层、DAL层,具体的区别如图:
从图上能看出来,JSP和Servlet构成了UI层,而Model层分成了BLL层和DAL层(也就是业务逻辑和数据持久层)。
从理论上认清了MVC设计模式之后,下面开始动手敲一个MVC设计模式示例代码:
JSP索引页面index.jsp:
[html]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?<%@
page
language="java"
contentType="text/html;
charset=GB18030"
pageEncoding="GB18030"%>
<!DOCTYPE
html
PUBLIC
"-//W3C//DTD
HTML
4.01
Transitional//EN"
"/TR/html4/loose.dtd">
<html>
<head>
<meta
http-equiv="Content-Type"
content="text/html;
charset=GB18030">
<title>Insert
title
here</title>
</head>
<body>
<form
action="servlet/addUser.action"
method="post">
姓名:<input
type="text"
name="username"
>
<input
type="submit"
value="提交">
</form>
</body>
</html>
业务逻辑代码UserManager:
[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
java.util.ArrayList;
import
java.util.List;
public
class
UserManager
{
public
void
addUser(String
username){
System.out.println("UserManager.addUsre()>username:"+username);
}
public
void
delUser(String
username){
System.out.println("UserManager.delUser()>username:"+username);
}
public
void
modifyUser(String
username){
System.out.println("UserManager.modifyUser()>username"+username);
}
public
List
queryUser(String
username){
System.out.println("UserManager.queryUser()>username"+username);
List
userList=new
ArrayList();
userList.add("a");
userList.add("b");
userList.add("c");
return
userList;
}
}
Servlet控制代码:
[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
java.io.IOException;
import
java.util.List;
import
javax.servlet.ServletException;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
class
TestServlet
extends
HttpServlet
{
protected
void
doGet(HttpServletRequest
request,
HttpServletResponse
response)
throws
ServletException,
IOException
{
String
requestURI=request.getRequestURI();
System.out.println("request="+requestURI);
String
path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf("."));
System.out.println("path="+path);
String
username=request.getParameter("username");
UserManager
userManager=new
UserManager();
//userManager.addUser(username);
String
forward="";
if("/servlet/delUser".equals(path)){
userManager.delUser(username);
forward="/del_success.jsp";
}else
if("/servlet/addUser".equals(path)){
userManager.addUser(username);
forward="/add_success.jsp";
}else
if("/servlet/modifyUser".equals(path)){
userManager.modifyUser(username);
forward="/modify_success.jsp";
}else
if("/servlet/queryUser".equals(path)){
List
userList=userManager.queryUser(username);
request.setAttribute("userList",
userList);
forward="/query_success.jsp";
}else{
throw
new
RuntimeException("请求失败");
}
request.getRequestDispatcher(forward).forward(request,
response);
}
这个servlet代码主要实现的功能判断是那个页面请求服务器做那些操作,之后调用业务逻辑实现相应业务操作。
配置Servlet:
[html]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?<?xml
version="1.0"
encoding="UTF-8"?>
<web-app
xmlns:xsi="/2001/XMLSchema-instance"
xmlns="/xml/ns/javaee"
xmlns:web="/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="/xml/ns/javaee
/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID"
version="3.0">
<display-name>test_Servlet</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>TestServlet</servlet-name>
<servlet-class>com.cjq.servlet.TestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestServlet</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
</web-app>
输出结果:
通过上面的示例已经对MVC设计模式有了初步的认识,其实这个示例是对Struts框架学习的基础,只有弄清楚了这个实例才能弄清楚Struts框架的实现原理和Struts框架使用。
那么我们怎么才能通过这个示例引入Struts框架呢?这个问题从IF-Eles开始。
首先我们看到了TestServlet中出现了许多if-else语句,这样是非常不稳定的,这样的程序是非常不灵活的,以后如果有变化,那么维护是非常差的;而且我们在if-else中出现了大量的字符串,这样在coding的时候会出现写错,这样无形中给调试带来了麻烦。所以去掉if-else成了我们重构的第一步,也是我们进行Struts框架学习的第一步。
如何才能去掉If-ELSE呢?请看下一篇文章《深入浅出学习Struts1框架(二):重构MVC模式代码中跳转路径和业务逻辑》。
在上篇博文《深入浅出学习Struts1框架(一):一个简单mvc模式代码示例开始》中简单说了一下MVC模式代码的实现和MVC模式和三层架构的区别,并且留下一个问题—如何去掉TestServlet中的IF-Else语句块。
因为在TestServlet中出现了If-Else语句块,所以让程序变得不再灵活,让应付需求变化时变得笨拙。所以就承接上篇文章来重构一下TestServlet代码,主要是用继承多肽来进一步对TestServlet进行重构。虽然这一篇文章最后没有将if-else彻底去掉,但是比起上篇文章的代码显得更加灵活,也为下一篇彻底去掉If-else埋下伏笔。
下面进入重构阶段:
先看一下上篇文章的TestServlet代码:
[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
java.io.IOException;
import
java.util.List;
import
javax.servlet.ServletException;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
class
TestServlet
extends
HttpServlet
{
protected
void
doGet(HttpServletRequest
request,
HttpServletResponse
response)
throws
ServletException,
IOException
{
String
requestURI=request.getRequestURI();
System.out.println("request="+requestURI);
String
path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf("."));
System.out.println("path="+path);
String
username=request.getParameter("username");
UserManager
userManager=new
UserManager();
//userManager.addUser(username);
String
forward="";
if("/servlet/delUser".equals(path)){
userManager.delUser(username);
forward="/del_success.jsp";
}else
if("/servlet/addUser".equals(path)){
userManager.addUser(username);
forward="/add_success.jsp";
}else
if("/servlet/modifyUser".equals(path)){
userManager.modifyUser(username);
forward="/modify_success.jsp";
}else
if("/servlet/queryUser".equals(path)){
List
userList=userManager.queryUser(username);
request.setAttribute("userList",
userList);
forward="/query_success.jsp";
}else{
throw
new
RuntimeException("请求失败");
}
request.getRequestDispatcher(forward).forward(request,
response);
}
}
首先我们看到了在每个语句块中都出现了给forward赋值,其实也就是给页面跳转的路径赋值,针对每个请求路径判断来赋值跳转路径。另外每个IF-Else语句块中都有业务处理,我们要把这些业务处理分别放到类里面,让职责更加单一,这样更加符合面向对象的思路。
就从这里我们开始重构,我们可以将这个跳转路径和业务逻辑封装起来。
既然封装,那么我们就抽象出来一个借口,主要完成一个方法,这个方法主要的功能就是要完成业务逻辑封装和路径跳转的返回。随后建立四个类,主要实现相应的增删改查的业务处理和处理之后的跳转路径返回。
代码如下:
接口Action:[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
interface
Action
{
public
String
execute(HttpServletRequest
request,HttpServletResponse
response)
throws
Exception;
}
增删改查实现类:
添加用户实现类:[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?<pre
name="code"
class="java">package
com.cjq.servlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
class
AddUserAction
implements
Action
{
public
String
execute(HttpServletRequest
request,
HttpServletResponse
response)
throws
Exception
{
String
username=request.getParameter("username");
UserManager
userManager=new
UserManager();
userManager.addUser(username);
return
"/add_success.jsp";
}
}</pre><br><br>
删除用户实现类:[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
class
DelUserAction
implements
Action
{
public
String
execute(HttpServletRequest
request,
HttpServletResponse
response)
throws
Exception
{
String
username=request.getParameter("username");
UserManager
userManager=new
UserManager();
userManager.delUser(username);
return
"/del_success.jsp";
}
}
更新用户实现类:[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
class
ModifyUserAction
implements
Action
{
@Override
public
String
execute(HttpServletRequest
request,
HttpServletResponse
response)
throws
Exception
{
String
username=request.getParameter("username");
UserManager
userManager=new
UserManager();
userManager.modifyUser(username);
return
"/modify_success.jsp";
}
}
查询用户实现类:[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
java.util.List;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
class
QueryUserAction
implements
Action
{
@Override
public
String
execute(HttpServletRequest
request,
HttpServletResponse
response)
throws
Exception
{
String
username=request.getParameter("username");
UserManager
userManager=new
UserManager();
List
userList=userManager.queryUser(username);
request.setAttribute("userList",
userList);
return
"/query_success.jsp";
}
}
TestServlet类重构如下:
[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
java.io.IOException;
import
java.util.List;
import
javax.servlet.ServletException;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
class
TestServlet
extends
HttpServlet
{
protected
void
doGet(HttpServletRequest
request,
HttpServletResponse
response)
throws
ServletException,
IOException
{
String
requestURI=request.getRequestURI();
System.out.println("request="+requestURI);
String
path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf("."));
System.out.println("path="+path);
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("请求失败");
}
String
forward=null;
try{
forward=action.execute(request,
response);
}catch(Exception
e){
e.printStackTrace();
}
request.getRequestDispatcher(forward).forward(request,
response);
}
}
运行结果:
这样TestServlet类虽然没有彻底去掉If-Else,但是这样的代码变得更加简练,利用多肽实现业务逻辑处理和路径跳转返回。职责更加清晰,让维护变得更加轻松。
问题遗留:
If-else语句块没有彻底剔除,而且程序中依旧出现了过多的字符串,所以程序依旧是不灵活,而且字符串过多增加调试的复杂性。所以下一篇文章就把if-else语句块剔除,并且把字符串放到配置文件来用dom4j来动态读取。
我们离Struts框架越来越近,当我们把if-else和字符串剔除之后就会出现Struts框架的雏形。期待下一篇文章。
在《深入浅出学习Struts1框架(一):一个简单mvc模式代码示例开始》和《深入浅出学习Struts1框架(二):重构MVC模式代码中跳转路径和业务逻辑》文章中已经说了分层和mvc模式的区别,和一些为了去掉mvc模式代码中的TestServlet类中的if-else。因为if-else在程序代码中是相对不稳定的,所以通过去掉if-else来引入对struts框架的学习。
在《深入浅出学习Struts1框架(二):重构MVC模式代码中跳转路径和业务逻辑》中我们已经抽象出来了一个接口和四个实现类,主要封装了业务处理和页面跳转路径字符串放回,以便利用多肽来重构了TestServlet代码(具体见博客)。
在上两篇博客我们遗留了两个问题,一是if-else,二是字符串太多。今天这篇博客就要解决这两个问题。
上一篇TestServlet重构后的代码:
[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
java.io.IOException;
import
java.util.List;
import
javax.servlet.ServletException;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
class
TestServlet
extends
HttpServlet
{
protected
void
doGet(HttpServletRequest
request,
HttpServletResponse
response)
throws
ServletException,
IOException
{
String
requestURI=request.getRequestURI();
System.out.println("request="+requestURI);
String
path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf("."));
System.out.println("path="+path);
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("请求失败");
}
String
forward=null;
try{
forward=action.execute(request,
response);
}catch(Exception
e){
e.printStackTrace();
}
request.getRequestDispatcher(forward).forward(request,
response);
}
}
解决字符串问题,当然就要用到配置文件了,用到配置文件就要有用来读取配置文件的相关的类和方法,这里就用dom4j中的类来读取配置文件,这里的配置文件的书写是有点逻辑上的难度的。
我们来看TestServlet中的代码,我们要在这个testservlet中实现读取配置文件和path比较,还有利用多肽实例化相应的实现类,最后通过实例化的实现类的方法来返回跳转路径,最终跳转到相应的页面。
所以我们的配置文件就要不仅配上testservlet中出现的字符串,还要配置相应的Action接口的实现类(我们可以利用反射来实例化该类的对象,进而使用这个类的所有属性和方法),另外还有跳转路径字符串。这样我们的配置文件就变成了如下代码所示:[html]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?<?xml
version="1.0"
encoding="UTF-8"?>
<action-config>
<action
path="/servlet/delUser"
type="com.cjq.servlet.DelUserAction">
<forward
name="success">/del_success.jsp</forward>
<forward
name="error">/del_error.jsp</forward>
</action>
<action
path="/servlet/addUser"
type="com.cjq.servlet.AddUserAction">
<forward
name="success">/add_success.jsp</forward>
<forward
name="error">/add_error.jsp</forward>
</action>
<action
path="/servlet/modifyUser"
type="com.cjq.servlet.ModifyUserAction">
<forward
name="success">/modify_success.jsp</forward>
<forward
name="error">/modify_error.jsp</forward>
</action>
<action
path="/servlet/queryUser"
type="com.cjq.servlet.QueryUserAction">
<forward
name="success">/query_success.jsp</forward>
<forward
name="error">/query_error.jsp</forward>
</action>
</action-config>
我们有了配置文件之后就要想法通过相关类读取,并且实现相应的功能。所以这里用dom4j来读取完成。其实如果能把这个逻辑捋顺之后就能发现,其实懂我们利用dom4j读取完配置文件的时候,我们是取得的是一个配套的匹配路径字符串、相应业务逻辑类还有处理业务逻辑之后跳转页面路径字符串。这样我们就能直截了当的去掉了if-else。(这里可能逻辑上会出现一些困难,但是看到下面的重构之后的testservlet中的代码和读取配置文件之后的代码就会一目了然)。
现在等待解决的问题就是我们要把从配置文件取得的一整套内容放到那里,当然这是毋庸置疑的要放到类中。所以我们就建立一个ActionMapping类来放我们的那一整套内容。
ActionMapping中的代码如下:
[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
java.util.Map;
public
class
ActionMapping
{
private
String
path;
private
Object
type;
private
Map
forwardMap;
public
String
getPath()
{
return
path;
}
public
void
setPath(String
path)
{
this.path
=
path;
}
public
Object
getType()
{
return
type;
}
public
void
setType(Object
type)
{
this.type
=
type;
}
public
Map
getForwardMap()
{
return
forwardMap;
}
public
void
setForwardMap(Map
forwardMap)
{
this.forwardMap
=
forwardMap;
}
}
现在ActionMapping类已经有了,剩下的工作就是要利用dom4j来读取配置文件类,具体代码如下:
[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
java.io.InputStream;
import
java.util.HashMap;
import
java.util.Iterator;
import
java.util.Map;
import
org.dom4j.Document;
import
org.dom4j.DocumentException;
import
org.dom4j.Element;
import
org.dom4j.io.SAXReader;
public
class
XmlConfigReader
{
private
static
XmlConfigReader
instance=new
XmlConfigReader();
ActionMapping
actionMapping=new
ActionMapping();
private
Document
doc;
private
Map
actionMap=new
HashMap();
private
XmlConfigReader(){
try
{
SAXReader
reader=new
SAXReader();
InputStream
in=Thread.currentThread().getContextClassLoader().getResourceAsStream("action_config.xml");
doc=reader.read(in);
}
catch
(DocumentException
e)
{
//
TODO
Auto-generated
catch
block
e.printStackTrace();
}
}
public
ActionMapping
getActionMapping(String
path){
synchronized(this){
Object
type=null;
/*if(action.containsKey(path)){
type=action.get(path);
}*/
Element
eltAction
=
(Element)doc.selectObject("//action[@path=\""
+
path
+
"\"]");
try{
type=Class.forName(eltAction.attributeValue("type")).newInstance();
}catch(Exception
e){
e.printStackTrace();
}
Element
eltForwards
=
eltAction.element("forward");
for
(Iterator
iter
=
eltForwards.elementIterator();
iter.hasNext();)
{
Element
eltForward
=
(Element)
iter.next();
actionMap.put(
eltForward.attributeValue("name"),eltForward.getTextTrim());
}
actionMapping.setPath(path);
actionMapping.setType(type);
actionMapping.setForwardMap(actionMap);
return
actionMapping;
}
}
public
static
synchronized
XmlConfigReader
getInstance(){
return
instance;
}
/**
*
@param
args
*/
public
static
void
main(String[]
args)
{
//
TODO
Auto-generated
method
stub
ActionMapping
actionMapping=XmlConfigReader.getInstance().getActionMapping("/servlet/delUser");
System.out.println(actionMapping.getPath());
System.out.println(actionMapping.getType());
System.out.println(actionMapping.getForwardMap().toString());
}
}
我们通过返回ActionMapping来动态创建出action相应的实现类,进而完成业务逻辑和页面跳转,重构之后的TestServlet代码如下:
[java]
\o"viewplain"viewplain
\o"copy"copy
\o"print"print\o"?"?package
com.cjq.servlet;
import
java.io.IOException;
import
java.util.List;
import
javax.servlet.ServletException;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
public
class
TestServlet
extends
HttpServlet
{
protected
void
doGet(HttpServletRequest
request,
HttpServletResponse
response)
throws
ServletException,
IOException
{
String
requestURI=request.getRequestURI();
System.out.println("request="+requestURI);
String
path=requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf("."));
System.out.println("path="+path);
String
forward="";
ActionMapping
actionMapping=XmlConfigReader.getInstance().getActionMapping(path);
Action
action=(Action)actionMapping.getType();
try
{
forward=action.execute(request,
response);
}
catch
(Exception
e)
{
//
TODO
Auto-generated
catch
block
e.printStackTrace();
}
request.getRequestDispatcher(forward).forward(request,
response);
}
protected
void
doPost(HttpServletRequest
request,
HttpServletResponse
response)
throws
ServletException,
IOException
{
doGet(request,response);
}
}
我们可以清晰的看到if-else已经没有了,字符串也已经没有了。通过这篇文章对if-else还有字符串问题的解决,又一次重构了testservlet代码,程序相对灵活许多。通过这一次的重构,我们已经看到了struts框架的雏形,下一篇文章就真正开始了struts框架的学习。
下一篇引子:
其实框架就是对程序的高度封装,我们经历了这三篇文章之后,一步一步重构,一步一步封装,逐步向框架靠拢,其实框架没有什么难的,其实没有学习框架之前感觉挺神秘,其实如果一步一步来研究之后发现框架就是封装的高度化,分层的高度化。
下一篇文章《深入浅出学习struts1框架(四):从MVC模式代码认识struts框架》就借助刚刚完成的实例来简单认识struts框架,看看真正的struts框架和我们这个mvc小实例有什么相同和相异之处。《深入浅出学习Struts1框架(一):一个简单mvc模式代码示例开始》分析mvc和三层关系开始,引出这个mvc设计模式实例,到《深入浅出学习Struts1框架(二):重构MVC模式代码中跳转路径和业务逻辑》抽象封装业务处理和路径跳转,再到《深入浅出学习Struts1框架(三):彻底去掉TestServlet中的字符串和if-else语句块》去掉if-else语句块和字符串,经过三篇文章循序渐进的重构了一个mvc设计模式实例,其实也就是重构出来了一个struts框架雏形。今天来看看什么是struts1框架。1.
框架
框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法。也就是说框架是一个半成品的应用程序。我们所面对的应用程序一般都是分为两部分,一部分是业务相关的组件部分,另一部分是和业务无关的组件部分。而我们知道和业务相关的组件部分的重用性是非常低的,这也是显而易见的事情;而和业务无关的组件部分,如验证、异常、程序流程控制等等服务组件的复用性是非常高的。所以当人们在不同的应用程序中抽出共性的组件,构成一个半成品应用程序,这时候框架就应运而生了。2.
Struts1
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 大自然的语言同步练习1
- 河北省保定市2025-2026学年高二下学期5月期中考试语文试题
- 胰腺癌新辅助治疗后病理评估挑战与进展2026
- 2025年建筑行业数字化转型技术架构案例
- 2026届湖北省随州市高三压轴卷历史试卷含解析
- 循证康复实践中的社会支持系统
- 2026年交通运输行业智能驾驶技术发展创新报告
- 2026年城市交通诱导系统与智能交通数据分析融合可行性研究报告
- 康复评估的循证康复循证实践策略
- 康复评估的循证康复循证实践完善
- 上海银行来访管理制度
- 新婚姻法测试题及答案
- 《矿井通风与安全》课件
- 煤矿雨季三防培训
- 2025执业兽医小动物诊疗试题及答案
- 高一物理5.4抛体运动的规律课件
- 人工智能在半导体制造中的未来应用
- 印刷服务售后服务方案
- 医疗器械安全检查制度
- 2021版十八项医疗质量安全核心制度附流程图
- DB33T896-2024高等级公路沥青路面设计规范
评论
0/150
提交评论