??xml version="1.0" encoding="utf-8" standalone="yes"?> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) 2.1 在Web.xml中的配置 1) (tng) FilterToBeanProxy 2) filter-mapping 3) HttpSessionEventPublisher FilterChainProxy?x)按序来调用这些filter,使这些filter能n用Spring ioc的功? CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON定义?jin)url比较前先转ؓ(f)写Q?PATTERN_TYPE_APACHE_ANT定义?jin)用Apache ant的匹配模? 1) authenticationManager (tng) (tng) (tng) (tng) (tng) (tng) (tng) 每个认证者会(x)对自己指定的证明信息q行认证Q如DaoAuthenticationProvider仅对UsernamePasswordAuthenticationTokenq个证明信息q行认证?/p>
5) userCache & (tng) resourceCache
7) basicProcessingFilterEntryPoint 8) authenticationProcessingFilterEntryPoint 1) httpSessionContextIntegrationFilter
4Q?strong>exceptionTranslationFilter 5) authenticationProcessingFilter 6) filterInvocationInterceptor
(详见 2.6.3 资源权限定义扩展) 1) methodSecurityInterceptor 采用 http://jcaptcha.sourceforge.net (tng)作ؓ(f)通用的验证码Ҏ(gu)Q请参考SpringSide中的例子Q或|上的:(x) 差沙在此q程中又发现acegi logout filter的错误,q行?jin)修正?/p>
另外它默认提供的囄比较难认Q我们custom?jin)一个美观一点的版本?/p>
]]>
Acegi 的配|看h非常复杂,但事实上在实际项目的安全应用中我们ƈ不需要那么多功能,清楚的了(jin)解Acegi配置中各的功能Q有助于我们灉|的运用Acegi于实践中?/p>
Acegi通过实现?jin)Filter接口的FilterToBeanProxy提供一U特D的使用Servlet Filter的方式,它委托Spring中的Bean -- FilterChainProxy来完成过滤功能,q好处是化了(jin)web.xml的配|,q且充分利用?jin)Spring IOC的优ѝFilterChainProxy包含?jin)处理认证过E的filter列表Q每个filter都有各自的功能?/p>
(tng) (tng) <filter>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <filter-name>Acegi Filter Chain Proxy</filter-name>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <init-param>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <param-name>targetClass</param-name>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <param-value>org.acegisecurity.util.FilterChainProxy</param-value>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) </init-param>
(tng) (tng) (tng) </filter>
<filter-mapping>限定?jin)FilterToBeanProxy的URL匚w模式,只有*.do?.jsp?j_acegi_security_check 的请求才?x)受到权限控Ӟ对javascript,css{不限制?/p>
(tng) (tng) <filter-mapping>
(tng) (tng) (tng) (tng) (tng) <filter-name>Acegi Filter Chain Proxy</filter-name>
(tng) (tng) (tng) (tng) (tng) <url-pattern>*.do</url-pattern>
(tng) (tng) (tng) </filter-mapping>
(tng) (tng) (tng)
(tng) (tng) (tng) <filter-mapping>
(tng) (tng) (tng) (tng) (tng) <filter-name>Acegi Filter Chain Proxy</filter-name>
(tng) (tng) (tng) (tng) (tng) <url-pattern>*.jsp</url-pattern>
(tng) (tng) (tng) </filter-mapping>
(tng) (tng) (tng)
(tng) (tng) (tng) <filter-mapping>
(tng) (tng) (tng) (tng) (tng) <filter-name>Acegi Filter Chain Proxy</filter-name>
(tng) (tng) (tng) (tng) (tng) <url-pattern>/j_acegi_security_check</url-pattern>
</filter-mapping>
<listener>的HttpSessionEventPublisher用于发布HttpSessionApplicationEvents和HttpSessionDestroyedEvent事glspring的applicationcontext?/p>
(tng) (tng) (tng) <listener>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <listener-class>org.acegisecurity.ui.session.HttpSessionEventPublisher</listener-class>
(tng) (tng) (tng) </listener>
2.2 在applicationContext-acegi-security.xml?/h2>
2.2.1 FILTER CHAIN
<bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="filterInvocationDefinitionSource">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) PATTERN_TYPE_APACHE_ANT
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) /**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,
basicProcessingFilter,rememberMeProcessingFilter,anonymousProcessingFilter,
exceptionTranslationFilter,filterInvocationInterceptor
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) </value>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) </property>
(tng) (tng) (tng) </bean>2.2.2 基础认证
起到认证理的作用,它将验证的功能委托给多个ProviderQƈ通过遍历Providers, 以保证获取不同来源的w䆾认证Q若某个Provider能成功确认当前用L(fng)w䆾Qauthenticate()Ҏ(gu)?x)返回一个完整的包含用户授权信息的Authentication对象Q否则会(x)抛出一个AuthenticationException?br />Acegi提供?jin)不同的AuthenticationProvider的实?如:(x)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) DaoAuthenticationProvider 从数据库中读取用户信息验证n?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) AnonymousAuthenticationProvider 匿名用户w䆾认证
(tng) (tng) (tng) (tng) (tng) (tng) (tng) RememberMeAuthenticationProvider 已存cookie中的用户信息w䆾认证
(tng) (tng) (tng) (tng) (tng) (tng) (tng) AuthByAdapterProvider 使用容器的适配器验证n?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) CasAuthenticationProvider Ҏ(gu)Yale中心(j)认证服务验证?li)w䆾, 用于实现单点登陆
(tng) (tng) (tng) (tng) (tng) (tng) (tng) JaasAuthenticationProvider 从JASS登陆配置中获取用户信息验证n?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) RemoteAuthenticationProvider Ҏ(gu)q程服务验证用户w䆾
(tng) (tng) (tng) (tng) (tng) (tng) (tng) RunAsImplAuthenticationProvider 对n份已被管理器替换的用戯行验?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) X509AuthenticationProvider 从X509认证中获取用户信息验证n?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) TestingAuthenticationProvider 单元试时?/p>
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="providers">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <list>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <ref local="daoAuthenticationProvider"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <ref local="anonymousAuthenticationProvider"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <ref local="rememberMeAuthenticationProvider"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) </list>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) </property>
</bean>
2) daoAuthenticationProvider
q行单的Z数据库的w䆾验证。DaoAuthenticationProvider获取数据库中的̎号密码ƈq行匚wQ若成功则在通过用户w䆾的同时返回一个包含授权信息的Authentication对象Q否则n份验证失败,抛出一个AuthenticatiionException?/p>
(tng) (tng) (tng) <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="userDetailsService" ref="jdbcDaoImpl"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="userCache" ref="userCache"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="passwordEncoder" ref="passwordEncoder"/>
(tng) (tng) </bean>
3) passwordEncoder
使用加密器对用户输入的明文进行加密。Acegi提供?jin)三U加密器:
PlaintextPasswordEncoder—默认,不加密,q回明文.
ShaPasswordEncoder—哈希算?SHA)加密
Md5PasswordEncoder—消息摘?MD5)加密<bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"/>
4) jdbcDaoImpl
用于在数据中获取用户信息?acegi提供?jin)用户?qing)授权的表l构Q但是?zhn)也可以自己来实现。通过usersByUsernameQueryq个SQL得到你的(用户ID,密码,状态信?;通过authoritiesByUsernameQueryq个SQL得到你的(用户ID,授权信息) <bean id="jdbcDaoImpl" class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="dataSource" ref="dataSource"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="usersByUsernameQuery">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>select loginid,passwd,1 from users where loginid = ?</value>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) </property>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="authoritiesByUsernameQuery">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>select u.loginid,p.name from users u,roles r,permissions p,user_role ur,role_permis rp where u.id=ur.user_id and r.id=ur.role_id and p.id=rp.permis_id and
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) r.id=rp.role_id and p.status='1' and u.loginid=?</value>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) </property>
</bean>
~存用户和资源相对应的权限信息。每当请求一个受保护资源ӞdaoAuthenticationProvider׃(x)被调用以获取用户授权信息。如果每ơ都从数据库获取的话Q那代h(hun)很高Q对于不常改变的用户和资源信息来_(d)最好是把相x(chng)权信息缓存v来?详见 2.6.3 资源权限定义扩展 )
userCache提供?jin)两U实? NullUserCache和EhCacheBasedUserCache, NullUserCache实际上就是不q行M~存QEhCacheBasedUserCache是用Ehcache来实现缓功能?/p>
(tng) (tng) (tng) <bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="cacheManager" ref="cacheManager"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="cacheName" value="userCache"/>
(tng) (tng) (tng) </bean>
(tng) (tng) (tng) <bean id="userCache" class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache" autowire="byName">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="cache" ref="userCacheBackend"/>
(tng) (tng) (tng) </bean>
(tng) (tng) (tng) <bean id="resourceCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="cacheManager" ref="cacheManager"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="cacheName" value="resourceCache"/>
(tng) (tng) (tng) </bean>
(tng) (tng) (tng) <bean id="resourceCache" class="org.springside.modules.security.service.acegi.cache.ResourceCache" autowire="byName">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="cache" ref="resourceCacheBackend"/>
(tng) (tng) (tng) </bean>
6) basicProcessingFilter
用于处理HTTP头的认证信息Q如从Springq程协议(如Hessian和Burlap)或普通的览器如IE,Navigator的HTTP头中获取用户信息Q将他们转交l通过authenticationManager属性装配的认证理器。如果认证成功,?x)将一个Authentication对象攑ֈ?x)话中,否则Q如果认证失败,?x)将控制转交l认证入口点(通过authenticationEntryPoint属性装? (tng) (tng) (tng) <bean id="basicProcessingFilter" class="org.acegisecurity.ui.basicauth.BasicProcessingFilter">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="authenticationManager" ref="authenticationManager"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="authenticationEntryPoint" ref="basicProcessingFilterEntryPoint"/>
(tng) (tng) (tng) </bean>
通过向浏览器发送一个HTTP401(未授?消息Q提C用L(fng)录?br />处理ZHTTP的授权过E, 在当验证q程出现异常后的"d"Q通常实现转向、在response里加入error信息{功能?/p>
<bean id="basicProcessingFilterEntryPoint" class="org.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="realmName" value="SpringSide Realm"/>
</bean>
当抛出AccessDeniedExceptionӞ用户重定向到登录界面。属性loginFormUrl配置?jin)一个登录表单的URL,当需要用L(fng)录时QauthenticationProcessingFilterEntryPoint?x)将用户重定向到该URL <bean id="authenticationProcessingFilterEntryPoint" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="loginFormUrl">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>/security/login.jsp</value>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) </property>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="forceHttps" value="false"/>
</bean>2.2.3 HTTP安全h
每次request?HttpSessionContextIntegrationFilter从Session中获取Authentication对象Q在request完后, 又把Authentication对象保存到Session中供下次request使用,此filter必须其他Acegi filter前用,使之能跨多个请求?/p>
<bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter"></bean>
(tng) (tng) (tng) <bean id="httpRequestAccessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="allowIfAllAbstainDecisions" value="false"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="decisionVoters">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <list>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <ref bean="roleVoter"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) </list>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) </property>
</bean>
2) httpRequestAccessDecisionManager
l过投票机制来决定是否可以访问某一资源(URL或方?。allowIfAllAbstainDecisions为false时如果有一个或以上的decisionVoters投票通过,则授权通过。可选的决策机制有ConsensusBased和UnanimousBased (tng) (tng) (tng) <bean id="httpRequestAccessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="allowIfAllAbstainDecisions" value="false"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="decisionVoters">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <list>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <ref bean="roleVoter"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) </list>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) </property>
(tng) (tng) (tng) </bean>
3) roleVoter
(tng) 必须是以rolePrefix讑֮的value开头的权限才能q行投票,如AUTH_ , ROLE_ (tng) (tng) (tng) <bean id="roleVoter" class="org.acegisecurity.vote.RoleVoter">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="rolePrefix" value="AUTH_"/>
(tng) (tng) </bean>
异常转换qo(h)器,主要是处理AccessDeniedException和AuthenticationExceptionQ将l每个异常找到合适的"d" (tng) (tng) (tng) <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="authenticationEntryPoint" ref="authenticationProcessingFilterEntryPoint"/>
(tng) (tng) (tng) </bean>
和servlet spec差不?处理登陆h.当n份验证成功时QAuthenticationProcessingFilter?x)在会(x)话中放|一个Authentication对象Qƈ且重定向到登录成功页?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) authenticationFailureUrl定义登陆p|时{向的面
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) defaultTargetUrl定义登陆成功时{向的面
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) filterProcessesUrl定义登陆h的页?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) rememberMeServices用于在验证成功后dcookie信息 (tng) (tng) (tng) <bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="authenticationManager" ref="authenticationManager"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="authenticationFailureUrl">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>/security/login.jsp?login_error=1</value>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) </property>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="defaultTargetUrl">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>/admin/index.jsp</value>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) </property>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="filterProcessesUrl">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) <value>/j_acegi_security_check</value>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) </property>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="rememberMeServices" ref="rememberMeServices"/>
(tng) (tng) (tng) </bean>
在执行{向url前检查objectDefinitionSource中设定的用户权限信息。首先,objectDefinitionSource中定义了(jin)讉KURL需要的属性信?q里的属性信息仅仅是标志Q告诉accessDecisionManager要用哪些voter来投?。然后,authenticationManager掉用自己的provider来对用户的认证信息进行校验。最后,有投者根据用h有认证和讉Kurl需要的属性,调用自己的voter来投,军_是否允许讉K?/p>
(tng) (tng) (tng) <bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="authenticationManager" ref="authenticationManager"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="objectDefinitionSource" ref="filterDefinitionSource"/>
(tng) (tng) (tng) </bean>
7) filterDefinitionSource (详见 2.6.3 资源权限定义扩展)
自定义DBFilterInvocationDefinitionSource从数据库和cache中读取保护资源及(qing)光要的讉K权限信息 (tng)<bean id="filterDefinitionSource" class="org.springside.modules.security.service.acegi.DBFilterInvocationDefinitionSource">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="convertUrlToLowercaseBeforeComparison" value="true"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="useAntPath" value="true"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="acegiCacheManager" ref="acegiCacheManager"/>
</bean>2.2.4 Ҏ(gu)调用安全控制
在执行方法前q行拦截Q检查用h限信?br />2) methodDefinitionSource
自定义MethodDefinitionSource从cache中读取权?/p>
(tng) (tng) <bean id="methodSecurityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="authenticationManager" ref="authenticationManager"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="objectDefinitionSource" ref="methodDefinitionSource"/>
(tng) (tng) (tng) </bean>
(tng) (tng) (tng) <bean id="methodDefinitionSource" class="org.springside.modules.security.service.acegi.DBMethodDefinitionSource">
(tng) (tng) (tng) (tng) (tng) (tng) (tng) <property name="acegiCacheManager" ref="acegiCacheManager"/>
(tng) (tng) (tng) </bean>2.3 Jcaptcha验证?/h2>
http://www.coachthrasher.com/page/blog?entry=jcaptcha_with_appfuse?/p>
]]>
Subscriber Code: jLR8ZC-444-55-4467865481680090
Subscriber:www.1cn.biz
Subscriber Code: jLR8ZC-444-55-4467865481680090
]]>
相关内容QLocal, (tng)DataFormat, (tng)MessageFormat, (tng)SimpleDateFormat, (tng)Format
---------------------------------------------------------------
java.text.NumberFormatcL三个Ҏ(gu)可以产生下列数据的标准格式化器:(x)
数字
货币
癑ֈ?br />
---------------------------------------------------------------
创徏格式化器(默认地区Local格式)Q?br />NumberFormat.getNumberInstance();
NumberFormat.getCurrencyInstance();
NumberFormat.getPercentInstance();
---------------------------------------------------------------
例题Q?br />double (tng)dbl=10000.0/3;
NumberFormat (tng)formatter=NumberFormat.getNumberInstance();
String (tng)s=formatter.format(x);
System.out.println(s);
---------------------------------------------------------------
讑֮整数或小数部分所昄的最和最多位敎ͼ可以使用NumberFormatc?br />的方法:(x)
setMinimumIntegerDigits(int)
setMinimumFractionDigits(int)
setMaximumIntegerDigits(int)
setMaximumFractionDigits(int)
讑֮数部分的最多位很有用处。如果小数部分丢qW一位数字大于等?Q?br />那么昄的最后一位会(x)?Q四舍五入)(j)。如果要昄N的零Q可以把数部分的最位{于最多位?br />如果不想昄Q可以把数部分的最位讑֮?或不讑֮?br />
指定最多位整数相当危险Q显C值将?x)被截断Q生一个错误的倹{?br />
---------------------------------------------------------------
试例题Q?br />
文g名TestNumberFormat.java
--------------------------------------------------------
import (tng)java.text.NumberFormat;
public (tng)class (tng)TestNumberFormat
{
(tng) (tng) (tng) (tng)public (tng)static (tng)void (tng)main(String[] (tng)args) (tng){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)NumberFormat (tng)nFormat=NumberFormat.getNumberInstance();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)nFormat.setMinimumIntegerDigits(3);//讄整数部分臛_??br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)nFormat.setMaximumFractionDigits(5);//讄数点后面尾Cؓ(f)5
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println("Format (tng)Out (tng)3.2128345="+nFormat.format(3.2128345));
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)NumberFormat (tng)cFormat=NumberFormat.getCurrencyInstance();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)cFormat.setMaximumFractionDigits(3);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println("Format (tng)Out (tng)321283.47656="+cFormat.format(321283.47656));
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)NumberFormat (tng)pFormat=NumberFormat.getPercentInstance();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)pFormat.setMaximumFractionDigits(4);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println("Format (tng)Out (tng)3.2128345="+pFormat.format(3.2128345));
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println("Format (tng)Out (tng)null="+nFormat.format(null));//参数是null,出现异常
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)//Throws (tng) (tng)I(yng)llegalArgumentException
(tng) (tng) (tng) (tng)}
}
//================= (tng)q行l果如下 (tng)=======================
Format (tng)Out (tng)3.2128345=003.21283
Format (tng)Out (tng)321283.47656=K?21,283.477
Format (tng)Out (tng)3.2128345=321.2834%
Exception (tng)in (tng)thread (tng)"main" (tng)java.lang
]]>
其实(zhn)也可以完全不用配|文Ӟ而是在代码中配置Log4j环境。但是,使用配置文g(zhn)的应用E序更加灉|。Log4j支持两种配置文g格式Q一U是XML格式的文Ӟ一U是JavaҎ(gu)文Ӟ?|(j)。下面我们介l用JavaҎ(gu)文件做为配|文件的Ҏ(gu)Q?/p>
1.配置根LoggerQ其语法为:(x)
log4j.rootLogger = [ level ] , appenderName, appenderName, ?
其中Qlevel 是日志记录的优先U,分ؓ(f)OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者?zhn)定义的别。Log4j只用四个别,优先U从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的U别Q?zhn)可以控制到应用程序中相应U别的日志信息的开兟뀂比如在q里定义?jin)INFOU别Q则应用E序中所有DEBUGU别的日志信息将不被打印出来?appenderName是指定日志信息输出到哪个地斏V?zhn)可以同时指定多个输出目的地?
2.配置日志信息输出目的地AppenderQ其语法为:(x)
log4j.appender.appenderName = fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1 = value1
?
log4j.appender.appenderName.option = valueN
其中QLog4j提供的appender有以下几U:(x)
org.apache.log4j.ConsoleAppenderQ控制台Q,
org.apache.log4j.FileAppenderQ文Ӟ(j)Q?
org.apache.log4j.DailyRollingFileAppenderQ每天生一个日志文Ӟ(j)Q?br /> org.apache.log4j.RollingFileAppenderQ文件大到达指定尺寸的时候生一个新的文Ӟ(j)Q?
org.apache.log4j.WriterAppenderQ将日志信息以流格式发送到L指定的地方)(j)
3.配置日志信息的格式(布局Q,其语法ؓ(f)Q?/p>
log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1 = value1
?
log4j.appender.appenderName.layout.option = valueN
其中QLog4j提供的layout有以下几U:(x)
org.apache.log4j.HTMLLayoutQ以HTML表格形式布局Q,
org.apache.log4j.PatternLayoutQ可以灵zd指定布局模式Q,
org.apache.log4j.SimpleLayoutQ包含日志信息的U别和信息字W串Q,
org.apache.log4j.TTCCLayoutQ包含日志生的旉、线E、类别等{信息)(j)
Log4J采用cMC语言中的printf函数的打印格式格式化日志信息Q打印参数如下:(x) %m 输出代码中指定的消息
%p 输出优先U,即DEBUGQINFOQW(xu)ARNQERRORQFATAL
%r 输出自应用启动到输出该log信息耗费的毫U数
%c 输出所属的cȝQ通常是所在类的全?
%t 输出产生该日志事件的U程?
%n 输出一个回车换行符QW(xu)indowsq_为“\r\n”,Unixq_为“\n?
%d 输出日志旉点的日期或时_(d)默认格式为ISO8601Q也可以在其后指定格式,比如Q?d{yyy MMM dd HH:mm:ss,SSS}Q输出类|(x)2002q?0?8?22Q?0Q?8Q?21
%l 输出日志事g的发生位|,包括cȝ名、发生的U程Q以?qing)在代码中的行数。D例:(x)Testlog4.main(TestLog4.java:10)
二、在代码中用Log4j
1.得到记录?/p>
使用Log4jQ第一步就是获取日志记录器Q这个记录器负责控制日志信息。其语法为:(x)
public static Logger getLogger( String name)
通过指定的名字获得记录器Q如果必要的话,则ؓ(f)q个名字创徏一个新的记录器。Name一般取本类的名字,比如Q?
static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () )
2.d配置文g
当获得了(jin)日志记录器之后,W二步将配置Log4j环境Q其语法为:(x)
BasicConfigurator.configure ()Q?自动快速地使用~省Log4j环境?br /> PropertyConfigurator.configure ( String configFilename) Q读取用Java的特性文件编写的配置文g?br /> DOMConfigurator.configure ( String filename ) Q读取XML形式的配|文件?/p>
3.插入记录信息Q格式化日志信息Q?/p>
当上两个必要步骤执行完毕Q?zhn)可以轻村֜使用不同优先U别的日志记录语句插入到(zhn)想记录日志的Q何地方,其语法如下:(x)
Logger.debug ( Object message ) ;
Logger.info ( Object message ) ;
Logger.warn ( Object message ) ;
Logger.error ( Object message ) ;
本demo既适合于JSF + Spring2.0.1 + Hibernate3.2 目也适合于Struts + Spring2.0.1 + Hibernate3.2目Q?br />
未列入特别说明没有授权的企业和个人都可以自由免费下蝲使用提供宝贵意见Q?br />
本h不急功q利Q正在做完整的文编写,做最后严格的试Q近期在此免费发布,敬请x(chng)Q?/p>
(tng) |
(tng)var strm = document.myform.CoMail.value (tng) (tng) //提交mail地址的文本框 (tng)var regm = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;//验证Mail的正则表辑ּ,^[a-zA-Z0-9_-]:开头必Mؓ(f)字母,下划U?数字, (tng)if (!strm.match(regm) && strm!="") (tng) (tng) { (tng) (tng) (tng) (tng) alert("邮箱地址格式错误或含有非法字W?\nh查!"); (tng) (tng)document.myform.CoMail.select(); (tng) (tng) (tng) (tng)return false; (tng) (tng) (tng) } |