随笔-57  评论-117  文章-1  trackbacks-0
 

     我们都知道普通的文件上传是通过表单进行文件上传的,还不能达到异步上传的目的。通过使用某些技术手段,比如jquery form.js可以达到异步上传的目的,但最重要的问题在于,它不能够进行多个文件的上传。如果你要上传多个文件,必须一个一个地上传,同时还要在界面上处理当上传完一个文件之后,下一个文件上传框的问题。
    现在我们有了一个更多的运行,即使用swfupload进行多文件异步上传。顾名思义,它是一个flash的上传工具,但在界面上的表现形式使它和普通的html元素一样,没有复杂的展现,就一个普通的上传框,即可达到想要目的。

    关于swfupload的使用这里自不必多,这里主要介绍的是解决在java web开发过程中经常碰到的验证失败的问题。这是因为flash在上传的时候使用的是和浏览器不同的会话,flash的SWFUpload上传利用socket套接字进行通信,所以导致session和原来上一次的会话不同,导致session丢失。这样就导致服务器在验证时自然被认为是新会话,从而验证不能通过,导致上传不能成功了。
    解决问题的方法,就是让flash在上传文件的时候带上同在一个界面的session标识,这通常是修改其中的upload_url来达到我们的目的,修改如下所示:

upload_url: "/admin/infobuild/image/upload.action;jsessionid=${pageContext.session.id }"

上面这句话,必须放到jsp界面上,因为里面使用到了JavaWeb的语法,当然这可以修改,通过将<%=session.getId()%> 或 ${pageContext.session.id } 放到特殊的js变量中,可以达到隐藏变量的目的。比如如下的代码:
<!-- 这句要房子jsp页面中的script脚本中,或是放在servlet的response.getWriter()流中的script脚本中;总之要在swfupload 的js引入之前执行 -->
window["sessionId"]="${pageContext.session.id}"; 
<!-- 这句话就可以在引入的js中使用 -->
upload_url: Gtip.util.addContextPath("/admin/infobuild/image/upload.action;jsessionId"  + "=" + window["sessionId"]),

以上方案是解决在jsp页面中解决的取值java的变量值;

如上代码的第一句放到jsp文件中,如jsp的公共include文件中。下面一句就放到js文件中,如引入的upload.js文件当中。
    但以上代码还存在一个问题,就是默认的sessionName问题。在tomcat或者其它j2ee容器,默认的sessionName也是 jsessionId。如果我们修改了sessionName如通过tomcat的server.xml修改session_cookie_name,这样默认的sessionName就是我们修改之后的了。解决此问题,需要再加一个参数设置才可,如下所示:

 

<!-- 这三行放在include 导入的那个jsp的页面中 -->
window["contextPath"] = "${pageContext.request.contextPath}";
window["sessionId"] = "${pageContext.session.id}";
window["sessionName"] = "jsessionId";
 
// js中使用jsp中设置的window的变量值
upload_url: addContextPath("/admin/infobuild/image/upload.action;" + window["sessionName"] + "=" + window["sessionId"])

以上代码的前三行放到公共的include.jsp中,最后一行放到公共的upload.js中。这样即可满足最终要求了。
不过有一点不好的即是,在部署环境中时,如果部署环境修改了sessionName,则必须在此include.jsp中修改一个具体的sessionName才可。

转载请标明出处:i flym
本文地址:http://www.iflym.com/index.php/code/201108190001.html

posted @ 2012-05-11 14:14 hoojo 阅读(2946) | 评论 (0)编辑 收藏
     摘要: 开发环境: System:Windows WebBrowser:IE6+、Firefox3+ JavaEE Server:tomcat5.0.2.8、tomcat6 IDE:eclipse、MyEclipse 6.5 开发依赖库: JavaEE5、ext 2.2.2 Email:hoojo_@126.com Blog:http://blog.csdn.net/IBM_hoojo ...  阅读全文
posted @ 2012-03-17 03:09 hoojo 阅读(2066) | 评论 (0)编辑 收藏
     摘要: 支持Form颜色选择组件、日期时间选择组件、带图标的下拉列表、多选下来列表、动态下拉列表树等组件 开发环境: System:Windows WebBrowser:IE6+、Firefox3+ JavaEE Server:tomcat5.0.2.8、tomcat6 IDE:eclipse、MyEclipse 8 开发依赖库: JavaEE5、ext 2.2.2 Email:hoojo_@126.co...  阅读全文
posted @ 2012-02-27 13:56 hoojo 阅读(2891) | 评论 (0)编辑 收藏
     摘要:   上两篇文章:http://www.cnblogs.com/hoojo/archive/2011/06/01/2066426.html http://www.cnblogs.com/hoojo/archive/2011/06/02/2068665.html 介绍到了在MongoDB的控制台完成MongoDB的数据操作、以及通过Java MongoDB 的驱动完成在Java中对Mon...  阅读全文
posted @ 2012-02-17 10:34 hoojo 阅读(2599) | 评论 (1)编辑 收藏

做手机Web开发做浏览器兼容用到了,所以在网上找了些汇总下。

alert($(window).height()); //浏览器当前窗口可视区域高度 
alert($(document).height()); //浏览器当前窗口文档的高度 
alert($(document.body).height());//浏览器当前窗口文档body的高度 
alert($(document.body).outerHeight(true));//浏览器当前窗口文档body的总高度 包括border padding margin 
alert($(window).width()); //浏览器当前窗口可视区域宽度 
alert($(document).width());//浏览器当前窗口文档对象宽度 
alert($(document.body).width());//浏览器当前窗口文档body的高度 
alert($(document.body).outerWidth(true));//浏览器当前窗口文档body的总宽度 包括border padding margin 
 
// 获取页面的高度、宽度
function getPageSize() {
    var xScroll, yScroll;
    if (window.innerHeight && window.scrollMaxY) {
        xScroll = window.innerWidth + window.scrollMaxX;
        yScroll = window.innerHeight + window.scrollMaxY;
    } else {
        if (document.body.scrollHeight > document.body.offsetHeight) { // all but Explorer Mac    
            xScroll = document.body.scrollWidth;
            yScroll = document.body.scrollHeight;
        } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari    
            xScroll = document.body.offsetWidth;
            yScroll = document.body.offsetHeight;
        }
    }
    var windowWidth, windowHeight;
    if (self.innerHeight) { // all except Explorer    
        if (document.documentElement.clientWidth) {
            windowWidth = document.documentElement.clientWidth;
        } else {
            windowWidth = self.innerWidth;
        }
        windowHeight = self.innerHeight;
    } else {
        if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode    
            windowWidth = document.documentElement.clientWidth;
            windowHeight = document.documentElement.clientHeight;
        } else {
            if (document.body) { // other Explorers    
                windowWidth = document.body.clientWidth;
                windowHeight = document.body.clientHeight;
            }
        }
    }       
    // for small pages with total height less then height of the viewport    
    if (yScroll < windowHeight) {
        pageHeight = windowHeight;
    } else {
        pageHeight = yScroll;
    }    
    // for small pages with total width less then width of the viewport    
    if (xScroll < windowWidth) {
        pageWidth = xScroll;
    } else {
        pageWidth = windowWidth;
    }
    arrayPageSize = new Array(pageWidth, pageHeight, windowWidth, windowHeight);
    return arrayPageSize;
}
 
// 滚动条
document.body.scrollTop;
$(document).scrollTop();
posted @ 2012-02-16 17:45 hoojo 阅读(12496) | 评论 (0)编辑 收藏

有问题可以留言、私信、发邮件:
Email:hoojo_@126.com 

Blog:http://blog.csdn.net/IBM_hoojo

http://hoojo.cnblogs.com/

方法一:

1、安装Rational Rose2003时,在需选择安装项的时候,只选择Rational Rose EnterPrise Edition即可,不需选择其他项,之后选择“DeskTop Installation from CD Image“,一路下一步。出现Mem_pointer_Bad错误,点击确定继续;

2、安装finish后将弹出的Rational License Key Administrator向导等窗口关闭。若有连接FLEXlm License Server的出错提示框出现,也关闭它们。

安装会出现 Mem_pointer_Bad 错误,原因应该是某个函数因为安全等级问题而无法运行,只要下载一个SHW32.dll把 ../Rational/Rose/SHW32.dll替换即可。(注:此方法可以避免报错,但是亦可能会造成Rose新建工程报Automation错误,所以此方法基本无效。。。任他报错吧!囧)

下载地址: http://www.oyksoft.com/soft/1880.html

3、安装好Rational Rose Enterprise Editon后,打开rose2003crack.rar压缩包,里面有四个文件,分别为flexlm.cpl、license.dat、lmgrd.exe、rational.exe。

4、用记事本打开license.dat文件,大约在文件的中间位置有:

SERVER MICROSOFT ANY

DAEMON rational "C:\Program Files\Rational\common\rational.exe"

将其修改为:SERVER 计算机名 ANY   DAEMON rational "自己安装的目录\rational.exe"后,保存。

5、将license.dat、 lmgrd.exe 、rational.exe三个文件一起拷贝到:安装目录\rational\common\   下面。

  如:若为默认则为:C:\Program Files\Rational\common\目录。

6、将flexlm.cpl拷贝到C:\Windows\system32目录下。

