`
gzhzh
  • 浏览: 25139 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

发布一个MVC开发框架SimpleFace

阅读更多

前言

 

  做过不少的J2EE项目,由于个人的习惯问题,很希望能保持表现层代码的高度简洁,也希望页面的HTML能尽可能地保持原貌(不知是否可称之为洁癖^_^)。从以前就一直使用的Struts到后来使用过一段时间的JSF,都为自己的开发工作带来了非常大的便利和喜悦,但由于前面所说的个人习惯的原因,对于这两个非常优秀的框架还是感到稍嫌繁琐,特别是那些几乎必须使用的侵入性极高的页面标签,如果不使用的话就几乎发挥不出框架的优势。大多数时候,个人只是需要项目的总体结构能实现MVC而已,至于页面上的数据显示、合法值验证等,则交由标准的JSTL标签、模版组件及JS验证框架来做,当然,要求安全性高的合法值验证,还需要框架在后台验证多一次。于是前段时间便萌发了开发一个简单的MVC框架来自用的想法,毕竟它的原理并不复杂,而且自己也从来都不让正在使用的框架包揽太多的东西,所以只需要去实现必需的功能,运行效率必然可以提高,在以后的开发上也能让自己省多点事。既然要求简单(主要是使用上很简单),所以就起了个贴切的名字——SimpleFace。

  事实上,在开发的过程中,有些原本不打算要的功能还是觉得不可或缺的,否则就丝毫没有应用的价值了。当然,这些功能是应用上的必备功能,在使用上的简单化和非侵入性上与我的原则始终保持一致。最终,SimpleFace实现了请求路径与处理方法及处理结果转发的可配置化,同时支持Freemarker模版的使用;支持国际化资源文件的配置使用;支持极其方便的文件上传;支持类似Struts的通配符配置以简化配置工作。

  由于开发SimpleFace的动机只是为了自用,而且个人的水平的确有限,难免会有很多不足,相比那些标杆框架更是显得幼稚,所以不敢奢望让很多人去使用它,发布出来完全是为了分享与交流。当然,如果您觉得可以在您的项目中使用它,我会感到很高兴,如果您能不啬给出改进的建议,我会非常感谢您。也许有人会觉得做这个东西纯粹是无聊,我也明白造轮子的说法,我只是想把自己所学的那丁点知识转化为一点成果,对日后的开发工作中起到一点帮助。目前我还不能保证这个框架的稳定性,因为才做出来不久,我还没有应用到我的项目上,但有经过几轮的各项测试,暂时没有发现什么问题。因此还是随着时间的推移,来不断发现问题并予以改善吧。

 

  附件:

  1、SimpleFace-1.0_bin.rar(运行所需JAR包、使用例子工程[Eclipse]、API文档)

  2、SimpleFace-1.0_src.rar(SimpleFace源码)

 

一、SimpleFace工作原理示意图

 

  由于手头上的画图工具无法完全表达出我想要的效果,所以将就着画出了下面这张图。

 

 

  不难看出,SimpleFace的结构与Struts的结构有点类似,这种经典合理的结构非我辈可以突破。

 

二、快速上手

 

  以附件例子中的用户登录演示部份内容来讲解。

 

  (1)配置

 

  1、将核心的几个jar(SimpleFace-1.0.jar、依赖dom4j.jar、commons-logging.jar、jaxen.jar)放置到WEB-INF\lib目录下;

 

  2、web.xml配置

    <servlet>
      <servlet-name>simpleface</servlet-name>
      <servlet-class>com.funper.simpleface.action.DispatcherServlet</servlet-class>
      <init-param>
        <param-name>config</param-name>
        <param-value>/WEB-INF/simple-face.xml</param-value>
      </init-param>
      <!--在这里还可以加上其他三个可选参数:采用何种编码、允许上传文件最大字节数、允许上传文件类型。附件中的例子有提供-->
      <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
      <servlet-name>simpleface</servlet-name>
      <url-pattern>*.sf</url-pattern>
    </servlet-mapping>

 这样就使得所有后缀为.sf的请求URI都由SimpleFace来处理。

 

  3、SimpleFace的核心配置文件simple-face.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE simple-face PUBLIC "-//SimpleFace//DTD 1.0//EN"
"http://www.funper.com/dtds/simple-face1.0.dtd">
<!--已由上面的DTD文档定义配置文档的规范-->
<simple-face>
  <global>
    <!--全局转发配置(如果在Action中找不到对应的result,则在这里找)[可选]-->
    <results>
      <result name="success">/common/success.jsp</result>
      <result name="failure">/common/failure.jsp</result>
    </results>
    <!--Freemarker模版文件目录配置(如果配置此项,则必须将freemarker.jar引入工程)[可选]-->
    <!--freemarker directory="/WEB-INF/templates"/-->
    <!--国际化资源文件配置[可选]-->
    <!--resources baseName="net.sf.demo.Messages"/-->
  </global>
  <!--action配置-->
  <actions>
    <!--action的class别名配置(如果设置了别名,则在action的class属性中只需填写别名而无需填写类全名)[可选]-->
    <classAlias name="user" class="net.sf.demo.UserAction"/>

    <!--用户登录演示, 支持通配符配置, 在附件中的例子有演示-->
    <action path="/login" method="login" class="user">
      <!--result的type属性可选(freemarker|redirect|forward,不选默认为forward)-->
      <result name="success" type="redirect">/index.jsp</result>
    </action>

  </actions>
</simple-face>

有Struts使用经验的朋友一定能一眼就看得明白simple-face.xml的内容,加上还算详细的注释,不需要多说些什么了。在配置文件里有些标签的名称我沿用了Struts一惯使用的名称,我可不想搞出一些词不达意的新的名称出来以示自己有什么独特的创举,毕竟如果我没有使用Struts和JSF的经验的话,我是不可能开发得出来这个所谓的框架的。

 

  (2)功能实现

 

  在配置文件中可以看到,用户登录的Action配置,请求path为“/login”,处理请求的类的别名为”user“,对应的类为“net.sf.demo.UserAction”,处理请求的类方法名为“login”。

 

  1、登录页面login.jsp的表单内容

  <form name="form1" method="post" action="login.sf">
  <table width="300" border="0">
    <tr align="center">
      <td height="26" colspan="2" align="center">::用户登录::</td>
    </tr>
    <tr>
      <td width="84" height="26" align="right">登录帐号:</td>
      <td width="205"><input type="text" name="user.userName"></td>
    </tr>
    <tr>
      <td width="84" height="26" align="right">登录密码:</td>
      <td bgcolor="#FFFFFF"><input type="password" name="user.userPwd"></td>
    </tr>
    <tr align="center">
      <td height="30" colspan="2" bgcolor="#FFFFFF">
	    <input type="submit" name="submitButton" value="登 录">
	  </td>
    </tr>
  </table>
  </form>

 

  2、用户数据模型User.java

public class User  {

	private String userName;//用户名
	private String userPwd;  //用户密码

	public void setUserName(String name) {
		this.userName = name;
	}

	public void setUserPwd(String pwd) {
		this.userPwd = pwd;
	}
	
	public String getUserName() {
		return userName;
	}

	public String getUserPwd() {
		return userPwd;
	}
}

 

  3、UserAction.java

import com.funper.simpleface.DataModel;
import com.funper.simpleface.action.FaceContext;

public class UserAction {
	
	private static final String SUCCESS="success";
	private static final String FAILURE="failure";

	@DataModel
	private User user;	//用户数据模型——对于数据模型来讲,要与提交的参数值绑定就必须使用@DataModel注解,否则不能绑定。如果直接把用户名和用户密码定义在这里,则不需要使用注解)

	public void setUser(User user)
	{
		this.user=user;
	}
	
	/**
	 * 登录方法
	 * @param context 方法上下文参数
	 * @return String
	 */
	public String login(FaceContext context)
	{
		//关于上下文参数FaceContext,可以从中获取到HttpServletRequest、HttpServletResponse、ServletContext、国际化资源ResourceMessages、文件上传监控器UploadWatcher等对象,在附件中的例子均有体现。
		
if("".equals(user.getUserName())||"".equals(user.getUserPwd()))
		{
			//登录失败
			return FAILURE;
		}
		else
		{
			//登录成功
		}
		return SUCCESS;
	}
}

到此,已经展示了SimpleFace的基本使用方法。可以看到, 较Struts1.x而言,所需代码量减少了不是一般的多,配置文件内容也很少,而且还同样支持使用通配符来配置。较Struts2.0而言,所需代码量差别不大。Struts2.0功能非常强大,所耗资源也不小,如果项目不大的话,又想使用MVC框架,SimpleFace的性能应该是非常高的,因为它相对Struts来说,实现上非常简单,执行步骤与所需要加载的类也非常少。我已经使用JMeter和JProfilter来做过几轮测试,验证了这一点。

 

三、文件上传

 

  1、上传页面upload.jsp的表单内容

<form name="form1" method="POST" enctype="multipart/form-data" action="/Upload/uploadBySign.sf">  
         title:<input name="title" type="text" size="40"><br>  
         File:<input type="file" name="myFile"><br>  
         <input type="submit" name="submitButton" value="提 交">  
</form> 

 

   2、配置

<action path="/Upload/uploadBySign" method="uploadBySign" class="net.sf.demo.UploadAction"/>

 

  3、UploadAction.java

import java.io.File;
import java.io.IOException;

import com.funper.simpleface.upload.UploadFile;
import com.funper.simpleface.action.FaceContext;

public class UploadAction {

	private String title;  //对应<input type="text" name="title">
	private UploadFile myFile;  //对应<input type="file" name="myFile">
	
	public void setTitle(String title)
	{
		this.title=title;
	}
	
	public void setMyFile(UploadFile myFile)
	{
		this.myFile=myFile;
	}

	//-----------------------------------------------------
	
	/**
	 * 上传文件
	 * @param context
	 * @return String
	 */
	public String uploadBySign(FaceContext context)
	{
		//输出提交的title参数值
		System.out.println("title="+title);
		/**
		 * 如果在web.xml中配置SimpleFace的DispatcherServlet时,
		 * 有配置允许上传文件的最大字节数或允许上传文件的类型,
		 * 则可以利用文件上传监控器来获取上传文件属性是否已经超出了限定范围, 并作出相应处理。
		 **/
		/*if(context.getUploadWatcher().isExtensionExceeded)  //上传文件类型超出了限定范围
		{
			//处理
		}
		else if(context.getUploadWatcher().isMaxlengthExceeded)  //上传文件尺寸超出了限定范围
		{
			//处理
		}*/

		if(myFile!=null)
		{
			//定义文件保存目录
			File saveDir=new File(context.getServletContext().getRealPath("/")+"Upload/upload_files");
			try {
				myFile.save(saveDir);  //保存上传文件
				System.out.println("上传文件保存在==>"+saveDir.getAbsolutePath()+"\\"+myFile.getFileName());
			} catch (IOException e) {
				e.printStackTrace();
				return "failure";
			}
		}
		else
		{
			return "failure";
		}
		return "success";
	}
}

文件上传这一块是不是很简单?多文件上传可以把接收对象UploadFile定义为数组,在附件中的例子有演示。


四、国际化

 

  1、资源文件(以中、英文为例),假设放在net.sf.demo包下面

 

  (1).Messages_zh_CN.properties

login.success={0} 登录成功!
login.failure=登录失败!
login.signout=登录已注销!

  (2).Messages_en.properties

login.success={0} Login is successed!
login.failure=Login is failured!
login.signout=Login is canceled!

 

  2、配置

  <global>
    <resources baseName="net.sf.demo.Messages"/>
  </global>

 

  3、方法

	public String test(FaceContext context)
	{
		//中文客户端下输出“登录失败!”
		System.out.println(context.getResourceMessages().getValue("login.failure"));
		//中文客户端下输出“张三 登录成功!”
		System.out.println(
			context.getResourceMessages().getValue(
					"login.success",
					new Object[]{"张三"})
		);
		return null;
	}

 

五、使用Freemarker

 

  1、模版文件目录配置

  <global>
    <freemarker directory="/WEB-INF/templates"/>
  </global>

 

  2、result配置

<result name="view2" type="freemarker">/viewNews.ftl</result>

 

  3、方法

	public String freemarkerViewNews(FaceContext context)
	{
		News news=new News();
		Map<String, Object> dataMap=new HashMap<String, Object>();
		dataMap.put("news", news);
		//设置Freemarker模版数据
		context.setFreemarkerDataMap(dataMap);
		return "view2";
	}

 

 

六、结束

 

  SimpleFace能做的基本上就这么多了。在这里要提一下合法值验证的问题,目前我还没有去实现这部份的完整功能,而是仅仅验证提交上来的值是否为后台定义的类型,如果不符合定义则不会继续执行类方法。我通常是使用前台的JS验证框架来做验证的,有使用自己实现的,也有使用第三方的如jsvalidate。如果像Struts那样使用自定义标签或者再加上一个写验证规则的配置文件,这个功能倒是不难实现,但我因为极力避免对页面的侵入和增加使用者的学习成本,所以在想到更好的办法之前,我不想去实现。欢迎各位大佬拍砖,没有批评指正,则不会有进步!

  • SimpleFace-1.0_bin.rar (2.7 MB)
  • 描述: 运行所需JAR包、使用例子工程[Eclipse]、API文档
  • 下载次数: 36
2
0
分享到:
评论
1 楼 youngmaster 2009-09-07  
朋友的框架做的很好,简洁,也有利于扩展。期望更多的精彩。

相关推荐

    springmvc之HelloWord

    在IT行业中,Spring MVC是一个广泛使用的Java Web框架,它提供了模型-视图-控制器(MVC)架构,便于开发高效、可维护的Web应用程序。本教程将指导你如何使用Eclipse IDE和Maven构建工具来创建一个基础的Spring MVC...

    避开10大常见坑:DeepSeekAPI集成中的错误处理与调试指南.pdf

    在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!

    前端分析-2023071100789

    前端分析-2023071100789

    基于kinect的3D人体建模C++完整代码.cpp

    基于kinect的3D人体建模C++完整代码.cpp

    搞机工具箱10.1.0.7z

    搞机工具箱10.1.0.7z

    GRU+informer时间序列预测(Python完整源码和数据)

    GRU+informer时间序列预测(Python完整源码和数据),python代码,pytorch架构,适合各种时间序列直接预测。 适合小白,注释清楚,都能看懂。功能如下: 代码基于数据集划分为训练集测试集。 1.多变量输入,单变量输出/可改多输出 2.多时间步预测,单时间步预测 3.评价指标:R方 RMSE MAE MAPE,对比图 4.数据从excel/csv文件中读取,直接替换即可。 5.结果保存到文本中,可以后续处理。 代码带数据,注释清晰,直接一键运行即可,适合新手小白。

    性价比革命:DeepSeekAPI成本仅为GPT-4的3%的技术揭秘.pdf

    在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!

    基于ANSYS LSDyna的DEM-SPH-FEM耦合模拟滑坡入水动态行为研究,基于ANSYS LSDyna的DEM-SPH-FEM耦合的滑坡入水模拟分析研究,基于ansys lsdyna的滑坡入水

    基于ANSYS LSDyna的DEM-SPH-FEM耦合模拟滑坡入水动态行为研究,基于ANSYS LSDyna的DEM-SPH-FEM耦合的滑坡入水模拟分析研究,基于ansys lsdyna的滑坡入水模拟dem-sph-fem耦合 ,基于ANSYS LSDyna; 滑坡入水模拟; DEM-SPH-FEM 耦合,基于DEM-SPH-FEM耦合的ANSYS LSDyna滑坡入水模拟

    auto_gptq-0.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

    auto_gptq-0.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

    复件 复件 建设工程可行性研究合同[示范文本].doc

    复件 复件 建设工程可行性研究合同[示范文本].doc

    13考试真题最近的t64.txt

    13考试真题最近的t64.txt

    Microsoft Visual C++ 2005 SP1 Redistributable PackageX86

    好用我已经解决报错问题

    嵌入式开发入门:用C语言点亮LED灯的全栈开发指南.pdf

    # 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!

    auto_gptq-0.4.2-cp38-cp38-win_amd64.whl

    auto_gptq-0.4.2-cp38-cp38-win_amd64.whl

    自动立体库设计方案.pptx

    自动立体库设计方案.pptx

    手把手教你用C语言实现贪吃蛇游戏:从算法设计到图形渲染.pdf

    # 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!

    性能对决:DeepSeek-V3与ChatGPTAPI在数学推理场景的基准测试.pdf

    在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!

    从零到一:手把手教你用Python调用DeepSeekAPI的完整指南.pdf

    在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!

    为什么你的switch总出bug?90%新手不知道的break语句隐藏规则.pdf

    # 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!

    用deepseek变现实操流程

    用deepseek变现实操流程,小白必看。

Global site tag (gtag.js) - Google Analytics