posts - 10, comments - 9, trackbacks - 0, articles - 17

2009年4月21日

选自 http://java.chinaitlab.com/Spring/762022.html

 Spring Security使用一组过滤器链来对用户进行身份验证和授权。首先,在web.xml文件中添加FilterToBeanProxy过滤器配置:
 1 <filter>   
 2       <filter-name>springSecurityFilterChain</filter-name>
 3      <filter-class>
 4         org.springframework.security.util.FilterToBeanProxy
 5      </filter-class>
 6      <init-param>       
 7           <
param-name>targetClass</param-name>
 8          <param-value>           
 9               org.springframework.security.util.FilterChainProxy
10          </param-value>
11       </init-param>
12 </filter>
13
        org.springframework.security.util.FilterToBeanProxy实现了Filter接口,它通过调用WebapplicationContextUtils类的getWebApplicationnContext(servletContext)方法来获取Spring的应用上下文句柄,并通过getBean(beanName)方法来获取Spring受管Bean的对象,即这里targetClass参数配置的Bean,并通过调用FilterChain Proxy的init()方法来启动Spring Security过滤器链进行各种身份验证和授权服务(FilterChainProxy类也是实现了Filter接口),从而将过滤功能委托给Spring的FilterChainProxy受管Bean(它维护着一个处理验证和授权的过滤器列表,列表中的过滤器按照一定的顺序执行并完成认证过程),这样即简化了web.xml文件的配置,又能充分利用 Spring的IoC功能来完成这些过滤器执行所需要的其它资源的注入。

        当用户发出请求,过滤器需要根据web.xml配置的请求映射地址来拦截用户请求,这时Spring Security开始工作,它会验证你的身份以及当前请求的资源是否与你拥有的权限相符,从而达到保护Web资源的功能,下面是本例所要过滤的用户请求地址:
 1 <filter-mapping>
 2 
 3        <filter-name>springSecurityFilterChain</filter-name>

 5        <url-pattern>/j_spring_security_check</url-pattern>
 6 
 7     </filter-mapping>
 8 
 9     <filter-mapping>