7、进入控制面板,则在控制面板的上方会增加了一个图标,即FLEXlm License Manager,将其打开,在Setup页中lmgrd.exe右侧目录写为:C:\Program Files\Rational\Common\lmgrd.exe(若为默认安装目录)

License File右侧目录写为:C:\Program Files\Rational\Common\license.dat 点击“应用”。

clip_image001

8、回到Control页,点击Start,若出现"Server Started",则表示已经成功,可以点击Status,若状态为:计算机名:license server UP(MASTER)则成功。

 clip_image002

9、这时可打开安装的Rational Rose Enterprise Edition,若还是出现Error,则打开Rational License Key Administrator ,点击工具栏中的第一个工具(Start WIzard),点击下一步,在Server Name中的名字改为自己的计算机名,port可以不输,能进入下一个管理窗口并且没出错提示,就代表license server配置成功,Rational的产品应该可以运行了。

clip_image003

clip_image004

clip_image005

——————————————————————————————————————————————————

 

更简单方法二:

安装完成后,下载rational_perm.dat覆盖到Common文件夹即可完成破解,简单吧 o(∩_∩)o...哈哈!

###########################################################################

另一版本:

FROM:http://blog.csdn.net/fenglibing/archive/2007/08/17/1747693.aspx

这么好的东西,不拿来出分享,我对不起原作者呀。但是我这里不知道作者是谁,感谢在先了。

http://www.oyksoft.com/soft/1880.html

http://files.cnblogs.com/lixianhuei/rose2003crack.rar

以上两个网址分别是用来下载Rational Rose 2003及其破解软件的。

1、安装Rational Rose2003时,在需选择安装项的时候,只选择Rational Rose EnterPrise Edition即可,不需选择其他项。

2、安装好Rational Rose Enterprise Editon后,打开rose2003crack.rar压缩包,里面有四个文件,分别为flexlm.cpl、license.dat、lmgrd.exe、rational.exe。

3、用记事本或者是EditPlus打开license.dat文件,大约在文件的中间位置有:SERVER Microsoft ANY

DAEMON rational “C:\Program Files\Rational\common\rational.exe”  将其修改为:SERVER 计算机名 ANY DAEMON rational “自己安装的目录\rational.exe”后,保存

注:若是按默认目录安装,则只需修改计算机名即可。

4、将license.dat、 lmgrd.exe 、rational.exe三个文件一起拷贝到:安装目录\rational\common\ 下面。

  如:若为默认则为:C:\Program Files\Rational\common\目录。

5、将flexlm.cpl拷贝到system32目录下。如win2000系统中为C:\WINNT\system32目录。

6、进入控制面板,则在控制面板的上方会增加了一个图标,即FLEXlm License Manager,将其打开,在Setup页中lmgrd.exe右侧目录写为:C:\Program Files\Rational\Common\lmgrd.exe(若为默认安装目录)

License File右侧目录写为:C:\Program Files\Rational\Common\license.dat

7、回到Control页,点击Start,若出现”Server Started”,则表示已经成功,可以点击Status,若状态为:计算机名:license server UP(MASTER)则成功。

8、这时可打开安装的Rational Rose Enterprise Edition,若还是出现Error,则打开Rational License Key Administrator ,点击工具栏中的第一个工具(Start WIzard),点击下一步,在Server Name中的名字改为自己的计算机名即可。因现在的学习需在使用Rational Rose,所以进行了安装,但确实花了不少工夫,所以特把自己安装的经验来跟大家一起分享,希望能对大家有所帮助。

 

该文章为转载文章,原文作者应该是163.com的blog,但找不到作者blog,只能通过图片url找到是163.com的

Email:hoojo_@126.com 

Blog:http://blog.csdn.net/IBM_hoojo

http://hoojo.cnblogs.com/

posted @ 2012-02-14 11:35 hoojo 阅读(135652) | 评论 (24)编辑 收藏
     摘要: 最近在搭建一个项目,需要用到很多通用的工具类,自己也写了几个。现在分享一下,也方便自己以后使用。如果你觉得不错的话,也欢迎转载。blog http://blog.csdn.net/IBM_hoojohttp://hoojo.cnblogs.comhttp://hoojo.blogjava.netemail hoojo_@126.com   文件上传状态枚举类: package com...  阅读全文
posted @ 2012-02-10 14:04 hoojo 阅读(3061) | 评论 (6)编辑 收藏
     摘要: 支持将Image的宽度、高度缩放到指定width、height,并保存在指定目录通过目标对象的大小和标准(指定)大小计算出图片缩小的比例可以设置图片缩放质量,并且可以根据指定的宽高缩放图片 源码: package com.hoo.util; import java.awt.Image;import java.awt.image.BufferedImage;import java.io....  阅读全文
posted @ 2012-02-08 13:48 hoojo 阅读(2542) | 评论 (0)编辑 收藏

Struts 概述

随着MVC 模式的广泛使用,催生了MVC 框架的产生。在所有的MVC 框架中,出现最早,应用最广的就是Struts 框架。

Struts 的起源

Struts 是Apache 软件基金组织Jakarta 项目的一个子项目, Struts 的前身是CraigR. McClanahan 编写的JSP Model2 架构。

Struts 在英文中是"支架、支撑"的意思,这表明了Struts 在Web 应用开发中的巨大作用,采用Struts 可以更好地遵循MVC 模式。此外, Struts 提供了一套完备的规范,以基础类库,可以充分利用JSP/Servlet 的优点,减轻程序员的工作量,具有很强的可扩展性。

Struts优点

提高开发效率,减轻了程序员的工作量,降低了重复代码(降低代码冗余),文件不再臃肿。

可以规范软件开发的行为。ActionForm为我们封装请求数据

增加代码的扩展性、移植性

提高代码的可重用性、可读性,无需多个Servlet多个方法

Action转发页面只须配置跳转资源即可,无效全路径、硬编码。降低代码的耦合性

Struts 架构的工作原理

1. Model 部分

Struts 的Model 部分由ActionForm和JavaBean 组成。其中ActionForm用于封装用户请求参数,所有的用户请求参数由系统自动封装成ActionForm 对象:该对象被ActionServlet转发给Action; 然后Action 根据ActionForm里的请求参数处理用户请求。JavaBean 则封装了底层的业务逻辑,包括数据库访问等。在更复杂的应用中,JavaBean所代表的绝非一个简单的JavaBean,可能是EJB 组件或者其他的业务逻辑组件。该Model 对应图3 .4的Model 部分。

2. View 部分

Struts 的View 部分采用JSP 实现。Struts 提供了丰富的标签库,通过这些标签库可以最大限度地减少脚本的使用。这些自定义的标签库可以实现与Model 的有效交互,并增加了显示功能。对应图的JSP 部分。

整个应用由客户端请求驱动,当客户端请求被ActionServlet 拦截时, ActionServlet根据请求决定是否需要调用Model 处理用户请求,当用户请求处理完成后,其处理结果通过JSP 呈现给用户。

3. Controller部分

Struts 的Controller 由两个部分组成。

·系统核心控制器—拦截用户请求ActionServlet 派发请求

·业务逻辑控制器—处理用户请求的Action,处理业务逻辑

其中,系统核心控制器是一个ActionServlet。该控制器由Struts 框架提供,继承HttpServlet类,因此可以配置成一个标准的Servlet。该控制器负责拦截所有Http请求,然后根据用户请求决定是否需要调用业务逻辑控制器,如果需要调用业务逻辑控制器,则将请求转发给Action 处理,否则直接转向请求的JSP 页面。业务逻辑控制器负责处理用户请求,但业务逻辑控制器本身并不具有处理能力,而是调用Model 来完成处理。业务逻辑控制器对应图3 .4中的Action 部分。

clip_image002

下面结合图3.7 对Struts 的工作流程作详细的讲解。

Web 应用都是请求一响应的程序结构。程序是由客户端Client 发出Http 请求开始的,客户端请求被ActionServlet 拦截。在ActionServlet 处,有两种情况:

·要求逻辑控制器处理的请求:

·简单转发的请求。

对于第一种的请求,ActionServlet 需要调用对应的Action。因此ActionServlet 将请求转发到Action ,如果请求还配置了对应的FormBean,则ActionServlet 还负责用请求参数填充ActionForm,此时如果ActionForm还没有创建。ActionServlet会帮我们创建一个可以用的ActionForm,如果ActionForm已经创建就直接给我们用, ActionForm 的实质就是JavaBean,专门用于封装请求参数。并且在次期间,如果ActionForm如果有验证方法,会去执行验证方法,如果验证通过会进入Action中。验证失败,会跳转到Action配置的input资源页面。

此时的Action 将无须从HTTP Request 中获取请求参数,而是从ActionForm 中获得请求参数。Action 获得请求参数后,调用Model 对象由JavaBean 处理用户请求。Action处理完用户请求之后,将处理结果包装成ActionForward,回送给ActionServlet。

由于ActionForward 对象封装了JSP 资源的映射。因此, ActionServlet 知道调用合适的JSP 资源表现给客户端。

对于第二种请求, HTTP 请求无须Action 处理,只是对普通资源的请求,作为超级链接的替代。因为ActionServlet 直接将该请求转发给JSP 资源,既不会填充ActionForm,也无须调用Action 处理。

JSP 页面在表现之前,还需要调用对应的JavaBean,此处的JavaBean 不再是包含业务逻辑的JavaBean,而是封装了处理结果的普通vo (值对象)。JSP 页面根据vo 的值,可能利用JSTL 或者Struts 的标签库来生成HTTP 响应给客户端。总之JSP 应尽量避免使用Java 脚本。

Action配置

path是我们请求访问的路径,如果用struts标签,会默认加上.do的后缀。ActionServlet拦截到*.do的请求后,就进行相应的业务处理,然后派发到path对应的Action;

name是Action对象的ActionForm,ActionForm是封装请求的信息,如表单

attribute和name一样,可以省略,在省略的情况下用name。都是对应ActionForm

type是Action对象对应的文件路径,含包名

scope是ActionForm的作用域,默认request

parameter后带方法名称,即请求所执行的方法

forward是转发后的资源页面

ActionForward配置

name逻辑名称和Action中的mapping.forward参数对应

path对应映射的JSP页面

redirect是否重定向请求

forward有全局和局部的2种,如果当前Action配置的forward资源在当前配置的Action中没有找到,然后回到全局的forward资源中查找。局部优先全局

ActonForm配置

name是form的名称

type是form的包名+文件名

ActionForm还有动态ActionForm、验证ActionForm