10 
11        <filter-name>springSecurityFilterChain</filter-name>
12 
13        <url-pattern>/*</url-pattern>
14 
15 </filter-mapping>

提示:
/j_spring_security_check是Spring Security默认的进行表单验证的过滤地址,你也可以修改为别的名称,但是需要和
applicationContext-security.xml中相对应,当然还会涉及到其它一些默认值(可能是一个成员变量,也可能是别的请
求地址),在下文我们将看到,建议你在阅读此文的同时,应该参照Spring Security项目的源代码,便于你更好的理解。


3 配置applicationContext-security.xml

    3.1 FilterChainProxy过滤器链

    FilterChainProxy会按顺序来调用一组filter,使这些filter即能完成验证授权的本质工作,又能享用Spring Ioc的功能来方便的得到其它依赖的资源。FilterChainProxy配置如下:

 1 <bean id="filterChainProxy"   
        class
="org.springframework.security.util.FilterChainProxy">
 2      <property name="filterInvocationDefinitionSource">
 3         <value><![CDATA[         
                CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON 
 4              PATTERN_TYPE_APACHE_ANT         
                /**=httpSessionContextIntegrationFilter,logoutFilter,
 5              authenticationProcessingFilter,securityContextHolderAwareRequestFilter,
 6              rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,
 7              filterSecurityInterceptor 
 8         ]]></value>
 9      </property>
10 </bean>

    CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON 定义URL在匹配之前必须先转为小写,PATTERN_TYPE_APACHE_ANT 定义了使用Apache ant的匹配模式,/**定义的将等号后面的过滤器应用在那些URL上,这里使用全部URL过滤,每个过滤器之间都适用逗号分隔,它们按照一定的顺序排列。

 
提示:
特别需要注意的是,即使你配置了系统提供的所有过滤器,这个过滤器链会很长,但是千万不要使用换行,否则它们不会正常工作,
容器甚至不能正常启动。
 

    下面根据FilterChainProxy的配置来介绍各个过滤器的配置,各个过滤器的执行顺序如以上配置。

    首先是通道处理过滤器,如果你需要使用HTTPS,这里我们就使用HTTP进行传输,所以不需要配置通道处理过滤器,然后是集成过滤器,配置如下:

1 <bean id="httpSessionContextIntegrationFilter"
2 
3 class="org.springframework.security.context.HttpSessionContextIntegrationFilter"/>

    httpSessionContextIntegrationFilter是集成过滤器的一个实现,在用户的一个请求过程中,用户的认证信息通过SecurityContextHolder(使用ThreadLoacl实现)进行传递的,所有的过滤器都是通过SecurityContextHolder来获取用户的认证信息,从而在一次请求中所有过滤器都能共享Authentication(认证),减少了HttpRequest参数的传送,下面的代码是从安全上下文的获取Authentication对象的方法:

1 SecurityContext context = SecurityContextHolder.getContext();
2 
3 Authentication authentication = context.getAuthentication();

    但是,ThreadLoacl不能跨越多个请求存在,所以,集成过滤器在请求开始时从Http会话中取出用户认证信息并创建一个SecurityContextHolder将Authentication对象保存在其中,在请求结束之后,在从SecurityContextHolder中获取Authentication对象并将其放回Http会话中,共下次请求使用,从而达到了跨越多个请求的目的。集成过滤器还有其它的实现,可以参考相关文档。

提示:
集成过滤器必须在其它过滤器之前被使用。
 

    logoutFilter(退出过滤器) ,退出登录操作:

 1 <bean id="logoutFilter"
 2 
 3     class="org.springframework.security.ui.logout.LogoutFilter">
 4 
 5     <constructor-arg value="/index.jsp"/>
 6 
 7     <constructor-arg>
 8 
 9        <list>
10 
11            <!-- 实现了LogoutHandler接口(logout方法) -->
12 
13            <ref bean="rememberMeServices"/>
14 
15            <bean class="org.springframework.security.ui.logout.SecurityContextLogoutHandler"/>
16 
17        </list>
18 
19     </constructor-arg>
20 
21 </bean>


posted @ 2009-04-21 16:11 wesley1987 阅读(598) | 评论 (0)编辑 收藏

2008年12月23日

 

                  项目实训心得

             在这一个多月的项目实训过程,我感到是我专业学习中收获非常大的一个月。在这个月里,我体验到了团队合作的经验,编程过程中的乐趣,以及将学习应用到实际、从实践中学习的丰收感。

              这一个月里,得到了二个最宝贵体验:一是参与了一个团队合作的、有很强多同模块相互性、和一套完整生命周期流程的工程项目。这一套项目按照软件工程的流程一步步走下来,经历了需求分析,详细设计,实际编码和测试这一系列阶段。一步一步慢慢的走下来。虽然对于真实的项目来说,这个项目的复杂度和规模并不是很大,逻辑要求也不是太严格。但是对于只参加一些3-4人的项目编程的我来说,已经第一次让我体真正的体验到将编程作为一项工程来执行的难得经验。

              第二个体验是详细设计中,将软件架构和分层的思想以及简单的工程模式等应用到了项目中。使用框架等方式,非常有效的提高了代码的复用和工程的可维护性,虽然多层结构看似麻烦,但实际上它很大的降低了设计的复杂度,在实际的体验中感到,使用了框架后的模块,维护起来清晰了很多,容易了很多,降低了耦合,同时增强了模块间的交互和重用。

              随着整个工程的流程一步步进行,我们看到了一个工程的一次次成长。项目伊始,我们得到了项目需求文档(我想这一步在实际中也应该是由项目人员精心设计才完成的),对于工程的不同用例,将工程分为了六个模块,并对应的将组员分为了六组。我们的第一步是完成对需求文档的理解,而成果就是对应了各个模块的实际功能的静态页面,因为软件客户最后体验所有需求的功能实现就是通过操作页面来实现,所以页面要在客户需求的角度去考虑,同时要将需求的功能都赋予体现。在这个过程中,大家除了按功能分化出页面分类外,大部分时间还用来精心设计页面的风格。页面布局和菜单中大量用到了JavaScriptCSS。和以我往设计页面时不同的是,为了让大家可以公用这些设计,在页面的布局中不能太复杂,甚至几乎是不能在需要统一的地面对整体的布置有任何复杂的干预。所有希望统一的部分都要在公共的CSSJavaScript中做出方便统一使用的类或方法,在页面本身的代码中几乎看不到布局设计,只有功能组件。

              在页面设计通过审核之后就是详细设计阶段了,在这阶段的前几天我们犯了一个顺序错误,直接从数据库着手。结果由于项目的功能的复杂性和模块之间太多需要交互的地方,使得数据库的设计进行的很缓慢。经过老师的提点我们改为从程序编码的框架开始着手。联系各功能的具体实现来设计编码的层次结构(框架详细设计在下一节),划分出公共平台。这样再从各模块的功能及其交互划分来联系设计数据库就变的清晰了很多。在设计过程中我们还使用了E-R图来设计出关系数据库,即从参与的对象和对象之间的关系最终设计出数据库的方法。在这次设计中发现自己在利用一些系统的理论进行整体的数据库模型设计方面还存在很多不足。数据库完成后,对框架的设计也基本完成,公共的分页设计,数据库连接与关闭,工程的文件结构和工程的环境也在几次讨论后完成统一设计。

              由于之前对struts有了一定的了解,所以我在需求分析阶段就开始尝试着着手对几个简单模块的实现编码,之后在详细设计阶段中,每次讨论后新加的内容都需要对已经完成的代码进行一次大的修改。随着代码的增长,尝试了很多种文件结构。之后引入项目的框架也经历了很大的修改和许多次的尝试。此外的修改还包括BaseAction的引入,DispatchAction的引入,使用struts异常处理等,并做好工程备份及将修改记录在日报中。在这一次次的修改中让我受益匪浅,对这些设计和修改有了更深刻的体会。这样在详细设计阶段的过程中,框架设计都已经在编码中事先进行了实现和测试,一些功能在写好后被分离出来作为公共平台。终于在小组开始编码时确定出了统一并详细完整的的工程的全部环境,项目的框架结构和整体编码方式。我的编码实现和单元测试也基本完成。

              在两周的编码过程中,我主要是和吉利一起协助各模块编码,增加各模块间交流,在这期间也解决问题的过程中学到知识。经过全体组员两周的努力工作,终于进入了测试阶段。我和吉利负责整体测试,测试联结了所有模块之后,可以顺利的完成全套的流程。让整个设计可以在6个流程中一步步的走下去,同时保证数据库中所有数据和状态的正确性。随着测试一次次的进行,问题渐渐被全部排除,经过3次测试之后,基本可以完全顺利的走完全套流程。

               

              我们这次工程中使用的是四层结构的框架,即将MVC三层结构的同时,将model模型层分成了model模型层和DAO持久层。其中又根据工厂模式分出DAO接口,beanfactoryservicemanager)提供DAO实现。

              结构实现:首先我们根据框架,设计出相应的文件结构。视图层即所有JSP文件,和配置文件一起由eclipse的自动生成单独分在WebRoot下,六模块的页面分别分于六个子目录下。所有的公共页面和jscss目录也放入WebRoot下。由于这次项目中模块间的功能页面基本是完全相互独立的,这为在实现视图层和控制层之间的页面跳转控制带来很大的方便。代码目录(src)下为六个模块的六个目录,公共代码目录(platform),以及后加入的验证模块的目录(validate)。除公共目录外,各模块下代码分为5个目录:ActionmodelFormmanagerdao。(这里有两个命名的失误,根据实际的使用,model的名字应该叫bean更合适,而这里manager一般在框架中称为service。但我们已经有了称为service的模块名称。)这里的ActionForm对应了struts中的组件,DAO层和model-bean一起完成了操作的具体实现,

              视图层view:总体框架上,我们使用的是frameset来实现,不过听老师说现在流行的使用japinclude结合div等来实现页面框架。在之后编码中,因为frameset出现了一个问题,就是用来验证拦截的过滤器无法刷新整个框架,使得拦截后的页面只能显示在被操作的frame中。但是frameset的好处是框架分离的很好,在实现jsp编码中几乎完全不用去考虑框架。我不知道用include是否能做到。以前虽然都使用的include,但是是在每个页面中都要加入include。有时还会影响布局。在编码过程中,我们用JavaScript实现了很多很好用的效果,比如选择时间的窗口,表单的正则表达式验证,表格的变色效果等,封装到公共的js文件中,调用起来很方便。在这次jap编程中,我终于由最初的在页面中堆满java代码,转变为只使用一些JSTLEL语句和struts标签处理逻辑,美观了页面编码,同时让页面更专注于显示层。但这里我对EL语句和纯标签语句又有些难以取舍。EL语句在页面代码中虽然不如单用标签显得纯粹美观,但是EL表达式简约的表现风格让实现和维护变得容易了很多。

              控制层Action的设计一是使用了DispatchAction,将多个Action类合并,方便了管理。二在公共部分中定义了BaseAction,由这个类去继承strutsDispatchAction。之后我们的所有Action都去继承这个BaseAction。这样在需要对Action进行统一处理,以及定义一些供Action公共使用的方法时就可以在这个BaseAction中修改。虽然在这次项目中,BaseAction只定义了个用于处理字符乱码的方法公共使用,但由此即可瞥见对于更复杂的Action统一处理这种设计也能从容应对。由于是分模块进行,于是我们将strutsxml配置文件也分为对应各个模块,使用多xml的配置方式,而这也需要对命名规则等很多方面有更好的协调和统一。在这次控制层的实现中,我起初还是像以前一样对很多不同的验证,模型层返回的异常都在Action中处理并跳转。在之后的修改中,逐渐将这些处理都改至模型层Manager中,由Manager取用持久层的操作方法,实现所有业务逻辑处理。

              具体实现功能的模型层中,我们为每个DAO定义了接口和实现类,这也是我第一次将接口真正应用到程序中。同时我们在每个模块的DAO中应用了工厂模式,由一个factory类实现所有DAO的单例生成。之后在Manager中调用这个实例实现操作。而这个Manager同时本身也是单例实现的,由Action进行静态调用。可见其中实现Action控制层和DAO持久层交互的就是Manager模型层,并将两者严格的分离开来。同时在Manager中还集合处理了所有来至业务功能逻辑和底部数据库的所有异常。因为数据库的连接也是在Manager中创建的,但这不影响持久层的独立性,因为这是考虑到有时一次业务操作会进行多个数据库操作、调用多个数据库方法,将连接在模型层中创建更便于数据库的高效使用。模型层中对异常的集中处理,更简化了上下控制层和模型层的实现,使其更专注于各自的业务实现。在异常处理上,使用了struts的一种异常处理机制,在xml配置文件中进行异常配置。这样在Manager中将异常抛出,由struts实现异常跳转和提示。同时我们还将自定义的异常处理类也作为公共类公用,这样就可以在需要的时候对异常进行统一的处理。

              在持久层的实现上,我们使用了tomcat数据库连接池,在编码中将数据库连接等方法封装到公共类中,并且将连接数据源作静态单例实现,以提高数据库调用的效率。在DAO的设计方面,我们主要针对实际的操作对象和对应的数据库进行DAO层方法的封装。每个方法尽量实现一些简单的操作。这样在不同模块直接有数据和操作交互的时候,只在模型层只要去各个模块的DAO中取得需要的方法加以组合,实现自己的业务处理。很好的提高了代码的复用性和可维护性,降低了各个模块间数据交互处理的设计复杂度。

    //文采太烂, 结尾的感慨段就不发了

posted @ 2008-12-23 21:38 wesley1987 阅读(726) | 评论 (0)编辑 收藏

2008年12月15日

今天一个诡异的问题弄了我半天,最后发现原因如下:

在HTML的head中 引入外部script:
        <script src="<%=path%>/js/service.js" type="text/javascript" ></script>
之后又写内部script (内容无关)
<script type="text/javascript">
  function SecondType(){
  if (document.check.classTwo.value==1){
   stext.style.display="inline";
  }

  else{
   stext.style.display="none";
  }

 }

 function FirstType(select,forwards){
  if (document.check.classOne.value==1){
    ftext.style.display = "inline";
    document.check.classTwo.value=1;
    SecondType();
  }
else{
   ftext.style.display = "none";
   window.location="<%=path%>/service/good.do?operation=getClass&classone="+select.value+"&forward="+forwards; 
  }

 }

</script>
一切正常,
但是 如果将head中的改为
<script src="<%=path%>/js/service.js" type="text/javascript"  />变了下结尾
引入的外部script任然好用,但是下面的内部script就完全不执行。并伴随很多奇怪的显示效果。

posted @ 2008-12-15 19:21 wesley1987 阅读(544) | 评论 (0)编辑 收藏

转自网上的一篇很详细的关于servlet中各种出现乱码的问题即解决方案:
http://www.diybl.com/course/3_program/java/javajs/200829/99730.html

(1)前言:
解决web程序的国际化问题,必须在任何地方使用UTF-8对字符进行编码。(包括:数据库设置为:UTF-8,web页面也要设置为:UTF-8)
这样做的好处在于可以解决在web上不止中文字符编码问题,所有的字符编码都统一使用UTF-8,实现了语言的国际化。同时在保存数据到
数据库时候也省去了编码转换的问题。
在JSP或JSF应用中使用到Servlet,我们通过使用Servlet过滤器进行编码转换,也就是制定编码转换为UFT-8。

(2)Servlet和JSP过滤器Filter简介:
servlet API的2.3版本中最重要的一个新功能就是能够为servlet和JSP页面定义过滤器。过滤器提供了某些早期服务器所支持的非标准“servlet链接”的一种功能强大且标准的替代品。
过滤器是一个程序,它先于与之相关的servlet或JSP页面运行在服务器上。过滤器可附加到一个或多个servlet或JSP页面上,并且可以检查进入这些资源的请求信息。在这之后,过滤器可以作如下的选择:
- 以常规的方式调用资源(即,调用servlet或JSP页面)。
- 利用修改过的请求信息调用资源。
- 调用资源,但在发送响应到客户机前对其进行修改
- 阻止该资源调用,代之以转到其他的资源,返回一个特定的状态代码或生成替换输出。
过滤器提供了几个重要好处。
     首先,它以一种模块化的或可重用的方式封装公共的行为。你有30个不同的serlvet或JSP页面,需要压缩它们的内容以减少下载时间吗?没问题:构造一个压缩过滤器(参阅第11节),然后将它应用到30个资源上即可。
    其次,利用它能够将高级访问决策与表现代码相分离。这对于JSP特别有价值,其中一般希望将几乎整个页面集中在表现上,而不是集中在业务逻辑上。例如,希望阻塞来自某些站点的访问而不用修改各页面(这些页面受到访问限制)吗?没问题:建立一个访问限制过滤器(参阅第8节)并把它应用到想要限制访问的页面上即可。
    最后,过滤器使你能够对许多不同的资源进行批量性的更改。你有许多现存资源,这些资源除了公司名要更改外其他的保持不变,能办到么?没问题:构造一个串替换过滤器(参阅第10节),只要合适就使用它。
    但要注意,过滤器只在与servlet规范2.3版兼容的服务器上有作用。如果你的Web应用需要支持旧版服务器,就不能使用过滤器。
建立一个过滤器涉及下列五个步骤:
1、建立一个实现Filter接口的类。这个类需要三个方法,分别是:doFilter、init和destroy。doFilter方法包含主要的过滤代码,init方法建立设置操作,而destroy方法进行清楚。
2、在doFilter方法中放入过滤行为。doFilter方法的第一个参数为ServletRequest对象。此对象给过滤器提供了对进入的信息(包括表单数据、cookie和HTTP请求头)的完全访问。第二个参数为ServletResponse,通常在简单的过滤器中忽略此参数。最后一个参数为FilterChain,如下一步所述,此参数用来调用servlet或JSP页。
3、调用FilterChain对象的doFilter方法。Filter接口的doFilter方法取一个FilterChain对象作为它的一个参数。在调用此对象的doFilter方法时,激活下一个相关的过滤器。如果没有另一个过滤器与servlet或JSP页面关联,则servlet或JSP页面被激活。
4、对相应的servlet和JSP页面注册过滤器。在部署描述符文件(web.xml)中使用filter和filter-mapping元素。
5、禁用激活器servlet。防止用户利用缺省servlet URL绕过过滤器设置。

doFilter方法:

1 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
2  throws ServletException, IOException
3 {
4  HttpServletRequest req = (HttpServletRequest)request;
5  System.out.println(req.getRemoteHost() + " tried to access " +req.getRequestURL() +" on " + new Date() + ".");
6  chain.doFilter(request,response);
7 }


在web.xml中进行部署
分别是:filter和filter-mapping。filter元素向系统注册一个过滤对象,filter-mapping元素指定该过滤对象所应用的URL。

<filter>
<filter-name>ChangeCodeFilter</filter-name>
<display-name>ChangeCodeFilter</display-name>
<description></description>
<filter-class>com.cnc.SetCharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SetCharacterEncodingFilter</filter-name>
<url-pattern>/SetCharacterEncodingFilter</url-pattern>
</filter-mapping>

1.filter元素
filter元素位于部署描述符文件(web.xml)的前部,所有filter-mapping、servlet或servlet-mapping元素之前。filter元素具有如下六个可能的子元素:
 :icon  这是一个可选的元素,它声明IDE能够使用的一个图象文件。
 : filter-name  这是一个必需的元素,它给过滤器分配一个选定的名字。
 : display-name  这是一个可选的元素,它给出IDE使用的短名称。
 : description  这也是一个可选的元素,它给出IDE的信息,提供文本文档。
 : filter-class  这是一个必需的元素,它指定过滤器实现类的完全限定名。
 : init-param  这是一个可选的元素,它定义可利用FilterConfig的getInitParameter方法读取的初始化参数。单个过滤器元素可包含多个init-param元素。
2.filter-mapping元素
  filter-mapping元素位于web.xml文件中filter元素之后serlvet元素之前。它包含如下三个可能的子元素::
  filter-name 这个必需的元素必须与用filter元素声明时给予过滤器的名称相匹配。
  url-pattern  此元素声明一个以斜杠(/)开始的模式,它指定过滤器应用的URL。所有filter-mapping元素中必须提供url-pattern或servlet-name。但不能对单个filter-mapping元素提供多个url-pattern元素项。如果希望过滤器适用于多个模式,可重复整个filter-mapping元素。
:servlet-name  此元素给出一个名称,此名称必须与利用servlet元素给予servlet或JSP页面的名称相匹配。不能给单个filter-mapping元素提供多个servlet-name元素项。如果希望过滤器适合于多个servlet名,可重复这个filter-mapping元素。

(3)在Rational Application Developer 中的建立字符转换过滤器:
1.新建-web-过滤器:SetCharacterEncodingFilter
会在web.xml中产生如上代码:

2.在过滤器的doFilter方法中添加如下代码:

public void doFilter(ServletRequest arg0, ServletResponse arg1,FilterChain arg2) throws IOException, ServletException {
  arg0.setCharacterEncoding(
"UTF-8"); //设定字体编码为UTF-8
  arg2.doFilter(arg0, arg1);// 传递控制到下一个过滤器
 }

3.在web.xml中进行部署
在web.xml的过滤器-编辑器中选择:servlet 映射 - 添加 - Faces Servlet
会在web.xml中产生如下代码:
<filter-mapping>
<filter-name>SetCharacterEncodingFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>

(4)其他参考信息
tomcat下中文的彻底解决
(一)    JSP页面上是中文,但是看的是后是乱码:
解决的办法就是在JSP页面的编码的地方<%@ page language="java" contentType="text/html;charset=GBK" %>,因为Jsp转成Java文件时的编码问题,默认的话有的服务器是ISO-8859-1,如果一个JSP中直接输入了中文,Jsp把它当作ISO8859-1来处理是肯定有问题的,这一点,我们可以通过查看Jasper所生成的Java中间文件来确认
(二)    当用Request对象获取客户提交的汉字代码的时候,会出现乱码:
解决的办法是:要配置一个filter,也就是一个Servelet的过滤器,代码如下:

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.UnavailableException;
/**
 * Example filter that sets the character encoding to be used in parsing the
 * incoming request
 
*/
public class SetCharacterEncodingFilter implements Filter {
    
/**
     * Take this filter out of service.
     
*/
    
public void destroy() {
    }
    
/**
     * Select and set (if specified) the character encoding to be used to
     * interpret request parameters for this request.
     
*/
    
public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain chain)
throws IOException,ServletException {
    request.setCharacterEncoding(
"GBK");
    
// 传递控制到下一个过滤器
    chain.doFilter(request, response);
    }
    