国际化I18N(Internationalization

目的:是适应更多的、更好的用户界面

Java 程序的国际化主要通过如下三个类完成。

   java.util. ResourceBundle: 对应用于加载一个资源包。

   java.util.Locale: 对应一个特定的国家/区域及语言环境。

   java.text.MessageFormat: 用于将消息格式化。

为了实现程序的国际化,必须先提供程序所需要的资源文件。资源文件的内容是和很多key-value 对。其中key 是程序使用的部分,而value 则是程序界面的显示。

资源文件的命名可以有如下三种形式。

   baseName _language_country.properties。

   baseName _language.properties。

   baseNarne.properties 。

其中baseName 是资源文件的基本名,用户可以自由定义。而language 和count可都不可随意变化,必须是Java 所支持的语言和国家。

1.国际化支持的语言和国家

事实上, Java 也不可能支持所有国家和语言,如需要获取Java 所支持的语言和国家,可调用Locale 类的getAvailableLocale 方法来获取。该方法返回一个Locale 数组,该数组里包含了Java 所支持的语言和国家。

2. 编写国际化所需的资源

国际化所需的资源文件内容是key-value 对,下面提供了两个资源文件,这两个资源文件很简单,只包含一个key-value 对。

下面是MyResource.properties 的文件的内容:

资源文件的内容: key-value 对。

msg=Hello , {O} Today is {1}.

下面是MyResource_zh_CN.properties 文件的内容:

资源文件的内容: key-value 对

msg=你好. {O} 今天是{l}。

所有资源文件的key 都是相同的,只是value 会随国家和语言的不同而变化。

3.程序从哪里获取资源呢?

在ResourceBundle 加载资源时按如下顺序搜索。

搜索所有国家和语言都匹配的资源文件,例如,对于简体中文的环境,先搜索如下文件:

MyResource_zh_CN.properties

如果没有找到国家和语言都匹配的资源文件,则再搜索语言匹配的文件,即搜索如下文件:

MyResource_zh.properties

如果上面的文件依然无法搜索到,则搜索baseNarne 匹配的文件,即搜索如下文件:

MyResource.properties

4. 使用类文件代替资源文件

Java 也允许使用类文件代替资源文件,即将所有的key-value对存入class 文件,而不是属性文件。

用来代替资源文件的Java 文件必须满足如下条件。

·类的名字必须为baseNarne_language_country,这与属性文件的命名相似。

·该类必须继承ListResourceBundle,并重写getContents 方法,该方法返回Object数组,该数组的每一个项都是key=value 对。

eg:下面的类文件可以代替上面的属性文件:

public class MyResource_zh_CN extends ListResourceBundle {

    // 定义资源

    private final Object myData[][] = { "msg" , " {0}您好!今天是{l} "};

    //重写方法getContents()

    public Object[] [] getContents() {

        //该方法返回资源的key-value对

        return myData;

    }

}

如果系统同时存在资源文件及类文件,则系统将以类文件为主,而不会调用资源文件。对于简体中文的Locale, ResourceBundle 搜索资源的顺序是:

(1) baseName zh CN.class 。

(2) baseNarne_zh_CN.properties。

(3) baseNarne zh.class 。

(4) baseNarne_zh.properties。

(5) baseNarne.class。

(6) baseNarne.properties。

当系统按上面的顺序搜索资源文件时,如果前面的文件不存在,则会使用下一个:如果一直找不到对应的文件,系统将抛出异常。

struts加载资源文件

资源文件的加载通过struts-config.xml文件来配置,加载资源文件应从Web 应用的WEB-INF/classes路径开始加载。因此,资源文件必须放在WEB-INF/classes路径或该路径的子路径下。如果直接放在WEB-INF/classes 路径下,在配置资源文件时,直接指定资源文件的baseName 即可。但如果放在子路径下,则必须以包的形式配置。

动态ActionForm

Why当一个form表单的属性、字段非常多的情况下,需要我们不断的修改、添加ActionForm中的属性,并提供getter、setter方法。虽然这个类比较简单,但是大量重复的getter、setter方法也是比较繁琐的。这个时候struts的动态ActionForm就派上用场了。使用动态ActionForm 的目的是为了减少代码的书写量,但是相对在配置方面要复杂些。

配置动态ActionForm

所有的动态ActionForm 的实现类都必须是org.apache.struts.action.DynaActionForm类,或者是它的子类。使用动态ActionForm 与前面不同的是:因为系统不清楚动态ActionForm 的属性,所以必须在配置文件中配置对应的属性。可以使用form-property 元素来配置动态ActionForm 的属性。

<!一配置动态ActionForm,动态Aciton 必须使用乌rnaActionForm 一〉

<form-bean name="loginForm" type="org.apache.struts.action.DynaActionForm">

     <!一配置ActionForm的属性: username-->

     <form-property name="username" type="java.lang.String"/>

     <! 配置ActionForm的属性: pass-->

     <form-property name="pass"type="java.lang.String"/>

</form-bean>

 

<!-- 配置Action中的path , type , name 属性>

<action path="/login" type="com.hoo.LoginAction" name="loginForm">

     <!一配置两个局部Forward-->

     <forward name="welcome" path="/WEB-INF/jsp/welcome.jsp"/>

     <forward name="input" path="/login.jsp"/>

</action>

从上面的配置文件可看出,动态ActionForm 的配置必须增加form-property 元素,每个属性必须对应一个form-property元素。

form-property元素包含两个属性。

name: 属性的名字,必须与JSP 页面的表单域的名字相同。

type: 属性的类型。

 

使用动态ActionForm

//必须重写该核心方法,该方法actionForm 将表单的请求参数封装成值对象

public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {

     //将ActionForm强制类型转换为DynaActionForm

     DynaActionForm loginForm = (DynaActionForm)form;

     //从ActionForm中解析出请求参数: username

     String username = (String)loginForm.get("username");

     //从ActionForm中解析出请求参数: password

     String pass = (String)loginForm.get("pass");

     //后面的处理与前一个示例的Action 相同。

     …………

}

使用动态ActionForm 时,请求参数必须使用DynaActionForm的getter 方法获取。

DynaActionForm 的getter 方法主要有如下三个。

Object get(java.lang.String name): 根据属性名返回对应的值。

Object get(java.lang.String name, int index): 对于有多个重名表单域的情况, Struts将其当成数组处理,此处根据表面域名和索引获取对应值。

Object get(java.lang.String name, java.lang.String key): 对于使用Map 属性的情况,根据属性名及对应key. 获取对应的值。

 

Struts 的标签库

Struts 提供了大量的标签库,用于完成表现层的输出。借助于Struts 的标签库,可避免在JSP 中嵌入大量的Java 脚本,从而提高代码的可读性。

Struts 主要提供了如下三个标签库。

A、 html: 用于生成HTML 的基本标签。

B、 bean: 用于完成程序国际化,输出Struts 的ActionForm 的属性值等。

C、 logic: 用于完成循环、选择等流程控制。

 

使用html 标签库

Struts 为htrnl 的大部分标签提供了对应的htrnl 标签, htrnl 所支持的标签大致有如下。

* base: 表现成一个HTML 的<base>标签。

* button: 表现成一个按钮,该按钮默认没有任何动作。

* cancel: 表现成一个取消按钮。

* checkbox: 表现成一个Checkbox 的输入框。

* error: 用于输出数据校验的出错提示。

* file: 表现成一个文件浏览输入框。

* form: 表现成一个form 域。

* frame: 表现成一个HTML<frame>标签。

* hidde: 表现成一个隐藏域。

* htrnl: 表现成HTML 的<htrnl>标签。

* image: 表现成表单域的image 域。

* img: 表现成一个HTML 的img 标签。

* javascrit: 表现成JavaScript 的校验代码,这些校验代码根据ValidatorPlugIn 生成。

* link: 表现成HTML 的超级链接。

* messages: 用于输出Struts 的各种提示信息,包括校验提示。

* multibox: 表现成一个Checkbox 输入框。

* option: 表现成选择框的一个选项。

* password: 表现成一个密码输入框。

* radio: 表现成一个单选输入框。

* reset: 表现成一个重设按钮。

* rewrite: 表现成一个URL 。

* select: 表现成一个列表选择框。

* submit: 表现成一个提交按钮。

* text: 表现成一个单行文本输入框。

* textarea: 表现成一个多行文本框。

 

使用bean 标签库

bean 标签库主要用于输出属性值、提示消息及定义请求参数等。下面是bean 标签库的常用标签。

* cookie: 将请求的cookie 的值定义成脚本可以访问的JavaBean 实例。

* define: 将某个bean 的属性值定义成脚本可以访问的变量。

* header: 将请求头的值定义成脚本可以访问的变量。

* include: 将某个JSP 资源完整定义成一个bean 实例。

* message: 用于输出国际化信息。

* page: 将page Context 中的特定项定义成一个bean 。

* parameter: 将请求参数定义成脚本可以访问的变量。

* resource: 加载Web 应用的资源,并将其变成JavaB eano

* struts: 用于将某个Struts 的内部配置成一个bean 。

* write: 用于输出某个bean 的属性值。

 

使用logic 标签库

logic 标签库是使用最频繁,相对复杂的标签库。logic 标签库主要用于完成基本的流程控制,比如循环及选择等。

logic 标签库主要有如下标签。

* empty: 如果给定的变量为空或者为空字符串,则就计算并输出标签体的内容。

* equal: 如果给定变量与特定的值相等,则会计算并输出该标签体的内容。

* forward: 将某个页面的控制权forward 确定的ActionForward 项。

* greaterEqual: 如果给定变量大于或等于特定的值,则会计算并输出标签体的内容。

* greaterThan: 如果给定变量大于特定的值,则会计算井输出标签体的内容。

* iterate: 通过遍历给定集合的元素,对标签体的内容进行循环。

* lessEqual: 如果给定变量小于或等于特定的值,则会计算并输出标签体的内容。

* lessThan: 如果给定变量小于特定的值,则会计算并输出标签体的内容。

* match: 如果特定字符串是给定消息合适的子字符串,则会计算并输出标签体的内容。

* messagesNotPresent: 如果请求中不包含特定的消息内容,将计算并输出标签体的内容。

* messagesPresent: 如果请求中包含特定的消息内容,则计算并输出标签体的内容。

* notEmpty: 如果给定的变量既不为空,也不是空字符串,则计算并输出标签体的内容。

* notEqual: 如果给定变量不等于特定的值,则会计算并输出标签体的内容。

* notMatch: 如果特定宇符串不是给定消息合适的子字符串,则会计算并输出标签体的内容。

* notPresent: 如果特定的值没有出现在请求中,则计算并输出标签体的内容。

* present: 如果特定的值出现在请求中,则计算并输出标签体的内容。

* redirect: 重定向页面。

 

Struts 的数据校验

数据校验也称为输入校验,指导对用户的输入进行基本过滤,包括必填宇段,宇段必须为数字及两次输入的密码必须相匹配等。这些是每个MVC 框架都应该完成的任务,Struts 提供了基本的数据校验,如果结合commons-validator, Struts 则拥有强大的校验框架,包括进行客户端的JavaScript 校验等。

Struts 的数据校验大致有如下几种方式:

ActionForm 的代码校验。

Action 里的代码校验。

结合commons-validator.jar 的校验。

 

ActionForm 的代码校验

ActionForm 的代码校验是最基本的校验方式。这种校验方式是重写ActionForm 的validate 方法,在该方法内对所有的宇段进行基本校验。如果出现不符合要求的输出,则将出错提示封装在ActionError 对象里,最后将多个ActionError 组合成ActionErrors 对象,该对象里封装了全部的出错提示。并将错误信息用<html:error/>展现在配置的input的失败页面上。

 

Action 的代码校验

在Action 里通过代码完成输入校验,是最基本,也最容易使用的方法。与最初的MVC 设计相似,在调用业务逻辑组件之前,先对数据进行基本校验。这是最传统也是最原始的方法。

这种校验方式非常容易理解,所有的代码都需要程序员自己控制,相当灵活。

但有如下几个不方便之处。

·用户需要书写大量的校验代码,使程序变得烦琐。

· 数据校验应该在填充ActionForm里完成,最好能在客户端完成校验,而不是推迟到Action 里才完成数据校验。

注意:在实际的使用中,这种校验方式不仅程序开发复杂,且性能也不高。

 

结合commons-validator.jar 的校验

借助于commons-validator.jar 的支持, Struts的校验功能非常强大,几乎不需书写任何代码。不仅可以完成服务器端校验,同时还可完成客户端校验,即弹出Javascript 提示。

使用commons-validator.jar 校验框架时,有如下几个通用配置。

·增加校验资源。

·利用ValidatorPlugIn 加载校验资源。

·ActionForm 使用ValidatorForm 的于类。

下面分别通过三个示例讲解这三种校验:基本的校验、对动态ActionForm 执行校验及弹出JavaScript 校验提示。

 

1. 继承ValidatorForm 的校验

如果需要使用commons-validator 框架,请按如下步骤进行。

(1) Struts 的ActionForm必须是ValidatorForm的子类,提供验证属性字段的getter、setter方法

(2) 编写表单域时必须满足校验规则。校验规则都由规则文件控制,规则文件有以下两个。

* validator-rules.xml 文件

* validation.xml 文件

第一个文件可在Struts 的解压缩后的文件夹的lib 下找到,将该文件复制到WEB-INF

2. common-validator支持的校验规则

common-validator支持的校验规则非常丰富,特别是mask 和validwhen 两个规则,

极大地丰富了该校验框架的功能。

常用的校验规则有如下几种。

* required: 必填。

* va1idwhen: 必须满足某个有效条件。

* minlength: 输入必须大于最小长度。

* maxlength: 输入必须小于最大长度。

* mask: 输入匹配正确的表达式。

* byte: 输入只能是一个byte 类型变量。

* short: 输入只能是一个short 类型变量。

* integer: 输入只能是一个integer 变量。

* long: 输入只能是一个long 变量。

* float: 输入只能是一个float 变量。

* double: 输入只能是一个double 变量。

* date: 输入必须是一个日期。

* intRange: 输入的数字必须在整数范围内。

* floatRange: 输入的数字必须在单精度浮点数范围内。

* doubleRange: 输入的数字必须在双精度浮点数范围内。

* email: 输入必须是有效的E-mail 地址。

* uri: 输入必须是有效的uri 地址。

3.使用DynaValidatorForm 的校验

即使不书写ActionForm,也可以利用cornmon-validator 校验框架。此时使用的ActionForm 的实现类,必须既是动态Form ,也是验证Form,DynaValidatorForm 就是满足这两个条件的Form。

4. 弹出客户端JavaScript提示

如需要弹出客户端JavaScript 校验非常简单,无须修改其他配置文件,只需修改登录使用的JSP 页面的两个地方。

(1) 为form 元素增加onsubmit="return validateXxxForm(this);"属性,其中的XxxForm就是需要校验的form 名,与struts-config.xrnl中配置的form-bean 的name 属性一致,也与validation.xrnl文件中需要校验的form 的name 属性一致。

(2) 增加<html:javascript formName="xxxForm"/> ,其中xxxForm 是需要校验的form 名。

注意:即使使用了客户端技验规则,也不要删除页面的htm1 :rnessages 标签。因为该标签会在客户端技验通过,而在服务器端技验并未通过时弹出提示。

 

Struts 的异常框架

Struts 1.1 版本中加入了对异常的处理,称之为Exception Handling,标志着作为一个整体的框架, Struts 越来越趋于成熟。

在以前的Struts 开发过程中,对于异常的处理,主要是采用手动处理的方式:如通过try/catch 等捕获异常:然后将定制个性化的,比较详细的错误信息放进ActionMessage中:最后在返回页面中把这些错误信息反馈给用户。

对于异常的原始信息,不管是最终用户还是开发员都不希望看到。

借助于Struts 的异常框架,异常处理只需通过struts-config.xm1文件定义即可。根据异常定义的位置不同,异常可分为局部异常和全局异常两种。

·局部异常作为action 的子元素中定义。

·全局异常在globa1-excetpions 元素中定义。

异常定义的格式如下:

<exception key="keyNarne" type="ExceptionNarne" scope="scope" path="uri"/>: 当Struts 出现ExceptionNarne 的异常时,页面自动转向uri 指向的资源,并在该页面输出keyName 对应的国际化中的出错提示。

几种常用的Action

除了基本的Action 之外, Struts 还提供了几个其他类型的Action ,这些Action 大大丰富了Struts 的功能。下面介绍如下儿个常用的Action 。

* DispatchAction: 能同时完成多个Action 功能的Action 。

* ForwardActon: 该类用来整合Struts 和其他业务逻辑组件,通常只对请求作有效性检查。

* IncludeAction: 用于引入其他的资源和页面。

* LookupDispatchAction: DispatchAction 的子类,根据按钮的key ,控制转发给action的方法。

* MappingDispatchAction: DispatchAction 的子类,一个action 可映射出多个Action地址。

* SwitchAction: 用于从一个模块转换至另一个模块,如果应用分成多个模块时,就可以使用SwitchAction 完成模块之间的切换。

 

DispatchAction

在该action 的配置中,增加了parameter属性,该属性用于指定参数名,即Struts 将根据该参数的值调用对应的方法。为了让请求增加method 的参数,method参数对应的是要请求执行的方法。

<action path="/login" type="com.hoo.LoginAction" name="loginForm" scope="request" validate="true" input="login.jsp" parameter="method">

     <forward name="success" path="/welcome.jsp"/>

</action>

Login.do?method=login

 

MappingDispatchAction

可将同一个Action 的不同方法映射成多个Action URI ,这种Action 的写法与DispatchAction 非常相似,同样不需要重写execute 方法,而是将书写多个自定义的方法。这些方法除了方法名与execute 方法不同外,其他的参数列表及异常处理完全一样。

<!-- 配置第一个Action. 实现类是com.hoo.LoginAction , parameter 为add-->

<action path="/add" type="com.hoo.LoginAction" name="loginForm" scope="request" validate="true" input="login.jsp" parameter="add">

     <forward name="success" path="/welcome.jsp"/>

</action>

<! 配置第二个Action. 实现类是com.hoo.LoginAction , parameter 为modify-->

<action path="/modify" type="com.hoo.LoginAction" name="loginForm" scope="request" validate="true" input="login.jsp" parameter="modify">

     <forward name="success" path="/welcome.jsp"/>

</action>

其中,path对应的是请求的地址uri,而parameter是对于当前请求所执行的方法;

注意:使用MappingDispatchAction 并没有带来太大的优势,系统完全可以书写两个Action,分别定义两个不同的action 映射,而其他部分没有区别。

LookupDispatchAction

LookupDispatchAction也是DispatchAction 的一种,但它的处理更加简单。该Action也可包含多个处理方法,它可让处理方法与按钮直接关联,无须使用任何的JavaScript脚本。因此可通过重写getKeyMethodMap方法完成按钮与Action 中方法的关联。

//用于关联按钮和方法

protected Map getKeyMethodMap() {

     Map map = new HashMap();

     //如果按钮标题的key 为button.add. 则提交该按钮时对应add 方法

     map .put ("button. add" , "add");

     //如果按钮标题的key 为button.modify. 则提交该按钮时对应modify 方法

     map.put ("button.modify" , "modify") ;

     return map;

}

 

ForwardAction

如果需要从一个页面或资源转换到另一个资源时,直接使用页面或资源路径的超级链接定位并不是好的做法,这使得控制器没有机会处理相关的请求事直。

使用ForwardAction可以完成请求的转发,当控制器调用ForwardAction的perform()方法时,它会使用属性parameter 所设定的路径进行forward 的动作。下面是一个设定ForwardAction的例子:

<actlon-mapplngs>

     <action path="/welcome" type="org.apache.struts.actions.ForwardAction" parameter="/welcome.jsp"/>

</action-mappings>

该action 仅仅完成转发,并没有执行其他的额外动作。页面控制转发的代码如下:

<a href="welcome.do">转入</a>

当单击转入超级链接时,将可以转向ForwardAction中parameter指向的资源。

 

IncludeAction

IncludeAction的用法与ForwardAction的用法比较相似,区别在于ForwardAction将跳转到action 定义的资源,而IncludeAction用于引入该action 对应的资源。

下面是IncludeAction定义的源代码:

<action-mapplngs>

     <action path="/welcome" type="org.apache. struts.actions.IncludeAction" parameter="/welcome.jsp"/>

</action-mappings>

该action 用于经welcome.jsp 作为资源导入。

页面中负责加载该action 所导入资源的代码如下:

<jsp:include page="welcome.do"/><br>

上面的代码将会把welcome action 定义的资源导入该页面。

 

SwitchAction

SwitchAction 主要用于模块之间的切换。当一个应用之中存在多个模块时,使用SwitchAction在不同模块之间的action 之间切换还是相当方便的。

 

Struts 的常见扩展方法

Struts 的强大吸引力还来自于它的可扩展性,其扩展性通常有如下三种方式。

·实现PlugIn: 如果需要在应用启动或关闭时完成某些操作,可以创建自己的PlugIn类。

·继承RequestProcessor: 如果想在请求被处理中的某个时刻做一些业务逻辑时,可以考虑实现自己的RequestProcessor 类。

·继承ActionServlet: 如果需要在每次开始处理请求之前,或者处理请求结束之后完成某些操作,可以实现自己的ActionServlet 来完成扩展。

 

下面分别从三个方面来介绍Struts 的扩展。

实现PlugIn 接口

Struts 已经演示了PlugIn 的扩展方法:与common- validation 的整合。后面还将介绍Spring 与Struts 的整合,也利用了PlugIn 的扩展。

在下面的应用中,系统使用Hibernate 作为持久层,在启动时创建SessionFactory 实例,并将该SessionFactory 存入application ,在应用关闭时销毁SessionFactory 。只需如下两步即可完成此功能。

(1) 实现自己的PlugIn 类。

     实现PlugIn 接口必须实现如下两个方法。

     1 void destroy()。

     2 void init(ActionServlet serlet, ModuleConfig config) 。

     应用启动时调用init 方法,而应用关闭时则调用destroy 方法。

     下面是SessionFactoryLoaderPlugIn 的实现类:

     public class SessionFactoryLoaderPlugin implements PlugIn {

          //Hibernate 的配置文件

          private String configFile;

          //应用关闭时,销毁资源

          public void destroy()

               System.out.println("系统销毁SessionFactory");

          }

          //应用启动时,完成SessionFactory 的初始化

          public void init(ActionServlet actionServlet , ModuleConfig config) throws ServletException

               System.out.println("系统以" + getConfigFile() + "为配置文件初始化SessionFactory") ;

              //获取Plugln 配置文件的方法

               public String getConfigFile() {

                    return configFile;

               }

          // 负责加载Plugln 配置属性的方法

          public void setConfigFile(String configFile) {

                this.configFile = configFile;

          }

     }

在上面的PlugIn 中,并没有真正初始化SessionFactory ,仅在控制台打印出字符串来标识创建动作。另外,还提供了configFile 属性的setter 和getter 方法,这两个方法负责访问plugin 元素的configFile 属性。

 

( 2 ) 将SessionFactoryLoaderPlugIn 配置在struts-config.xml 文件中。方法与ValidatorPlugIn 的配置并没有区别,下面是配置SessionFactoryLoaderPlugIn 的代码:

<plug-in className="hoo.SessionFactoryLoaderPluging">

     <set-property property="conf工gFile" value=" WEB-INF/hibernate.cfg.xml"I>

</plug-in>

在配置SessionFactoryLoaderPlugIn 时,配置了configFile 属性,该属性用于确定Hibernate 配置文件的文件名。

 

继承RequestProcessor

RequestProcessor 是Struts 的核心类,而Struts 的核心控制器是ActionServlet 。但ActionServlet 并未完成真正的处理,只是调用RequestProcessor , RequestProcessor 才是Struts 的核心类。

扩展RequestProcessor 的实例在Spring 中有个示范, Spring 提供的Delegating RequestProcessor 是一个很好的示例。下面示例对RequestProcessor 进行简单的扩展。

RequestProcessor 包含了如下常见的方法。

* ActionForm processActionForm: RequestProcessor填充ActionForm 时执行该方法。

* Action processActionCreate: RequestProcessor 调用Action 时调用该方法。

* boolean processPreprocess: 预处理用户请求时执行该方法。

* boolean processValidate: 处理输入校验时调用该方法。

扩展RequestProcessor 只需两步即可。

(2)在struts-config.xml 文件中配置MyRequestProcessor。用户重写了RequestProcessor,但Struts 并不知道,必须在struts-config且nl 中配置才可以。

下面是配置MyRequestProcessor 的代码:

<controller processorClass="lee.MyRequestProcessor" />

该属性的配置应该放在action-mappings元素之后。

注意:重写RequestProccessor的方法时,别忘了使用super 来调用父类的动作。如果没有调用该方法,意味着开发者必须完成Struts 框架所完成的动作。这是不应该的,因为程序员只是在框架中加入额外的处理,并不是要替代Struts。

 

继承ActionServlet

如果需要在开始处理请求,或者处理结束之后加入自己的处理时,可对ActionServlet进行扩展。例如解决中文的编码问题。

ActionServlet 接收处理请求参数时,并不是按GBK 的解码方式处理请求,因此容易形成乱码。为了解决该问题,可以强制指定ActionServlet 使用GBK 的解码方式。

继承ActionServlet重写process方法,设置request、response编码为gbk,然后配置在web.xml中。

posted @ 2012-01-29 16:48 hoojo 阅读(1918) | 评论 (4)编辑 收藏

Servlet 是一种比JSP 更早的动态网页编程技术。在没有JSP 之前, Servlet 也是同时充当视图层、业务逻辑层及持久层角色。

Servlet 的开发效率非常低,特别是当使用Servlet 生成表现层页面时,页面中所有的HTML 标签,都需采用Servlet 的输出流来输出,因此极其烦琐。由于Servlet 是个标准的Java 类,因此必须由程序员开发,其修改难度大,美工人员根本无法参与Servlet 页面的开发。这一系列的问题,都阻碍了Servlet 作为表现层的使用。