public void init(FilterConfig filterConfig) throws ServletException {
    }
}

 

 

配置web.xml

<
filter>
<filter-name>Set Character Encoding</filter-name>
<filter-class>SetCharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Set Character Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

如果你的还是出现这种情况的话你就往下看看是不是你出现了第四中情况,你的Form提交的数据是不是用get提交的,一般来说用post提交的话是没有问题的,如果是的话,你就看看第四中解决的办法。
还有就是对含有汉字字符的信息进行处理,处理的代码是:
package dbJavaBean;
public class CodingConvert
{  
 public CodingConvert()
 {
  //
 }
 public String toGb(String uniStr){
     String gbStr = "";
     if(uniStr == null){
   uniStr = "";
     }
     try{
   byte[] tempByte = uniStr.getBytes("ISO8859_1");
   gbStr = new String(tempByte,"GB2312");
     }
  catch(Exception ex){
    }
     return gbStr;
 }
  
 public String toUni(String gbStr){
     String uniStr = "";
     if(gbStr == null){
   gbStr = "";
     }
     try{
   byte[] tempByte = gbStr.getBytes("GB2312");
   uniStr = new String(tempByte,"ISO8859_1");
     }catch(Exception ex){
    }
    return uniStr;
 }
}
你也可以在直接的转换,首先你将获取的字符串用ISO-8859-1进行编码,然后将这个编码存放到一个字节数组中,然后将这个数组转化成字符串对象就可以了,例如:
String str=request.getParameter(“girl”);
Byte B[]=str.getBytes(“ISO-8859-1”);
Str=new String(B);
通过上述转换的话,提交的任何信息都能正确的显示。
(三)    在Formget请求在服务端用request. getParameter(“name”)时返回的是乱码;按tomcat的做法设置Filter也没有用或者用request.setCharacterEncoding("GBK");也不管用问题是出在处理参数传递的方法上:如果在servlet中用doGet(HttpServletRequest request, HttpServletResponse response)方法进行处理的话前面即使是写了:
request.setCharacterEncoding("GBK");
response.setContentType("text/html;charset=GBK");
也是不起作用的,返回的中文还是乱码!!!如果把这个函数改成doPost(HttpServletRequest request, HttpServletResponse response)一切就OK了。
同样,在用两个JSP页面处理表单输入之所以能显示中文是因为用的是post方法传递的,改成get方法依旧不行。
由此可见在servlet中用doGet()方法或是在JSP中用get方法进行处理要注意。这毕竟涉及到要通过浏览器传递参数信息,很有可能引起常用字符集的冲突或是不匹配。
解决的办法是:
1) 打开tomcat的server.xml文件,找到区块,加入如下一行:
URIEncoding=”GBK”
完整的应如下:
<Connector port="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" debug="0" connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="GBK"/>
2)重启tomcat,一切OK。
需要加入的原因大家可以去研究 $TOMCAT_HOME/webapps/tomcat-docs/config/http.html下的这个文件就可以知道原因了。需要注意的是:这个地方如果你要是用UTF-8的时候在传递的过程中在Tomcat中也是要出现乱码的情况,如果不行的话就换别的字符集。
(四)    JSP页面上有中文,按钮上面也有中文,但是通过服务器查看页面的时候出现乱码:
     解决的办法是:首先在JSP文件中不应该直接包含本地化的消息文本,而是应该通过<bean:message>标签从Resource Bundle中获得文本。应该把你的中文文本放到Application.properties文件中,这个文件放在WEB-INF/classes/*下,例如我在页面里有姓名,年龄两个label,我首先就是要建一个Application.properties,里面的内容应该是name=”姓名” age=”年龄”,然后我把这个文件放到WEB-INF/classes/properties/下,接下来根据Application.properties文件,对他进行编码转化,创建一个中文资源文件,假定名字是Application_cn.properties。在JDK中提供了native2ascii命令,他能够实现字符编码的转换。在DOS环境中找到你放置Application.properties的这个文件的目录,在DOS环境中执行一下命令,将生成按GBK编码的中文资源文件Application_cn.properties:native2ascii ?encoding gbk Application.properties Application_cn.properties执行以上命令以后将生成如下内容的Application_cn.properties文件:name=\u59d3\u540d age=\u5e74\u9f84,在Struts-config.xml中配置:<message-resources parameter="properties.Application_cn"/>。到这一步,基本上完成了一大半,接着你就要在JSP页面上写<%@ page language="java" contentType="text/html;charset=GBK" %>,到名字的那个label是要写<bean:message key=”name”>,这样的化在页面上出现的时候就会出现中文的姓名,年龄这个也是一样,按钮上汉字的处理也是同样的。
(五)    写入到数据库是乱码:
解决的方法:要配置一个filter,也就是一个Servelet的过滤器,代码如同第二种时候一样。
如果你是通过JDBC直接链接数据库的时候,配置的代码如下:jdbc:mysql://localhost:3306/workshopdb?useUnicode=true&characterEncoding=GBK,这样保证到数据库中的代码是不是乱码。
如果你是通过数据源链接的化你不能按照这样的写法了,首先你就要写在配置文件中,在tomcat 5.0.19中配置数据源的地方是在C:\Tomcat 5.0\conf\Catalina\localhost这个下面,我建立的工程是workshop,放置的目录是webapp下面,workshop.xml的配置文件如下:
<!-- insert this Context element into server.xml -->
<Context path="/workshop" docBase="workshop" debug="0"
reloadable="true" >
  <Resource name="jdbc/WorkshopDB"
               auth="Container"
               type="javax.sql.DataSource" />
  <ResourceParams name="jdbc/WorkshopDB">
    <parameter>
      <name>factory</name>
      <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
    </parameter>
    <parameter>
      <name>

maxActive</name>
      <value>100</value>
    </parameter>
    <parameter>
      <name>maxIdle</name>
      <value>30</value>
    </parameter>
   
    <parameter>
      <name>maxWait</name>
      <value>10000</value>
    </parameter>
      <parameter>
     <name>username</name>
     <value>root</value>
    </parameter>
    <parameter>
     <name>password</name>
     <value></value>
    </parameter>
    <!-- Class name for mm.mysql JDBC driver -->
    <parameter>
       <name>driverClassName</name>
       <value>com.mysql.jdbc.Driver</value>
</parameter>
   <parameter>
      <name>url</name>
 <value><![CDATA[jdbc:mysql://localhost:3306/workshopdb?useUnicode=true&characterEncoding=GBK]]></value>
    </parameter>
  </ResourceParams>
</Context>
粗体的地方要特别的注意,和JDBC直接链接的时候是有区别的,如果你是配置正确的化,当你输入中文的时候到数据库中就是中文了,有一点要注意的是你在显示数据的页面也是要用<%@ page language="java" contentType="text/html;charset=GBK" %>这行代码的。需要注意的是有的前台的人员在写代码的是后用Dreamver写的,写了一个Form的时候把他改成了一个jsp,这样有一个地方要注意了,那就是在Dreamver中Action的提交方式是request的,你需要把他该过来,因为在jsp的提交的过程中紧紧就是POST和GET两种方式,但是这两种方式提交的代码在编码方面还是有很大不同的,这个在后面的地方进行说明.


文章出处:http://www.diybl.com/course/3_program/java/javajs/200829/99730_3.html

posted @ 2008-12-15 17:09 wesley1987 阅读(465) | 评论 (0)编辑 收藏

一. 使用 方法调用处理中文:
    public static String changeStr(String str){    
        
if(str==null)return null;
        String temp
=null;
        
try {
            temp 
= new String(str.getBytes("ISO-8859-1"));
        } 
catch (UnsupportedEncodingException e) {
            
            e.printStackTrace();
        }
        
return temp;
    }

  我们将这个方法作为静态写入了BaseAction中,使所有的方法都能调用。
    String offername = changeStr(request.getParameter("offername"));
这种方法的好处是: 无论是POST/GET的页面表单,还是重写的URL他都一并处理了。写起来也简单
可问题是:对于所有页面参数几乎都要调用一下这个方法,对于大的工程就很不合适了。
                特别是参数很多的Form中,所有的参数都要用它处理一次。虽然我把这个处理写入了验证中自动调用。
            但是还是感觉比较麻烦。

 

二. 使用 过滤器 Filter
1 新建一个java文件:SetCharacterEncodingFilter


 
import java.io.IOException;
 
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
 
public class CharacterEncodingFilter implements Filter {
 
    
private FilterConfig config;
    
private String encoding;
 
    
public void destroy() {
        
// 销毁配置
        this.config = null;
 
    }
 
    
public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) 
throws IOException, ServletException {
        
// 如果编码已经配置, 则使用该编码.
        if(this.encoding != null) {
            request.setCharacterEncoding(
this.encoding);
        }
        
// 将资源链到下一Filter, 如果这是最后一个Filter, 则将资源链到目的位置.
        chain.doFilter(request, response);
 
    }
 
    
public void init(FilterConfig config) throws ServletException {
        
// 方便销毁配置
        this.config = config;
        
// 读取web.xml中CharacterEncodingFilter内的初始编码参数
        this.encoding = this.config.getInitParameter("encoding");
 
    }

2 在web.xml中 根节点下加入
<!-- 设置request编码方式  -->
   
<filter>
        
<filter-name>Set Character Encoding</filter-name>
        
<filter-class>com.neusoft.struts.platform.SetCharacterEncodingFilter</filter-class>
        
<init-param>
            
<param-name>encoding</param-name>
            
<param-value>GB2312</param-value>
        
</init-param>
        
<init-param>
            
<param-name>ignore</param-name>
            
<param-value>true</param-value>
        
</init-param>
    
</filter>
    
<filter-mapping>
        
<filter-name>Set Character Encoding</filter-name>
        
<url-pattern>*</url-pattern>
   
</filter-mapping>

使用过滤器 可谓是一劳永逸,所有页面表单是POST的请求,即所有struts中的Form基本都OK了。
但注意:它也仅对POST请求有效。对于GET请求和重写URL的请求,它也会去处理,但由于他们和POST的编码区别,
过滤器会把他们过滤成??

  解决方法:
找到Tomcat安装目录内conf文件夹下的server.xml文件,
给其中的连接器元素Connector添加属性: URIEncoding, 属性值为: UTF-8.

1  <Connector port="8080" protocol="HTTP/1.1" 
2                connectionTimeout="20000" 
3                redirectPort="8443"
4                URIEncoding="UTF-8" />

 

关于乱码详细问题即解决,见 乱码问题详解

posted @ 2008-12-15 14:46 wesley1987 阅读(619) | 评论 (1)编辑 收藏

2008年12月9日

1,操作对象,将数据库里的表映射为持久化类。
    一个商品类 Good,一个供应商 Offer类,一个Offer可以提供多个商品。
商品表字段: goodId, offerId, goodName, price .
供应商字段:    offerId ,offerName.
Good.hbm.xml
:<hibernate-mapping>
    <class name="com.neusoft.Good" table="GOOD" schema="WULIU">
        <id name="goodid" type="java.lang.Long">
            <column name="GOODID" precision="10" scale="0" />
            <generator class="assigned" />
        </id>
        <many-to-one name="offer" class="com.myweb.Offer" fetch="select">
            <column name="OFFERID" precision="10" scale="0" />
        </many-to-one>

        <property name="goodname" type="java.lang.String">
            <column name="GOODNAME" length="40" />
        </property>
        <property name="price" type="java.lang.Double">
            <column name="PRICE" precision="10" />
        </property>

        </property>
    </class>
</hibernate-mapping>

Offer.hbm.xml

<hibernate-mapping>
    <class name="com.neusoft.Offer" table="OFFER" schema="WULIU">
        <id name="offerid" type="java.lang.Long">
            <column name="OFFERID" precision="10" scale="0" />
            <generator class="assigned" />
        </id>
        <property name="offername" type="java.lang.String">
            <column name="OFFERNAME" length="30" />
        </property>
        <set name="goods" inverse="true" lazy="true" cascade="delete" >
            <key>
                <column name="OFFERID" precision="10" scale="0" />
            </key>

            <one-to-many class="com.neusoft.Good" />
<!--java.util.Set : private Set goods = new HashSet(0);-->

        </set>
    </class>
</hibernate-mapping>

lazy="true" 与特定的Offer对象相对应的Good不会像Offer对象一样由同一个SQL查询获取
inverse="true" 表示用此表示两者之间的关系。
cascade="delete" 级联删除

由此配置文件可生成对应的持久化类(即JavaBeans类)  Good.java, Offer.java

2. org.hibernate.cfg.Configuration 创建一个HibernateSessionFactory。
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;

public class HibernateSessionFactory {
          
          private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";//xml中配置了数据库的连接信息。
        private static org.hibernate.SessionFactory sessionFactory;
        
private static String configFile = CONFIG_FILE_LOCATION;

    
static {
        
try {
            configuration.configure(configFile);
            sessionFactory 
= configuration.buildSessionFactory();
        } 
catch (Exception e) {
            System.err
                    .println(
"%%%% Error Creating SessionFactory %%%%");
            e.printStackTrace();
        }
    }
    
private HibernateSessionFactory() {
    }

    public static org.hibernate.SessionFactory getSessionFactory() {
          return sessionFactory;
     }

}
(这是用Myeclipse自动生成的代码中一小段)
创建了SessionFactory,就可以用getSession方法来实现操作了,如
public void save(Good transientInstance) {
          log.debug("saving Good instance");
      try {
               getSession().save(transientInstance);
               log.debug("save successful");
      } catch (RuntimeException re) {
               log.error("save failed", re);
               throw re;
      }
 }




posted @ 2008-12-09 15:10 wesley1987 阅读(125) | 评论 (0)编辑 收藏

2008年12月4日

模块的实现写的差不多了,可是 每个页面的活动都要一个Action,3个对象的增删改查 就有14个Action。终于今天组长发飙了,要改成DispatchAction。现上网查查怎么用。。找到个本博客中的文章放入收藏了。

http://www.blogjava.net/jxhkwhy/archive/2007/01/21/95177.html

把增删改查都放到一个Action中,然后在XML中为每个方法配一个
< action

      attribute = "addUserForm"

      input = "/addUser.jsp"

      name = "addUserForm"

      parameter="method"

      path = "/addUser"

      scope = "request"

      type="com.why.struts.action.UserAction" >

    </ action >
其实如果使用的Form(name=“xxxForm”)是一样的话,几个方法配一个<action>也行。用多个的时候,注意path不要写成一样的了。
注意parameter的值,作为JSP跳转的do的参数就可以了。基本上配置方面 和一般<action>区别就是含有同一个type地址和parameter

<html:link href="addUser.do?method=addUser">Add User</html:link>

参数值为Action里的方法名,如这个 对应为 Action中的
addUser (ActionMapping mapping,ActionForm form, HttpServletRequest request,HttpServletResponse response)


 execute就不用在写了。虽然不知道写了会怎么样。 
下面是我自己的struts-config.xml配置: 
            实现offer的增,删,改,查。其中查和删的配置写在了一起。所以是 3个Action,注意其 path,type ,和parameter属性。调用时用parameter的值区分。这里还可以看到定向到offerSearch的URL的使用。
这里的name虽然相同,但是分开的原因是 我需要input这个属性作为异常的转回页面。查询和删除都不用name 而且异常提示页面相同,所以合并。
    <action
      
input="/service/offerSearch.jsp"
      parameter
="operation"
      path
="/offer"
      scope
="request"
      type
="com.neusoft.struts.service.action.OfferAction">
      
<forward name="success" path="/offer.do?operation=offerSearch&amp;offername="/>
      
<forward name="show" path="/service/offerSearch.jsp" />
    
</action>
    
<action
      
attribute="OfferForm"
      input
="/service/offerNew.jsp"
      parameter
="operation"
      name
="OfferForm"
      path
="/offerAdd"
      scope
="request"
      type
="com.neusoft.struts.service.action.OfferAction">
      
<forward name="success" path="/offer.do?operation=offerSearch&amp;offername="/>
    
</action>
    
<action 
     
attribute="OfferForm"
    name
="OfferForm"
    parameter
="operation"
    path
="/offerUpdate" 
    input
="/service/offerUpdate.jsp"
    scope
="request"
    type 
="com.neusoft.struts.service.action.OfferAction" >
     
<forward name="success" path="/offer.do?operation=offerSearch&amp;offername="/>
    
</action>

对应的DispatchAction    :

public class OfferAction extends DispatchAction {
    
    
    
public ActionForward offerSearch(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response) 
throws Exception {
        
        String offername 
= changeStr(request.getParameter("offername"));
        request.setAttribute(
"offername", offername);
        
        HttpSession session 
= request.getSession();
        IPageList pageList;

        
if(request.getParameter("page")==null){            //来自查询表单的请求
            pageList = new PageList(1,OfferManager.getInstance().getOfferList(offername));
            session.setAttribute(
"list", pageList.getResultList());
            request.setAttribute(
"pageList", pageList);
        }
        
else{                                            //来自分页链接的请求
            int page = Integer.parseInt(request.getParameter("page"));
            pageList 
= new PageList(page,OfferManager.getInstance().getOfferList(offername));
            session.setAttribute(
"list", pageList.getResultList());
            request.setAttribute(
"pageList", pageList);
        }        
        
return mapping.findForward("show");
    }

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

        OfferForm offer 
= (OfferForm) form;
        
        OfferManager.getInstance().addOffer(offer);
        
        
return mapping.findForward("success");
    }

    
public ActionForward offerUpdate(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response) 
throws Exception {
        
        OfferForm offer 
= (OfferForm) form;

        OfferManager.getInstance().offerUpdate(offer);
        
return mapping.findForward("success");
        
    }

    
public ActionForward offerDelete(ActionMapping mapping,ActionForm Form,
                    HttpServletRequest request,HttpServletResponse response)
throws Exception{
        
        String id 
= request.getParameter("offerId");
        
if(id!=null){
            OfferManager.getInstance().offerDelete(Integer.parseInt(id));
        }
        
return mapping.findForward("success");
    }
}



posted @ 2008-12-04 17:12 wesley1987 阅读(392) | 评论 (0)编辑 收藏

2008年11月27日

今天试着不用自动生成,手动配置了一次struts。结果是 传到Action的form 一直为空,上网查寻后原因是:

在struts-config.xml   <action>里的name属性值要和你的formbean里的name属性值要一致,validate属性值要为true,要是没写默认为true

看来有必要详看下struts-config.xml的配置。以下是复制于网上的“struts-config.xml详解”:
 http://www.9php.com/college/net/java/qt/2006/07/522422119091.html
Struts的核心是struts-config.xml配置文件,在这个文件里描述了所有的Struts组件。在这里包括配置主要的组件及次要的组件,下面是struts-config.xml包含主要元素的内容:

一、        struts-config.xml的主要元素:
<?xml  version=”1.0”  encoding=”ISO-8859-1”?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN" "http://struts.apache.org/dtds/struts-config_1_3.dtd">
<struts-config>
     
     <data-sources>
             <data-source>
             </data-source>
     </data-sources>

     <form-beans>
             <form-bean  name =“ ”  type=“ ”   / >
     </form-beans>

    <global-exceptions />

     <global-forwards>
             <forward  /  >
     </global-forwards>

     <action-mappings>
             <action  /  >
     </action-mappings>

     <controller  /  >

     <message-resources  /  >

     <plug-in  />

</struts-config>
注意:以上各元素的顺序是非常重要的,你的struts-config.xml配置文件必须按照这个顺序进行配置,否则在你的容器启动的时候就会出错。


二、        struts-config.xml的子元素:
1.<icon / >子元素
     它包含<small-icon  /  >及<large-icon  /  >,它的作用是图形化其父元素,<small-icon/>的内容是一个16x16的图像文件,而<large-icon/>的内容是一个32x32的图像文件。如下例子:
     <icon>
<small-icon>
                           /images/smalllogo.gif
</small-icon>
<large-icon>
       /images/largelogo.gif
</large-icon>
</icon>
2.<display-name  /  >子元素
     它提供对父元素的短文字(short  textual)描述信息,如下:
     <display-name>
                     short  textual  discription  of  its  parent  element
     </display-name>
3.<description  /  >子元素
     它提供对父元素的完全(full-length  textual)的描述信息,如下:
<description>
full-length  textual  discription  of  its  parent  element
</description>
4.<set-property  /  >子元素
             它用来设置它的父元素中设定的JavaBean的属性值,它一般用在指定的GenericDataSource  属性,扩展的ActionMappings以及扩展的  global  forwards。如下:
             <set-property  
                     property="name  of  bean  property"              
value="value  of  bean  property"  />
                 例如:
                 <set-property  property="driverClass"  value="org.gjt.mm.mysql.Driver"  />
               <set-property  property="user"  value="admin"/>
               <set-property  property="maxCount"  value="4"/>
<set-property  property="minCount"  value="2"/>  
<set-property  property="password"  value=""/>  
<set-property  property="url"  value="jdbc:mysql://localhost:3306/struts"/>


三、        配置JDBC数据源
其配置形式如下:
<data-sources>
<data-source>
<set-property  property="driverClass"  value="fully  qualified  path  of  JDBC  driver"/>
<set-property  property="url"  value="data  source  URL"/>
<set-property  property=”mincount”  value="the  minimum  number  of  connections  to  open"/>
<set-property  property="password"  value="the  password  used  to  create  connections"/>
<set-property  property="user"  value="the  username  used  to  create  connections"/>
</data-source>
</data-sources>
<data-source>的属性及其描述信息如下:
Key        绑定在ServletContext上的DataSource实例的索引键,若不设定则缺省为Action.DATA_SOURCE_KEY,如果在应用程序中有多于一个的DataSource,则必须设置Key的值。
DriverClass        所用的JDBC驱动类(必须的)如:com.microsoft.jdbc.sqlserver.SQLServerDriver
url        所用的JDBC的URL(必须的)如:jdbc:microsoft:sqlserver://xg088:1433
MaxCount        同时打开的最大连结数,缺省值为2(可选的)
MinCount        同时打开的最小连结数,缺省值为1(可选的)
User        连结到数据库的用户名(必须的)
Password        连结到数据库的密码(必须的)
Description        关于DataSource的描述信息(可选的)
ReadOnly        如果设为true,则表示该连结是只读的,缺省为false。(可选的)
LoginTimeout        创建连结的最大允许时间,以秒为单位。(可选的)
AutoCommit        如果为true,则每次execute之后会强制回滚。缺省为true。(可选的)
举例说明:
<data-sources>
       <data-source>
               <set-property  property=”key”  value=”  value="WILEY_DATA_SOURCE"  />
                <set-property  property="driverClass"  value="org.gjt.mm.mysql.Driver"  />
                <set-property  property="url"  value="jdbc:mysql://localhost/wileyusers"  />
                <set-property  property="maxCount"  value="5"/>
                <set-property  property="minCount"  value="1"/>
                <set-property  property="user"  value="sa"/>
                <set-property  property="password"  value="yourpassword"/>
        </data-source>
</data-sources>


四、        配置FormBean
<form-bean  /  >用来定义将要绑定到Action的FormBean的实例。语法如下:
<form-beans>
<form-bean  name="name  used  to  uniquely  identify  a  FormBean"   type=”fully  qualified  class  name  of  FormBean"/>
                 </form-beans>
例:
        <form-beans>
            <form-bean  name="lookupForm"  type="wiley.LookupForm"  />
        </form-beans>



五、        配置全局转发
全局转发可以定义几个<forward/>子元素,struts首先会在<action-mappings>元素中找对应的<forward>,若找不到,则到全局转发配置中找。语法如下:
<global-forwards>
<forward  name="unique  target  identifier"  
path="context-relative  path  to  targetted  resource  "/>
</global-forwards>
除了name及path属性之外,还有一个redirect属性,如果redirect设为true的时候,则用HttpServletResponse.sendRedirect()方法,否则用RequestDispatcher.forward()方法,缺省为false。
注:如果为true,则用HttpServletResponse.sendRedirect()方法,此时存储在原来的HttpServletRequest中的值将会丢失。
例子:
<global-forwards>
<forward  name="success"  path="/welcome.jsp"/>
<forward  name="failure"  path="/index.jsp"/>
</global-forwards>


六、        配置<action-mappings>
它可以定义几个<action  /  >子元素,它主要是定义Action实例到ActionServlet类中,语法如下:
<action-mappings>
<action  path="context-relative  path  mapping  action  to  a  request"
type="fully  qualified  class  name  of  the  Action  class"
name="the  name  of  the  form  bean  bound  to  this  Action">
<forward  name="forwardname1"  path="context-relative  path"/>
<forward name="forwardname2" path="context-relative path"/>
</action>
</action-mappings>
<action/>属性及其描述信息如下:
属  性    描 述 信 息
Path    在浏览器的URL中输入的字符(必须的)
Type    连结到本映射的Action的全称(可选的)
Name    与本操作关联的Action Bean在<form-bean/>中定义name名(可选的)
Scope    指定ActionForm Bean的作用域(session和request),缺省为session。(可选的)
Input    当Bean发生错误时返回的控制。(可选的)
ClassName    指定一个调用这个Action类的ActionMapping类的全名。缺省用org.apache.struts.action.ActionMapping,(可选的)
Forward    指定处理相应请求所对应的JSP页面。(可选的)
Include    如果没有forward的时候,它起forward的作用。(可选的)
Validate    若为true,则会调用ActionForm的validate()方法,否则不调用,缺省为true。(可选的)
例子:
<action-mappings>
    <action path="/lookupAction" 
            type="wiley.LookupAction"
            name="LookupForm"
            scope="request"
            validate="true"
            input="/index.jsp">
        <forward name="success" path="/quote.jsp"/>
        <forward name="faliue" path="/index.jsp"/>
    </action>
</action-mappings>



七、    配置RequestProcessor
在struts-config.xml文件中用<controller/>子元素来定义RequestProcessor,其语法格式如下:
<controller processorClass="fully qualified class name" />
<controller />元素属性及其描述信息如下:
属  性    描  述
processorClass    指定自定义的RequestProcessor类的全名
BufferSize    指定用来下载所用的缓存大小。缺省是4096字节。
contentType    定义response文本类型,缺省是text/html
Debug    定义当前系统的除错级别,缺省是0
Locale    如果是true,则在用户的session中存放Locale对象,缺省为true
maxFileSize    指定下载文件最大的大小。缺省是250M
multipartClass    指定去代替org.apache.struts.upload.DiskMultipartRequestHandler类的类的全名。
Nocache    如果是true,则会关闭每个response的缓存功能。缺省是false
TempDir    指定上载文件所用的临时目录。缺省值由容器决定
例子:
 <controller processorClass="wiley.WileyRequestProcessor" />
② <controller    contentType="text/html;charset=UTF-8"
                        debug="3"
                        locale="true"
                        nocache="true"
                        processorClass="org.apache.struts.action.RequestProcessor"/>



八、    配置Message Resources
在struts-config.xml文件中用<message-resources />元素来定义消息资源。其语法如下:
       <message-resources  parameter="wiley.ApplicationResources"/>
<message-resources />元素属性及其描述信息如下:
属  性    描  述
Parameter    给定资源文件全名
ClassName    定义处理消息资源的类名的全名,缺省是org.apache.struts.config.MessageResourcesConfig
Factory    定义MessageResourcesFactory类的全名,缺省是org.apache.struts.util.property.MessageResourcesFacotry
Key    定义绑定在这个资源包中的ServletContext的属性主键,缺省值是Action.MESSAGES_KEY.
Null    如果为true,则找不到消息key时,则返回null,缺省是true.
例子:
① <message-resources parameter="wiley.ApplicationResources"/>
② <message-resources
    parameter="StorefrontMessageResources"
    null="false"/>
<message-resources
    key="IMAGE_RESOURCE_KEY"
    parameter="StorefrontImageResources"
    null="false"/>

注意:设定key的目的如下:
<html:img altKey="navbar.home.image.alt" bundle="IMAGE_RESOURCE_KEY" pageKey="navbar.home.image" width="125" height="15" border="0"/>
这里说明要到StorefrontImageResources.properties资源文件中找主键值是”navbar.home.image”所对应的值。
这里StorefrontImageResources.properties的内容如下:
……
navbar.home.image=/images/home.gif
navbar.home.image.alt=Home
……
此处navbar.home.image.alt说明的和<img alt=”Home”……/>一样。


九、    配置Plug-in
配置Plug-in如下:
<plug-in className="wiley.WileyPlugin"/>
也可如下:
<plug-in className="com.oreilly.struts.storefront.service.memory.StorefrontMemoryDatabasePlugIn">
  <set-property property="pathname" value="/WEB-INF/database.xml"/>
</plug-in>

下面是我现在的struts-config.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN" "http://struts.apache.org/dtds/struts-config_1_3.dtd">

<struts-config>
  
<form-beans >
    
<form-bean name="OfferForm" type="com.neusoft.struts.form.OfferForm" />

  
</form-beans>

  
<global-exceptions />
  
<global-forwards />
  
<action-mappings >
    
<action
          
attribute="OfferForm"
          input
="/service/offerNew.jsp"
          name
="OfferForm"
          path
="/addOffer"
          scope
="request"
          type
="com.neusoft.struts.action.AddOfferAction">
          
<forward name="message" path="/service/message.jsp" />
          
<forward name="fail" path="/service/offerNew.jsp" />
    
</action>
    
<action path="/offerSearch"
            input
="/service/offerSearch.jsp"
            scope
="request" 
            type
="com.neusoft.struts.action.OfferSearchAction">
              
<forward name="show" path="/service/offerSearch.jsp" />
    
</action>
    
<action  attribute="OfferForm"
            name
="OfferForm"
            path
="/offerUpdate"
            input
="/service/offerUpdate.jsp"
            scope
="request"
            type 
="com.neusoft.struts.action.OfferUpdateAction" >
            
<forward name="message" path="/service/message.jsp"/>
             
<forward name="fail" path="/service/offerUpdate.jsp" />
    
</action>
  
</action-mappings>

  
<message-resources parameter="com.neusoft.struts.ApplicationResources" />
</struts-config>

posted @ 2008-11-27 16:53 wesley1987 阅读(1078) | 评论 (0)编辑 收藏

     摘要: 1.。JSP页面中: ////////////数据显示/////////////////////// 显示 从数据库查出的,放在 list<offer> 中的数据。 <c:forEach items="${requestScope.list}" var="offer">     <tr> &n...  阅读全文

posted @ 2008-11-27 13:34 wesley1987 阅读(750) | 评论 (1)编辑 收藏

2008年11月25日

<!--
/* 调用方法:
  <input onfocus="calendar()" name="s2" type="text" id="s2" style="width:100%;" />
*/
var cal_Width = 180;//定义日历显示的宽度,至少140