自MVC 规范出现后, Servlet 的责任开始明确下来,仅仅作为控制器使用,不再需要生成页面标签,也不再作为视图层角色使用。

 

Servlet ,通常称为服务器端小程序,是运行在服务器端的程序,用于处理及响应客户端请求。

Servlet 是个特殊的Java 类,这个Java 类必须继承HttpServlet 。每个Servlet 可以响应户端的请求。Servlet 提供不同的方法用于响应客户端请求。

doGet: 用于响应客户端的get 请求。

doPost: 用于响应客户端的post 请求。

doPut: 用于响应客户端的put 请求。

doDelete: 用于响应客户端的delete 请求。

事实上,客户端的请求通常只有get 和post 两种; Servlet 为了响应这两种请求,必须重写doGet 和doPost 两个方法。如果Servlet 为了响应四个方法,则需要同时重写上面的四个方法。

 

大部分时候, Servlet 对于所有请求的响应都是完全一样的。此时,可以采用重写一个方法来代替上面的几个方法, Servlet 只需重写service 方法即可响应客户端的所有请求。另外, HttpServlet 还包含两个方法。

init(ServletConfig config): 创建Servlet 实例时,调用的初始化方法。

destroy: 销毁Servlet 实例时,自动调用的资源回收方法。

通常无须重写init和destroy两个方法,除非需要在初始化Servlet 时,完成某些资源初始化的方法,才考虑重写init 方法。如果需要在销毁Servlet 之前,先完成某些资源的回收,比如关闭数据库连接等,才需要重写destroy 方法。

注意:如果重写了init(ServletConfig config)方法,则应在重写该方法的第一行调用super.init(config) 。该方法将调用HttpServlet 的init 方法。

 

Servlet 和JSP 的区别在于:

Servlet 中没有内置对象,原来JSP 中的内置对象都必须通过HttpServletRequest对象,或由HttpServletResponse 对象生成:

对于静态的HTML 标签, Servlet 都必须使用页面输出流逐行输出。

这也正是笔者在前面介绍的: JSP 是Servlet 的一种简化,使用JSP 只需要完成程序员需要输出到客户端的内容,至于JSP 中的Java 脚本如何镶嵌到一个类中,由JSP 容器完成。而Servlet 则是个完整的Java 类,这个类的service 方法用于生成对客户端的响应。

 

Servlet 的配置

编辑好的Servlet 源文件并不能响应用户请求,还必须将其编译成class 文件。将编译后的HelloServlet. class 文件放在WEB-INF/classes 路径下,如果Servlet 有包,则还应该将class 文件放在对应的包路径下。

为了让Servlet 能响应用户请求,还必须将Servlet 配置在Web 应用中。配置Servlet时,需要修改web.xrnl 文件。

配置Servlet 需要配置两个部分。<servlet>/<servlet-mapping>

 

Servlet的生命周期

Servlet 在容器中运行,其实例的创建及销毁等都不是由程序员决定的,而是由容器进行控制。

Servlet 的创建有两个选择。

客户端请求对应的Servlet 时,创建Servlet 实例:大部分的Servlet 都是这种Servlet。 Web 应用启动时,立即创建Servlet 实例:即load-on-startup Servlet。

每个Servlet 的运行都遵循如下生命周期。

(1)创建Servlet 实例。

(2) Web 容器调用Servlet 的init 方法,对Servlet 进行初始化。

(3) Servlet 初始化后,将一直存在于容器中,用于响应客户端请求。如果客户端有get 请求,容器调用Servlet 的doGet 方法处理并响应请求。对于不同的请求,有不同的处理方法,或者统一使用service 方法处理来响应用户请求。

(4) Web 容器角色销毁Servlet 时,调用Servlet 的destroy 方法,通常在关闭Web容器之时销毁Servlet。

 

使用Servlet创作为控制器

正如前面见到,使用Servlet 作为表现层的工作量太大,所有的HTML 标签都需要使用页面输出流生成。因此,使用Servlet 作为表现层有如下三个劣势。

开发效率低,所有的HTML 标签都需使用页面输出流完成。

不利于团队协作开发,美工人员无法参与Servlet 界面的开发。

程序可维护性差,即使修改一个按钮的标题,都必须重新编辑Java 代码,并重新编译。

 

整个结构非常清晰,下面是MVC 中各个角色的对应组件。

M: Model,即模型,对应JavaBean 。

V: View ,即视图,对应JSP 页面。

C: Controller,即控制器,对应Servlet。

 

load-on-startup Servlet

Servlet 的实例化有两个时机:用户请求之时,或应用启动之时。应用启动时就启动的Servlet 通常是用于某些后台服务的Servlet ,或者拦截很多请求的Servlet; 这种Servlet 通常作为应用的基础Servlet 使用,提供重要的后台服务。如果需要Web 应用启动时,可使用load-on-startup 元素完成Servlet 的初始化。load-on-startup 元素只接收一个整型值,这个整型值越小, Servlet 就越优先初始化。

访问Servlet 的配置参数

配置Servlet 时,还可以增加附加的配置参数。通过使用配置参数,可以实现更好地解耦,避免将所有的参数以硬编码方式写在程序中。

访问Servlet 配置参数要通过ServletConfig 类的实例完成, ServletConfig提供如下方法。

java.lang.String getInitParameter(java.lang.String name): 用于获取初始化参数。

注意: JSP 的内直对象config 就是此处的ServletConfig

自定义标签类

使用标签类,可以使用简单的标签来封装复杂的功能,从而使团队更好地协作开发(能让美工人员更好地参与JSP 页面的开发)。

自定义标签类都必须继承一个父类: java.Servlet.jsp.tagext.TagSupport 。除此之外,自定义标签类还有如下要求。

·如果标签类包含属性,每个属性都有对应的getter 和setter 方法。

·重写doStartTag或doEndTag方法,这两个方法生成页面内容。

·如果需要在销毁标签之前完成资源回收,则重写re1ease方法。

TLD 文件

TLD 是Tag Library Definition 的缩写,即标签库定义,文件的后缀是tld ,每个TLD文件对应一个标签库,一个标签库中可包含多个标签。TLD 文件也称为标签库定义文件。标签库定义文件的根元素是taglib,它可以有多个tag 子元素,每个tag 子元素都对应一个标签。

编辑了标签库定义文件还不够, Web 容器还无法加载标签库定义文件。还必须在web.xml 文件中增加标签库的定义。在web.xml 文件中定义标签库时使用taglib 元素,该元素包含两个子元素: taglib-uri和taglib-location,前者确定标签库的URI; 后者确定标签库定义文件的位置。

使用标签库

使用标签库分成以下两步。

(1) 导入标签库:使用taglib 编译指令导入标签。

(2) 使用标签:在JSP 页面中使用自定义标签。

taglib 的语法格式如下:

〈%@ taglib uri="tagliburi" prefix="tagPrefix" %〉

其中uri 属性确定标签库定义文件的URI,这个URI 就是在web.xml 文件中为标签

库定义的URI。而prefix 属性确定的是标签前缀,即在JSP 页面中使用标签时,该标签

库负责处理的标签前缀。

使用标签的语法格式如下:

<tagPrefix : tagName tagAttribute=ntagValue n ...>

<tagBody/>

</tagPrefix>

如果该标签没有标签体,则可以使用如下语法格式:

<tagPrefix : tagName tagAttribute=ntagValue n …/>

带标签体的标签

带标签体的标签,就是允许在标签内嵌套标签,通常可用于完成一些逻辑运算例如判断和循环等。

带标签体的标签需要继承BodyTagSupport,该类包含一个bodyContent 属性,该属性代表标签体。

BodyTagSupport 还包含两个方法。

doAfterBody: 每次处理完标签体后调用该方法。

void doInitBody: 开始调用标签体时调用该方法。

如果有必要,可以重写这两个方法。

在处理标签类的各个方法中,不同的返回值对应不同的含义,常用的返回值有如下几个。

SKIP_BODY: 不处理标签体,直接调用doEndTag方法。

SKIP_PAGE: 忽略标签后面的JSP 页面。

EVAL_PAGE: 处理标签结束,直接处理页面内容。

EVAL_BODY_BUFFERED: 处理标签体。

EVAL_BODY_INCLUDE: 处理标签体,但忽略setBodyContent和doInitBody方法。

EVAL_BODY_AGAIN: 对标签体循环处理。

 

Filter

Filter 并不是一个标准的Servlet ,它不能处理用户请求,也不能对客户端生成响应。主要用于对HttpServletRequest 进行预处理,也可以对HttpServletResponse 进行后处理,是个典型的处理链。

Filter 有如下几个用处。

·在HttpServletRequest 到达Servlet 之前,拦截客户的HttpServletRequest 。

·根据需要检查HttpServletRequest ,也可以修改HttpServletRequest 头和数据。

·在HttpServletResponse 到达客户端之前,拦截HttpServletResponse 。

·根据需要检查HttpServletResponse ,也可以修改HttpServletResponse 头和数据。

Filter 有如下几个种类。

·用户授权的Filter: Filter 负责检查用户请求,根据请求过滤用户非法请求。

·日志Filter: 详细记录某些特殊的用户请求。

·负责解码的Filter: 包括对非标准编码的请求解码。

.能改变XML 内容的XSLTFilter 等。

一个Filter 可负责拦截多个请求或响应:一个请求或响应也可被多个请求拦截。

创建一个Filter 只需两个步骤:

(1)创建Filter 处理类:

(2) 在web.xml 文件中配置Filter。

创建Filter 类

创建Filter 必须实现javax.servle t. Filter 接口,在该接口中定义了三个方法。

void init(FilterConfig config): 用于完成Filter 的初始化。

void destroy: 用于Filter 销毁前,完成某些资源的回收。

void doFilter(ServletRequest request, ServletResponse response,FilterChain chain): 实现过滤功能,该方法就是对每个请求及响应增加的额外处理。

执行chain.doFilter(request,reponse)方法,当Filter 对请求过滤后,依然将请求发送到目的地址。如果检查权限,可以在Filter 中根据用户请求的HttpSession,判断用户权限是否足够。

如果权限不够,则调用重定向即可,无须调用chain.doFilter(request,reponse)方法。

配置Filter

Filter 的配置和Servlet 的配置非常相似,都需要配置两个部分:

·配置Filter 名。

·配置Filter 拦截URL 模式。

区别在于, Servlet 通常只配置一个URL ,而Filter 可以同时拦截多个请求的URL。

因此,可以配置多个Filter 拦截模式。

 

Listener

Listener 的作用非常类似于load-on-startup Servlet。用于在Web 应用启动时,启动某些后台程序,这些后台程序负责为系统运行提供支持。

Listener 与load-on-startup Servlet 的区别在于: Listener 的启动时机比load-on-startup Servlet 早,只是Listener 是Servlet 2.3 规范之后才出现的。

使用Listener 只需要两个步骤:

(1) 创建Listener 实现类。

(2) 在web.xml 文件中配置Listener。

创建Listener 类

创建Li stener 类必须实现ServletContex tListener 接口,该接口包含两个方法。

eontextInitialized(ServletContextEvent see): 启动Web 应用时,系统调用该Filter的方法。

eontextDestroyed(ServletContextEvent see): 关闭Web 应用时候,系统调用Filter

的方法。

配置Listener

正如load-an-startup Servlet 一样, Listener 用于启动Web 应用的后台服务程序,但不负责处理及响应用户请求,因此无须配置URL。

若将Listener 配置在Web 容器中(如果Web 容器支持Listener),则Listener 将随Web 应用的启动而启动。

配置Listener 时使用<listener/>元素,下面是配置Listener 的片段:

<!-- 配置Listener-->

<listener>

<!- 指定Listener 的实现类→

<listener-class>lee.ScheduleListener</listener-class>

</listener>

在上面的配置中,既无须配置Listener 的名字,也无须配置Listener 的URL 只需配置它的实现类即可。此时容器将自动检测部署在容器中的Listener,并在应用启动时,自动加载所有的Listener。

posted @ 2012-01-29 15:50 hoojo 阅读(2175) | 评论 (5)编辑 收藏
     摘要: UML的组成

UML由视图(View)、图(Diagram)、模型元素(Model Element)和通用机制(General Mechanism)等几个部分组成。

a) 视图(View): 是表达系统的某一方面的特征的UML建模元素的子集,由多个图构成,是在某一个抽象层上,对系统的抽象表示。

b) 图(Diagram): 是模型元素集的图形表示,通常是由弧(关系)和顶点(其他模型元素)相互连接构成的。

c) 模型元素(Model Element):代表面向对象中的类、对象、消息和关系等概念,是构成图的最基本的常用概念。

d) 通用机制(General Mechanism):用于表示其他信息,比如注释、模型元素的语义等。另外,UML还提供扩展机制,使UML语言能够适应一个特殊的方法(或过程),或扩充至一个组织或用户。

  阅读全文
posted @ 2012-01-29 14:49 hoojo 阅读(1657) | 评论 (1)编辑 收藏
     摘要: 对jQuery blockUI插件进行了小的封装扩展,支持confirm、alert、dialog弹出窗口提示信息,支持按钮回调事件。可以自定义css样式、覆盖blockUI的样式等 首先要到jquery blockUI 官方网址:http://malsup.com/jquery/block/ 下载jquery.blockUI JS lib:http://malsup.com/jquery/blo...  阅读全文
posted @ 2012-01-09 14:19 hoojo 阅读(3263) | 评论 (3)编辑 收藏
select * from account where userName like 'ad%';
select * from account where userName >= 'ad' and userName < 'ae';

/*
这两种查询的结果是一样的,效率好像也差不多,没有做具体的效率测试,有兴趣可以测试下效率。
like查询中的ad%是查询ad开头userName的数据,
而userName >= 'ad'就是查询ad开头的数据并且还包含 ae、af、ag……,也就是说是查询“ad”中包含d且大于“ad”中d的数据
所以,and userName < 'ad'就保证查询的区间在“ad”中的,而ae、af、ag……这些数据就不会出现在结果集中。
当然你可以试试:
select * from account where userName >= 'ad' and userName < 'az';
结果集是不是包含:ae、af、ag……ak、al……ay、az等开头的数据。
*/
posted @ 2011-10-27 15:58 hoojo 阅读(2396) | 评论 (0)编辑 收藏
     摘要: Solr 是一种可供企业使用的、基于 Lucene 的搜索服务器,它支持层面搜索、命中醒目显示和多种输出格式。在这篇文章中,将介绍 Solr 并展示如何轻松地将其表现优异的全文本搜索功能加入到 Web 应用程序中。 开发环境: System:Windows WebBrowser:IE6+、Firefox3+ JDK:1.6+ JavaEE Server:tomcat5.0.2.8、tom...  阅读全文
posted @ 2011-10-21 16:41 hoojo 阅读(5741) | 评论 (4)编辑 收藏
     摘要:   阅读全文
posted @ 2011-10-21 11:18 hoojo 阅读(541) | 评论 (0)编辑 收藏
     摘要: 基本原理:利用URLConnection获取要下载文件的长度、头部等相关信息,并设置响应的头部信息。并且通过URLConnection获取输入流,将文件分成指定的块,每一块单独开辟一个线程完成数据的读取、写入。通过输入流读取下载文件的信息,然后将读取的信息用RandomAccessFile随机写入到本地文件中。同时,每个线程写入的数据都文件指针也就是写入数据的长度,需要保存在一个临时文件中。这样当...  阅读全文
posted @ 2011-09-30 18:29 hoojo 阅读(2622) | 评论 (0)编辑 收藏

开发环境:

System:Windows

WebBrowser:IE6+、Firefox3+

JavaEE Server:tomcat5.0.2.8、tomcat6

IDE:eclipse、MyEclipse 8

Flex IDE:Flash Builder 4

BlazeDS:4.5

开发依赖库:

JavaEE5、blazeDS 4.5

Email:hoojo_@126.com

Blog:http://blog.csdn.net/IBM_hoojo

http://hoojo.cnblogs.com/

 

一、准备工作

1、 首先要提供相关的jar包

Java服务器端需要提供BlazeDS相关的配置和jar包

下载地址:http://opensource.adobe.com/wiki/display/blazeds/download+blazeds+trunk

下载后,解压你可以看到这样的一个目录

clip_image002

Docs就是文档

Resource是源码

SampleDB是示例用的数据库,可以运行startdb.bat来启动数据库

Tomcat是内置的tomcat,如果你没有tomcat的话可以使用它,在tomcat的webapps目录中有samples示例

blazeds.war就是blazeDS的核心文件、库,你可以把这个war放到tomcat的webapps目录下,就会自动解压。当然你也可以自己手动解压。

Blazeds-spring.war是和spring整合的配置

Ds-console.war是blazeDS的控制台程序

Samples.war是官方提供的示例

Samples-spring.war是spring和blazeDS的整合示例

二、部署服务器端程序

1、新建一个JavaWeb Project工程,然后在WEB-INF/lib目录中添加如下jar包

clip_image004

这些jar包可以在blazeds.war包中的lib目录中可以找到

2、 然后你需要将blazeds.war包中的WEB-INF目录下的flex目录复制到当前工程的WEB-INF下

3、 将blazeds.war包中的WEB-INF目录下的web.xml的配置,添加到当前工程的web.xml文件中

4、 最后基本的样式如下

clip_image006

5、 最后你发布当前工程,如果没有错误就表明你服务器端部署成功了。

6、 编写一个HelloWorld的java程序。代码如下

package com.hoo.flex;
 