document.write("<div id='meizzCalendarLayer' style='position: absolute; z-index: 9999; width: " + (cal_Width+4).toString() + "px; height: 193px; display: none'>");
document.write("<iframe name='meizzCalendarIframe' scrolling='no' frameborder='0' width='100%' height='100%'></iframe></div>");
var WebCalendar = new WebCalendar();

function document.onclick()
{
    if(WebCalendar.eventSrc != window.event.srcElement) hiddenCalendar();
}

function WebCalendar() //初始化日历的设置
{
    this.regInfo    = "WEB Calendar ver 3.0 关闭的快捷键:[Esc]";
   
    this.dayShow    = 38;                       //定义页面上要显示的天数,不能小于35,或大于39
    this.daysMonth  = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
    this.day        = new Array(this.dayShow);            //定义日历展示用的数组
    this.dayObj     = new Array(this.dayShow);            //定义日期展示控件数组
    this.dateStyle  = null;                     //保存格式化后日期数组
    this.objExport  = null;                     //日历回传的显示控件
    this.eventSrc   = null;                     //日历显示的触发控件
    this.inputDate  = null;                     //转化外的输入的日期(d/m/yyyy)
    this.thisYear   = new Date().getFullYear(); //定义年的变量的初始值
    this.thisMonth  = new Date().getMonth()+ 1; //定义月的变量的初始值
    this.thisDay    = new Date().getDate();     //定义日的变量的初始值
    this.today      = this.thisDay +"/"+ this.thisMonth +"/"+ this.thisYear;   //今天(d/m/yyyy)
    this.iframe     = window.frames("meizzCalendarIframe"); //日历的 iframe 载体
    this.calendar   = getObjectById("meizzCalendarLayer");  //日历的层
    this.dateReg    = "";           //日历格式验证的正则式

    this.yearFall   = 50;           //定义显示的年份下拉框的年差值,如果今年是2000年,这里设置为50,就显示1950-2050
    this.format     = "yyyy-mm-dd"; //回传日期的格式
    this.timeShow   = false;        //是否返回时间
    this.drag       = true;         //是否允许拖动
    this.darkColor  = "#95B7F3";    //控件的暗色
    this.lightColor = "#FFFFFF";    //控件的亮色
    this.btnBgColor = "#E6E6FA";    //控件的按钮背景色
    this.wordColor  = "#000080";    //控件的文字颜色
    this.wordDark   = "#DCDCDC";    //控件的暗文字颜色
    this.dayBgColor = "#F5F5FA";    //日期数字背景色
    this.todayColor = "#FF0000";    //今天在日历上的标示背景色
    this.DarkBorder = "#D4D0C8";    //日期显示的立体表达色
   
    this.yearOption = "";
    var yearNow = new Date().getFullYear();
    yearNow = (yearNow <= 1000)? 1000 : ((yearNow >= 9999)? 9999 : yearNow);
    var yearMin = (yearNow - this.yearFall >= 1000) ? yearNow - this.yearFall : 1000;
    var yearMax = (yearNow + this.yearFall <= 9999) ? yearNow + this.yearFall : 9999;
        yearMin = (yearMax == 9999) ? yearMax-this.yearFall*2 : yearMin;
        yearMax = (yearMin == 1000) ? yearMin+this.yearFall*2 : yearMax;
    for (var i=yearMin; i<=yearMax; i++) this.yearOption += "<option value='"+i+"'>"+i+"年</option>";
}  