/**
 * <b>function:</b> HelloWorld Example
 * @author hoojo
 * @createDate 2011-8-31 下午06:11:27
 * @file HelloWorld.java
 * @package com.hoo.flex
 * @project BlazeDSServer
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
public class HelloWorld {
    
    public HelloWorld() {
    }
    
    public String sayHello(String name) {
        return "[" + name + "] say hello!";
    }
}

就一个sayHello方法,接收一个参数。

三、Flex客户端程序

1、创建一个Flex工程,在选择服务器技术的时候,你需要选择J2EE。然后勾上使用J2EE技术,然后选择BlazeDS。点击Next下一步

clip_image008

2、配置根文件夹,也就是JavaEE服务器端发布程序在tomcat中的位置。我这里是在tomcat的webapps的BlazeDSServer中,BlazeDSServer是我的服务器端程序。根URL是访问服务器端程序的url;上下文目录对应工程名称;最后就是输出文件夹目录,这个是Flex的文件最后在tomcat中保存的目录。

clip_image010

3、最后你需要设置服务器端的services-config.xml的路径到编译参数中,这个很重要!如果你不设置的话,那么你在后面用RemoteObject调用BlazeDS的时候,就需要设置endpoint。设置如下:

clip_image012

-services是参数键,后面的字符串是值。我这里是设置BlazeDSServer发布到tomcat目录中的services-config.xml的路径。

4、编译Flex前端代码,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" viewSourceURL="BlazeDSHelloWorld.mxml" layout="absolute" minWidth="955" minHeight="600">
    <mx:Script>
        <![CDATA[
            import mx.controls.Alert;
            import mx.rpc.AsyncToken;
            import mx.rpc.events.ResultEvent;
            
            private function faultHandler(event: Event): void {
                Alert.show(event.toString(), event.type);
            }
            
            private function resultHandler(event: ResultEvent): void {
                //event.result是服务器端返回对象
                result.text = "Message:" + event.result.toString();
            }
            
            private function sendHandler(): void {
                helloRemoteObject.sayHello(userName.text);
            }        
        ]]>
    </mx:Script>
    
    <!-- 当工程没有设置编译器-service参数 或是-context-root等参数,就需要手动设置endpoint参数 -->
    <mx:RemoteObject 
        id="helloRemoteObject" 
        destination="helloWorld" 
        fault="faultHandler(event)" 
        result="resultHandler(event)"
        showBusyCursor="true"/>
    <mx:Panel x="10" y="10" width="272" height="148" layout="absolute" title="BlazeDS Remote HelloWorld Sample">
        <mx:Label x="10" y="22" text="请输入名称"/>
        <mx:TextInput x="70" y="19" id="userName"/>
        <mx:Button x="184" y="45" label="发送" click="sendHandler()"/>
        <mx:Text x="10" y="79" id="result"/>
    </mx:Panel>    
</mx:Application>

首先你需要将Java服务器端的HelloWorld程序配置在flex的remoting-config.xml中,配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<service id="remoting-service" 
    class="flex.messaging.services.RemotingService">
 
    <adapters>
        <adapter-definition id="java-object" class="flex.messaging.services.remoting.adapters.JavaAdapter" default="true"/>
    </adapters>
    
    <default-channels>
        <channel ref="my-amf"/>
    </default-channels>
    
    <destination id="helloWorld">    
        <properties>    
            <source>com.hoo.flex.HelloWorld</source>    
        </properties>    
    </destination> 
</service>

上面mxml代码中的RemoteObject的destination对应的就是remoting-config.xml配置文件中的destination的id。这个是一一对应的,然后在sendHandler方法中,helloRemoteObject对应的就是RemoteObject的id,而sayHello方法对应的就是配置在remoting-config.xml中的destination的source的Java服务器端代码的公有方法。添加完配置后,需要重启tomcat。

运行上面的flex程序后,如果输入参数后,点击发送,可以看到服务器端返回的消息就说明BlazeDS整合Flex成功了。

posted @ 2011-09-16 15:24 hoojo 阅读(1869) | 评论 (2)编辑 收藏
     摘要: Dom4j也可以很方便完成XML文档的创建、元素的修改、文档的查询遍历等,但dom4j稍比jdom复杂一点,不过在大片文档的情况下dom4j的性能要不jdom好。 # 准备 首先,提供相关的jar包 Dom4j jar包下载: http://sourceforge.net/projects/dom4j/files/dom4j-2.0.0-ALPHA-2/ jaxen jar下载: http://...  阅读全文
posted @ 2011-08-11 15:52 hoojo 阅读(3220) | 评论 (0)编辑 收藏
     摘要: 可扩展标记语言——eXtensible Markup Language 用户可以自己定义语言标记,只要有开始和闭合标签即可。 xsl装饰、修饰xml的显示结果。 dtd约束xml文件中的标记。 Ø XML的优点:     1、xml可以让数据和标记分离。     2、异质信息互通     3、机...  阅读全文
posted @ 2011-08-10 18:40 hoojo 阅读(2215) | 评论 (0)编辑 收藏

SQL Server 数据库设计

     一、数据库设计的必要性
     二、什么是数据库设计
     三、数据库设计的重要
     四、数据模型
          实体-关系(E-R)数据模型
         实体(Entity)
         属性(Attribute)
         关系(Relationship)
     五、数据库设计步骤
         1、 需求分析阶段
         2、 概要设计阶段
         3、 详细设计阶段
     六、数据库设计规范化
         数据库设计中经常出现的问题
         规范设计
         规范化和性能关系

 

 

SQL Server 数据库基础编程

     Go批处理语句
     使用、切换数据库
     创建、删除数据库
     基本数据类型
          精确数字类型
          近似数字类型
          日期时间类型
          字符串类型
          Unicode字符串类型
          二进制字符串类型
     判断表或其他对象及列是否存在
     创建、删除表
     给表添加字段、修改字段、删除字段
     添加、删除约束
     插入数据
     查询、修改、删除数据
     备份数据、表
     利用存储过程查询表信息

 

 

SQL Server Transact-SQL 编程

    变量
        1、 局部变量(Local Variable)
        2、 全局变量(Global Variable
    输出语句
    逻辑控制语句
        1、 if-else判断语句
        2、 while…continue…break循环语句
        3、 case
        4、 其他语句

 

 

SQL Server T-SQL高级查询

    基本常用查询
    嵌套子查询
        # from (select … table)示例
        # in, not in子句查询示例
        # exists和not exists子句查询示例
        # some、any、all子句查询示例
    聚合查询
        1、 distinct去掉重复数据
        2、 compute和compute by汇总查询
        3、 cube汇总
    排序函数
        # row_number函数
        # rank函数函数
        # dense_rank函数
        # partition by分组子句
        # ntile平均排序函数
    集合运算
        1、 union和union all进行并集运算
        2、 intersect进行交集运算
        3、 except进行减集运算
    公式表表达式
    连接查询
        1、 简化连接查询
        2、 left join左连接
        3、 right join右连接
        4、 inner join内连接
        5、 cross join交叉连接
        6、 自连接(同一张表进行连接查询)
    函数
        1、 聚合函数
        2、 日期时间函数
        3、 数学函数
        4、 元数据
        5、 字符串函数
        6、 安全函数
        7、 系统函数
        8、 配置函数
        9、 系统统计函数
        10、 用户自定义函数

 

 

SQL Server 索引和视图

    索引
        1、 什么是索引
        2、 索引分类
        3、 创建索引
        4、 适合的创建索引的列
        5、 不适合创建索引的列
    视图
        1、 什么是视图
        2、 创建视图准则
        3、 创建视图
        4、 修改视图
        5、 加密视图

 

 

SQL Server 存储过程

    存储过程的概念
        1、 存储过程的优点
            A、 存储过程允许标准组件式编程
            B、 存储过程能够实现较快的执行速度
            C、 存储过程减轻网络流量
            D、 存储过程可被作为一种安全机制来充分利用
    系统存储过程
    用户自定义存储过程
        1、 创建语法
        2、 创建不带参数存储过程
        3、 修改存储过程
        4、 带参存储过程
        5、 带通配符参数存储过程
        6、 带输出参数存储过程
        7、 不缓存存储过程
        8、 加密存储过程
        9、 带游标参数存储过程
        10、 分页存储过程
    Raiserror

 

 

SQL Server 事务、异常和游标

    事务
        1、 事务的特点
            原子性
            一致性
            隔离性
            持久性
        2、 事务的模式
           a、 显示事务
           b、 自动提交事务
           c、 隐式事务
        3、 事务处理
            a、 begin transaction语句
            b、 commit transaction语句
            c、 rollback transaction语句
        4、 事务的示例
    异常
        # 示例:用异常处理错误信息
        # 示例:异常能处理的错误信息
        # 示例:无法提交的事务
        # 示例:处理异常日志信息
    游标
        1、游标实际功能
        2、游标的基本操作
           A、 定义游标
           B、 打开游标
           C、 检索游标
           D、 关闭游标
           E、 删除游标
        3、游标操作示例

 

 

SQL Server 触发器

    什么是触发器
       DML触发器分为:
            1、 after触发器(之后触发)
               a、 insert触发器
               b、 update触发器
               c、 delete触发器
            2、 instead of 触发器 (之前触发)
    创建触发器
        # 创建insert类型触发器
        # 创建delete类型触发器
        # 创建update类型触发器
        # update更新列级触发器
        # instead of类型触发器
        # 创建instead of触发器
        # 显示自定义消息raiserror
        # 修改触发器
        # 启用、禁用触发器
        # 查询创建的触发器信息
        # 示例,验证插入数据
        # 示例,操作日志

 

 

SQL Server 数据库安全

posted @ 2011-07-21 15:24 hoojo 阅读(2225) | 评论 (1)编辑 收藏
仅列出标题
共2页: 上一页 1 2