function writeIframe()
{
    var strIframe = "<html><head><meta http-equiv='Content-Type' content='text/html; charset=gb2312'><style>"+
    "*{font-size: 12px; font-family: 宋体}"+
    ".bg{  color: "+ WebCalendar.lightColor +"; cursor: default; background-color: "+ WebCalendar.darkColor +";}"+
    "table#tableMain{ width: "+ (cal_Width+2).toString() +"px; height: 180px;}"+
    "table#tableWeek td{ width:14%;color: "+ WebCalendar.lightColor +";}"+
    "table#tableDay  td{ width:14%;font-weight: bold;}"+
    "td#meizzYearHead, td#meizzYearMonth{color: "+ WebCalendar.wordColor +"}"+
    ".out { text-align: center; border-top: 1px solid "+ WebCalendar.DarkBorder +"; border-left: 1px solid "+ WebCalendar.DarkBorder +";"+
    "border-right: 1px solid "+ WebCalendar.lightColor +"; border-bottom: 1px solid "+ WebCalendar.lightColor +";}"+
    ".over{ text-align: center; border-top: 1px solid #FFFFFF; border-left: 1px solid #FFFFFF;"+
    "border-bottom: 1px solid "+ WebCalendar.DarkBorder +"; border-right: 1px solid "+ WebCalendar.DarkBorder +"}"+
    "input{ border: 1px solid "+ WebCalendar.darkColor +"; padding-top: 1px; height: 18px; cursor: hand;"+
    "       color:"+ WebCalendar.wordColor +"; background-color: "+ WebCalendar.btnBgColor +"}"+
    "</style></head><body onselectstart='return false' style='margin: 0px' oncontextmenu='return false'><form name=meizz>";

    if (WebCalendar.drag){ strIframe += "<scr"+"ipt language=javascript>"+
    "var drag=false, cx=0, cy=0, o = parent.WebCalendar.calendar; function document.onmousemove(){"+
    "if(parent.WebCalendar.drag && drag){if(o.style.left=='')o.style.left=0; if(o.style.top=='')o.style.top=0;"+
    "o.style.left = parseInt(o.style.left) + window.event.clientX-cx;"+
    "o.style.top  = parseInt(o.style.top)  + window.event.clientY-cy;}}"+
    "function document.onkeydown(){ switch(window.event.keyCode){  case 27 : parent.hiddenCalendar(); break;"+
    "case 37 : parent.prevM(); break; case 38 : parent.prevY(); break; case 39 : parent.nextM(); break; case 40 : parent.nextY(); break;"+
    "case 84 : document.forms[0].today.click(); break;} " +
    "try{window.event.keyCode = 0; window.event.returnValue= false;}catch(ee){}}"+
    "function dragStart(){cx=window.event.clientX; cy=window.event.clientY; drag=true;}</scr"+"ipt>"}

    strIframe += "<table id=tableMain class=bg border=0 cellspacing=2 cellpadding=0>"+
    "<tr><td width='"+ cal_Width +"px' height='19px' bgcolor='"+ WebCalendar.lightColor +"'>"+
    "    <table width='"+ cal_Width +"px' id='tableHead' border='0' cellspacing='1' cellpadding='0'><tr align='center'>"+
    "    <td width='10%' height='19px' class='bg' title='向前翻 1 月 快捷键:←' style='cursor: hand' onclick='parent.prevM()'><b>&lt;</b></td>"+
    "    <td width='45%' id=meizzYearHead "+
    "        onmouseover='this.bgColor=parent.WebCalendar.darkColor; this.style.color=parent.WebCalendar.lightColor'"+
    "        onmouseout='this.bgColor=parent.WebCalendar.lightColor; this.style.color=parent.WebCalendar.wordColor'>" +
    "<select name=tmpYearSelect  onblur='parent.hiddenSelect(this)' style='width:100%;'"+
    "        onchange='parent.WebCalendar.thisYear =this.value; parent.hiddenSelect(this); parent.writeCalendar();'>";
   
//    var yearNow = new Date().getFullYear();
//    yearNow = (yearNow <= 1000)? 1000 : ((yearNow >= 9999)? 9999 : yearNow);
//    var yearMin = (yearNow - WebCalendar.yearFall >= 1000) ? yearNow - WebCalendar.yearFall : 1000;
//    var yearMax = (yearNow + WebCalendar.yearFall <= 9999) ? yearNow + WebCalendar.yearFall : 9999;
//        yearMin = (yearMax == 9999) ? yearMax-WebCalendar.yearFall*2 : yearMin;
//        yearMax = (yearMin == 1000) ? yearMin+WebCalendar.yearFall*2 : yearMax;
//    for (var i=yearMin; i<=yearMax; i++) strIframe += "<option value='"+i+"'>"+i+"年</option>";

    strIframe += WebCalendar.yearOption + "</select>"+
    "</td>"+
    "    <td width='35%' id=meizzYearMonth "+
    "        onmouseover='this.bgColor=parent.WebCalendar.darkColor; this.style.color=parent.WebCalendar.lightColor'"+
    "        onmouseout='this.bgColor=parent.WebCalendar.lightColor; this.style.color=parent.WebCalendar.wordColor'>" +
    "<select name=tmpMonthSelect onblur='parent.hiddenSelect(this)' style='width:100%;'" +   
    "        onchange='parent.WebCalendar.thisMonth=this.value; parent.hiddenSelect(this); parent.writeCalendar();'>";
    for (var i=1; i<13; i++) strIframe += "<option value='"+i+"'>"+i+"月</option>";
    strIframe += "</select>"+
    "</td>"+
    "    <td width='10%' class=bg title='向后翻 1 月 快捷键:→' onclick='parent.nextM()' style='cursor: hand'><b>&gt;</b></td></tr></table>"+
    "</td></tr><tr><td height='20px'>"+
    "<table id=tableWeek border=1 width='"+ cal_Width +"px' cellpadding=0 cellspacing=0 ";
    if(WebCalendar.drag){strIframe += "onmousedown='dragStart()' onmouseup='drag=false' ";}
    strIframe += " borderColorLight='"+ WebCalendar.darkColor +"' borderColorDark='"+ WebCalendar.lightColor +"'>"+
    "    <tr align=center><td height='20px'>日</td><td>一</td><td>二</td><td>三</td><td>四</td><td>五</td><td>六</td></tr></table>"+
    "</td></tr><tr><td valign=top width='"+ cal_Width +"px' bgcolor='"+ WebCalendar.lightColor +"'>"+
    "    <table id=tableDay height='120px' width='"+ cal_Width +"px' border=0 cellspacing=1 cellpadding=0>";
         for(var x=0; x<5; x++){
           strIframe += "<tr>";
           for(var y=0; y<7; y++)
             strIframe += "<td class=out id='meizzDay"+ (x*7+y) +"'></td>";
           strIframe += "</tr>";
         }
         strIframe += "<tr>";
         for(var x=35; x<WebCalendar.dayShow; x++)
           strIframe += "<td class=out id='meizzDay"+ x +"'></td>";
         strIframe +="<td colspan="+(42-WebCalendar.dayShow).toString()+" class=out style='text-align:center;' title='"+ WebCalendar.regInfo +"'>" +
         "<input style=' background-color: " + WebCalendar.btnBgColor +";cursor: hand; padding-top: 2px; width: 44%; height: 100%;' onfocus='this.blur()'"+
         " type=button value='清空' onclick='parent.WebCalendar.objExport.value=\"\";parent.hiddenCalendar()'>" +
         "&nbsp;" +
         "<input style=' background-color: " + WebCalendar.btnBgColor +";cursor: hand; padding-top: 2px; width: 43%; height: 100%;' onfocus='this.blur()'"+
         " type=button value='关闭' onclick='parent.hiddenCalendar()'>" +
         "</td></tr></table>"+
    "</td></tr><tr><td height='20px' width='"+ cal_Width +"px' bgcolor='"+ WebCalendar.lightColor +"'>"+
    "    <table border=0 cellpadding=1 cellspacing=0 width='"+ cal_Width +"px'>"+
    "    <tr><td><input name=prevYear title='向前翻 1 年 快捷键:↑' onclick='parent.prevY()' type=button value='&lt;&lt;'"+
    "    onfocus='this.blur()' style='meizz:expression(this.disabled=parent.WebCalendar.thisYear==1000)'><input"+
    "    onfocus='this.blur()' name=prevMonth title='向前翻 1 月 快捷键:←' onclick='parent.prevM()' type=button value='&lt;&nbsp;'>"+
    "    </td><td align=center><input name=today type=button value='Today' onfocus='this.blur()' style='width: 50px;' title='当前日期 快捷键:T'"+
    "    onclick=\"parent.returnDate(new Date().getDate() +'/'+ (new Date().getMonth() +1) +'/'+ new Date().getFullYear())\">"+
    "    </td><td align=right><input title='向后翻 1 月 快捷键:→' name=nextMonth onclick='parent.nextM()' type=button value='&nbsp;&gt;'"+
    "    onfocus='this.blur()'><input name=nextYear title='向后翻 1 年 快捷键:↓' onclick='parent.nextY()' type=button value='&gt;&gt;'"+
    "    onfocus='this.blur()' style='meizz:expression(this.disabled=parent.WebCalendar.thisYear==9999)'></td></tr></table>"+
    "</td></tr><table></form></body></html>";
    with(WebCalendar.iframe)
    {
        document.writeln(strIframe); document.close();
        for(var i=0; i<WebCalendar.dayShow; i++)
        {
            WebCalendar.dayObj[i] = eval("meizzDay"+ i);
            WebCalendar.dayObj[i].onmouseover = dayMouseOver;
            WebCalendar.dayObj[i].onmouseout  = dayMouseOut;
            WebCalendar.dayObj[i].onclick     = returnDate;
        }
    }
}

function calendar() //主调函数
{
    var e = window.event.srcElement;   writeIframe();
    var o = WebCalendar.calendar.style; WebCalendar.eventSrc = e;
 if (arguments.length == 0) WebCalendar.objExport = e;
    else WebCalendar.objExport = eval(arguments[0]);

    WebCalendar.iframe.tableWeek.style.cursor = WebCalendar.drag ? "move" : "default";
 var t = e.offsetTop,  h = e.clientHeight, l = e.offsetLeft, p = e.type;
 while (e = e.offsetParent){t += e.offsetTop; l += e.offsetLeft;}
    o.display = ""; WebCalendar.iframe.document.body.focus();
    var cw = WebCalendar.calendar.clientWidth, ch = WebCalendar.calendar.clientHeight;
    var dw = document.body.clientWidth, dl = document.body.scrollLeft, dt = document.body.scrollTop;
   
    if (document.body.clientHeight + dt - t - h >= ch) o.top = (p=="image")? t + h : t + h + 6;
    else o.top  = (t - dt < ch) ? ((p=="image")? t + h : t + h + 6) : t - ch;
    if (dw + dl - l >= cw) o.left = l; else o.left = (dw >= cw) ? dw - cw + dl : dl;

    if  (!WebCalendar.timeShow) WebCalendar.dateReg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/;
    else WebCalendar.dateReg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/;

    try{
        if (WebCalendar.objExport.value.trim() != ""){
            WebCalendar.dateStyle = WebCalendar.objExport.value.trim().match(WebCalendar.dateReg);
            if (WebCalendar.dateStyle == null)
            {
                WebCalendar.thisYear   = new Date().getFullYear();
                WebCalendar.thisMonth  = new Date().getMonth()+ 1;
                WebCalendar.thisDay    = new Date().getDate();
                alert("原文本框里的日期有错误!\n可能与你定义的显示时分秒有冲突!");
                writeCalendar(); return false;
            }
            else
            {
                WebCalendar.thisYear   = parseInt(WebCalendar.dateStyle[1], 10);
                WebCalendar.thisMonth  = parseInt(WebCalendar.dateStyle[3], 10);
                WebCalendar.thisDay    = parseInt(WebCalendar.dateStyle[4], 10);
                WebCalendar.inputDate  = parseInt(WebCalendar.thisDay, 10) +"/"+ parseInt(WebCalendar.thisMonth, 10) +"/"+
                parseInt(WebCalendar.thisYear, 10); writeCalendar();
            }
        } else {
          WebCalendar.thisYear   = new Date().getFullYear();
          WebCalendar.thisMonth  = new Date().getMonth()+ 1;
          WebCalendar.thisDay    = new Date().getDate();
          writeCalendar();
        }
    } catch(e) {
      WebCalendar.thisYear   = new Date().getFullYear();
      WebCalendar.thisMonth  = new Date().getMonth()+ 1;
      WebCalendar.thisDay    = new Date().getDate();
      writeCalendar();
    }
}

function funMonthSelect() //月份的下拉框
{
    var m = isNaN(parseInt(WebCalendar.thisMonth, 10)) ? new Date().getMonth() + 1 : parseInt(WebCalendar.thisMonth);
    var e = WebCalendar.iframe.document.forms[0].tmpMonthSelect;
    e.value = m; //e.focus();
    //window.status = e.style.left;
}

function funYearSelect() //年份的下拉框
{
    var e = WebCalendar.iframe.document.forms[0].tmpYearSelect;
    var y = isNaN(parseInt(WebCalendar.thisYear, 10)) ? new Date().getFullYear() : parseInt(WebCalendar.thisYear);
    e.value = y; //e.focus();
//    if(e.value == "")
//    {
//      e.value = new Date().getFullYear();
//      WebCalendar.thisYear = e.value;
//    }
}

function prevM()  //往前翻月份
{
    WebCalendar.thisDay = 1;
    if (WebCalendar.thisMonth==1)
    {
        WebCalendar.thisYear--;
        WebCalendar.thisMonth=13;
    }
    WebCalendar.thisMonth--; writeCalendar();
}

function nextM()  //往后翻月份
{
    WebCalendar.thisDay = 1;
    if (WebCalendar.thisMonth==12)
    {
        WebCalendar.thisYear++;
        WebCalendar.thisMonth=0;
    }
    WebCalendar.thisMonth++; writeCalendar();
}
function prevY(){WebCalendar.thisDay = 1; WebCalendar.thisYear--; writeCalendar();}//往前翻 Year
function nextY(){WebCalendar.thisDay = 1; WebCalendar.thisYear++; writeCalendar();}//往后翻 Year
function hiddenSelect(e){
  //for(var i=e.options.length; i>-1; i--)e.options.remove(i); e.style.display="none";
}
function getObjectById(id){ if(document.all) return(eval("document.all."+ id)); return(eval(id)); }
function hiddenCalendar(){getObjectById("meizzCalendarLayer").style.display = "none";};
function appendZero(n){return(("00"+ n).substr(("00"+ n).length-2));}//日期自动补零程序
function String.prototype.trim(){return this.replace(/(^\s*)|(\s*$)/g,"");}
function dayMouseOver()
{
    this.className = "over";
    this.style.backgroundColor = WebCalendar.darkColor;
    if(WebCalendar.day[this.id.substr(8)].split("/")[1] == WebCalendar.thisMonth)
    this.style.color = WebCalendar.lightColor;
}
function dayMouseOut()
{
    this.className = "out"; var d = WebCalendar.day[this.id.substr(8)], a = d.split("/");
    this.style.removeAttribute('backgroundColor');
    if(a[1] == WebCalendar.thisMonth && d != WebCalendar.today)
    {
        if(WebCalendar.dateStyle && a[0] == parseInt(WebCalendar.dateStyle[4], 10))
        this.style.color = WebCalendar.lightColor;
        this.style.color = WebCalendar.wordColor;
    }
}
function writeCalendar() //对日历显示的数据的处理程序
{
    var y = WebCalendar.thisYear;
    var m = WebCalendar.thisMonth;
    var d = WebCalendar.thisDay;
    WebCalendar.daysMonth[1] = (0==y%4 && (y%100!=0 || y%400==0)) ? 29 : 28;
    if (!(y<=9999 && y >= 1000 && parseInt(m, 10)>0 && parseInt(m, 10)<13 && parseInt(d, 10)>0)){
        alert("对不起,你输入了错误的日期!");
        WebCalendar.thisYear   = new Date().getFullYear();
        WebCalendar.thisMonth  = new Date().getMonth()+ 1;
        WebCalendar.thisDay    = new Date().getDate(); }
    y = WebCalendar.thisYear;
    m = WebCalendar.thisMonth;
    d = WebCalendar.thisDay;
   
    funYearSelect(parseInt(y, 10));
    funMonthSelect(parseInt(m,10));
    //WebCalendar.iframe.meizzYearHead.innerText  = y +" 年";
    //WebCalendar.iframe.meizzYearMonth.innerText = parseInt(m, 10) +" 月";
    WebCalendar.daysMonth[1] = (0==y%4 && (y%100!=0 || y%400==0)) ? 29 : 28; //闰年二月为29天
    var w = new Date(y, m-1, 1).getDay();
    var prevDays = m==1  ? WebCalendar.daysMonth[11] : WebCalendar.daysMonth[m-2];
    for(var i=(w-1); i>=0; i--) //这三个 for 循环为日历赋数据源(数组 WebCalendar.day)格式是 d/m/yyyy
    {
        WebCalendar.day[i] = prevDays +"/"+ (parseInt(m, 10)-1) +"/"+ y;
        if(m==1) WebCalendar.day[i] = prevDays +"/"+ 12 +"/"+ (parseInt(y, 10)-1);
        prevDays--;
    }
    for(var i=1; i<=WebCalendar.daysMonth[m-1]; i++) WebCalendar.day[i+w-1] = i +"/"+ m +"/"+ y;
    for(var i=1; i<WebCalendar.dayShow-w-WebCalendar.daysMonth[m-1]+1; i++)
    {
        WebCalendar.day[WebCalendar.daysMonth[m-1]+w-1+i] = i +"/"+ (parseInt(m, 10)+1) +"/"+ y;
        if(m==12) WebCalendar.day[WebCalendar.daysMonth[m-1]+w-1+i] = i +"/"+ 1 +"/"+ (parseInt(y, 10)+1);
    }
    for(var i=0; i<WebCalendar.dayShow; i++)    //这个循环是根据源数组写到日历里显示
    {
        var a = WebCalendar.day[i].split("/");
        WebCalendar.dayObj[i].innerText    = a[0];
        WebCalendar.dayObj[i].title        = a[2] +"-"+ appendZero(a[1]) +"-"+ appendZero(a[0]);
        WebCalendar.dayObj[i].bgColor      = WebCalendar.dayBgColor;
        WebCalendar.dayObj[i].style.color  = WebCalendar.wordColor;
        if ((i<10 && parseInt(WebCalendar.day[i], 10)>20) || (i>27 && parseInt(WebCalendar.day[i], 10)<12))
            WebCalendar.dayObj[i].style.color = WebCalendar.wordDark;
        if (WebCalendar.inputDate==WebCalendar.day[i])    //设置输入框里的日期在日历上的颜色
        {WebCalendar.dayObj[i].bgColor = WebCalendar.darkColor; WebCalendar.dayObj[i].style.color = WebCalendar.lightColor;}
        if (WebCalendar.day[i] == WebCalendar.today)      //设置今天在日历上反应出来的颜色
        {WebCalendar.dayObj[i].bgColor = WebCalendar.todayColor; WebCalendar.dayObj[i].style.color = WebCalendar.lightColor;}
    }
}
function returnDate() //根据日期格式等返回用户选定的日期
{
    if(WebCalendar.objExport)
    {
        var returnValue;
        var a = (arguments.length==0) ? WebCalendar.day[this.id.substr(8)].split("/") : arguments[0].split("/");
        var d = WebCalendar.format.match(/^(\w{4})(-|\/)(\w{1,2})\2(\w{1,2})$/);
        if(d==null){alert("你设定的日期输出格式不对!\r\n\r\n请重新定义 WebCalendar.format !"); return false;}
        var flag = d[3].length==2 || d[4].length==2; //判断返回的日期格式是否要补零
        returnValue = flag ? a[2] +d[2]+ appendZero(a[1]) +d[2]+ appendZero(a[0]) : a[2] +d[2]+ a[1] +d[2]+ a[0];
        if(WebCalendar.timeShow)
        {
            var h = new Date().getHours(), m = new Date().getMinutes(), s = new Date().getSeconds();
            returnValue += flag ? " "+ appendZero(h) +":"+ appendZero(m) +":"+ appendZero(s) : " "+  h  +":"+ m +":"+ s;
        }
        WebCalendar.objExport.value = returnValue;
        hiddenCalendar();
    }
}
//-->

posted @ 2008-11-25 19:17 wesley1987 阅读(780) | 评论 (1)编辑 收藏