君子博学而日参省乎己 则知明而行无过矣

博客园 首页 新随笔 联系 订阅 管理
  240 Posts :: 5 Stories :: 12 Comments :: 0 Trackbacks

公告

2012年5月24日 #

这里笔者介绍一种很常用,也比较专业的权限控制思路。这里用java语言描述,其实都差不多的。要换成其他的语言主,自己转一下就可以了。为了方便起见,我们这里定义a^b为:a的b次方。这里,我们为每一个操作设定一个唯一的整数值,比如: 

        删除A---0 
        修改A---1 
        添加A---2 

        删除B---3 
        修改B---4 
        添加B---5 

  理论上可以有N个操作,这取决于你用于储存用户权限值的数据类型了。 
  这样,如果用户有权限:添加A---2;删除B---3;修改B---4。那用户的权限值 purview =2^2+2^3+2^4=28,也就是2的权的和了。化成二进制可以表示为11100。这样,如果要验证用户是否有删除B的权限,就可以通过位与运算来实现。在Java里,位与运算运算符号为&,即是: 

        int value = purview &((int)Math.pow(2,3)); 

  你会发现,当用户有操作权限时,运算出来的结果都会等于这个操作需要的权限值! 

  原理: 

  位与运算,顾名思义就是对位进行与运算: 
  以上面的式子为例:purview & 2^3 也就是 28&8 
  将它们化成二进制有 
     11100 
        & 01000 
        ------------------- 
     01000 == 8(十进制) == 2^3 

  同理,如果要验证是否有删除A---0的权限 
  可以用:purview &((int)Math.pow(2,0)); 
  即: 
    11100 
        & 00001 
        ------------------------ 
    00000 == 0(十进制)  != 2^0 

  这种算法的一个优点是速度快。可以同时处理N个权限。如果想验证是否同时有删除A---0和删除B---3的权限,可以用purview&(2^0+2^3)==(2^0+2^3)?true:false;设置多角色用户。根据权限值判断用户的角色。 
  
        下面提供一个java的单操作权限判断的代码:

Java代码  收藏代码
  1. //userPurview是用户具有的总权限   
  2.   
  3. //optPurview是一个操作要求的权限为一个整数(没有经过权的!)   
  4.   
  5. public static boolean checkPower(int userPurview, int optPurview){   
  6.   
  7.     int purviewValue = (int)Math.pow(2, optPurview);   
  8.   
  9.     return (userPurview & purviewValue) == purviewValue;   
  10. }   

 当然,多权限的验证只要扩展一下就可以了。 
       几点注意事项:首先,一个系统可能有很多的操作,因此,请建立数据字典,以便查阅,修改时使用。其次,如果用数据库储存用户权限,请注意数值的有效范围。操作权限值请用唯一的整数!

posted @ 2012-05-24 05:52 刺猬的温驯 阅读(24) 评论(0) 编辑

2012年5月21日 #

摘要: 之前我们使用的是HibernateTemplate来进行对象的持久化的,其实在DAO实现类中我们还可以使用Hibernate的上下文Session来持久化对象。也就是通过SessionFactory对象的getCurrentSession()对象来获得Session,然后通过Session来进行操作。 我们调整一下代码:Java代码packageorg.ourpioneer.course.dao;importjava.util.List;importorg.hibernate.Query;importorg.hibernate.SessionFactory;importorg.ourpione阅读全文
posted @ 2012-05-21 09:42 刺猬的温驯 阅读(10) 评论(0) 编辑

今天看Alef Arendsen的一篇blog。一点收获! 
http://blog.interface21.com/main/2007/06/26/so-should-you-still-use-springs-hibernatetemplate-andor-jpatemplate/ 

在spring2.0之前,我们在使用hibernate和spring的时候,都会被HibernateTemplate为我们提供 benefits(资源和事务管理以及把那个“丑陋”的checked exception转换为runtime exception-DataAccessException )而折服,在项目中不由自主、不假思索地使用它和那个经典的callback方法。而如今,hibernate3.0.1+ 、spring 2.0+版本以后,我们可以在数据访问层直接使用hinberate的session API(例如SessionFactory.getCurrentSession),不并担心session和transaction management。至于error handling可以通过spring的@Repository annotation和post processor-PersistenceExceptionTranslationPostProcessor来解决。让我们来看一些代码片段: 
配置文件片段: 
Java代码  收藏代码
  1. <bean id="sessionFactory" class="org.springframework.orm.hibernate3.  
  2. LocalSessionFactoryBean">  
  3. <!-- the properties setting-->  
  4. </bean>  
  5.    
  6. <bean id="accountRepo" class="com.mycompany.HibernateAccountRepository">  
  7. <constructor-arg ref="sessionFactory"></constructor-arg>  
  8. </bean>  
  9. <bean class="org.springframework.dao.annotation. PersistenceExceptionTranslationPostProcessor"/>  


数据访问层代码片段: 
Java代码  收藏代码
  1. @Repository  
  2. public class HibernateAccountRepository implements AccountRepository {  
  3.    
  4. private SessionFactory factory;  
  5.    
  6. public HibernateAccountRepository(SessionFactory factory) {  
  7. this.factory = factory;  
  8. }  
  9.    
  10. public Account loadAccount(String username) {  
  11. return (Account)factory.getCurrentSession()  
  12. .createQuery("from Account acc where acc.name = :name")  
  13. .setParameter("name", "thethirdpart").uniqueResult();  
  14. }  
  15. }  


在xml配置文件里面通过配置的post processor会自动检测@Repository标注的bean并为该bean打开exception转换功能。 

如果不支持annotations,可以通过AOP来实现,更方便 
Java代码  收藏代码
  1. <bean id=“persistenceExceptionInterceptor”  
  2. class=“org.springframework.dao.support.PersistenceExceptionTranslationInterceptor”/>  
  3. <aop:config>  
  4.     <aop:advisor pointcut=“execution(* *..*Repository+.*(..))”  
  5.                           advice-ref=“persistenceExceptionInterceptor” />  
  6. </aop:config>  



总结,我们应该选择哪种方式呢?还是那句话,根据不同的情况来做最正确的选择。但我建议是丢弃template,而直接使用hibernate的API,毕竟灵活性更大,更何况遇到复杂的情况我们始终得面对hibernate的API。spring并不强制你做任何事情,记得它是一个非侵入性的framework。
posted @ 2012-05-21 09:40 刺猬的温驯 阅读(16) 评论(0) 编辑

2012年5月17日 #

package org.springframework.web.servlet.theme;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.util.WebUtils;

/**
 * Implementation of ThemeResolver that uses a cookie sent back to the user
 * in case of a custom setting, with a fallback to the fixed locale.
 * This is especially useful for stateless applications without user sessions.
 *
 * <p>Custom controllers can thus override the user's theme by calling setTheme,
 * e.g. responding to a certain theme change request.
 *
 * 
@author Jean-Pierre Pawlak
 * 
@author Juergen Hoeller
 * 
@since 17.06.2003
 
*/
public class CookieThemeResolver extends AbstractThemeResolver {

    /**
     * Name of the request attribute that holds the theme name. Only used
     * for overriding a cookie value if the theme has been changed in the
     * course of the current request! Use RequestContext.getTheme() to
     * retrieve the current theme in controllers or views.
     * 
@see org.springframework.web.servlet.support.RequestContext#getTheme
     
*/
    public static final String THEME_REQUEST_ATTRIBUTE_NAME = CookieThemeResolver.class.getName() + ".THEME";

    public static final String DEFAULT_COOKIE_NAME = CookieThemeResolver.class.getName() + ".THEME";

    public static final String DEFAULT_COOKIE_PATH = "/";

    public static final int DEFAULT_COOKIE_MAX_AGE = Integer.MAX_VALUE;

    private String cookieName = DEFAULT_COOKIE_NAME;

    private int cookieMaxAge = DEFAULT_COOKIE_MAX_AGE;

    private String cookiePath = DEFAULT_COOKIE_PATH;
    
    /**
     * Use the given name for theme cookies, containing the theme name.
     
*/
    public void setCookieName(String cookieName) {
        this.cookieName = cookieName;
    }

    public String getCookieName() {
        return cookieName;
    }

    /**
     * Use the given path for theme cookies.
     * The cookie is only visible for URLs in the path and below. 
     
*/
    public String getCookiePath() {
        return cookiePath;
    }

    public void setCookiePath(String cookiePath) {
        this.cookiePath = cookiePath;
    }

    /**
     * Use the given maximum age, specified in seconds, for locale cookies.
     * Useful special value: -1 ... not persistent, deleted when client shuts down
     
*/
    public void setCookieMaxAge(int cookieMaxAge) {
        this.cookieMaxAge = cookieMaxAge;
    }

    public int getCookieMaxAge() {
        return cookieMaxAge;
    }

    public String resolveThemeName(HttpServletRequest request) {
        // check theme for preparsed resp. preset theme
        String theme = (String) request.getAttribute(THEME_REQUEST_ATTRIBUTE_NAME);
        if (theme != null)
            return theme;

        // retrieve cookie value
        Cookie cookie = WebUtils.getCookie(request, getCookieName());

        if (cookie != null) {
            return cookie.getValue();
        }

        // fallback
        return getDefaultThemeName();
    }

    public void setThemeName(HttpServletRequest request, HttpServletResponse response, String themeName) {
        Cookie cookie = null;
        if (themeName != null) {
            // set request attribute and add cookie
            request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, themeName);
            cookie = new Cookie(getCookieName(), themeName);
            cookie.setMaxAge(getCookieMaxAge());
            cookie.setPath(cookiePath);
        }
        else {
            // set request attribute to fallback theme and remove cookie
            request.setAttribute(THEME_REQUEST_ATTRIBUTE_NAME, getDefaultThemeName());
            cookie = new Cookie(getCookieName(), "");
            cookie.setMaxAge(0);
            cookie.setPath(cookiePath);
        }
        response.addCookie(cookie);
    }

}
posted @ 2012-05-17 21:36 刺猬的温驯 阅读(9) 评论(0) 编辑

在写iframe完成长连接获取上传状态的时候,有两次请求,一次上传,一次获取状态的。 

发现第一次上传上传的请求和获取状态的请求是不同的session,再次上传时就没问题了。 

找了资料,都说是放jsessionid,或者加P3P头信息。这些都不是我现在的真正问题。 

在google的bug工具中,看到原因了。 
我的iframe写得是 
<iframe name="upload${inputName}" src="" id="upload${inputName}" style="display:none"> 
</iframe> 



这个时候,src虽然什么都没写,但是它还是请求了一次 
GET about:blank HTTP/1.1 

User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.874.121 Safari/535.2 

Referer: http://127.0.0.1:8080/cgodo-fileupload/fileUploadComponent?key=1322999139092file&inputName=file

,再上传的时候,iframe 
请求的cookie中并没有发送jsessionid过去 
POST /cgodo-fileupload/doUpload.html?key=1322999245171file HTTP/1.1 
Cookie: OFBiz.Visitor=10360 

这是因为iframe初始化的时候,src是空,它的cookie中没有信息,发送请求过去的时候cookie自然就没有jessionid信息了。服务器就创建了新的session。 

而第一次上传完毕后,从服务器中获取到了一个session,所以第二次上传,读取状态的和上传文件的两次请求就是同一个session了。 

解决方案 
在iframe中,请求一次我们应用中数据最少的一个链接,这样就能生成session了。 
我这里使用的是springmvc,写了一个什么都不输出的action。这个action一定要确保把session创建好。 
/** 

* 描述:为iframe生成sessionid 

* @param locale 
* @return 
* @author liyixing 2011-12-4 下午07:39:43 
*/ 
@ResponseBody 
@RequestMapping("/fileUploadSessionId") 
public String fileUploadSessionId(HttpServletRequest request) { 
request.getSession(true); 

return null; 


然后让iframe初始化的时候访问这个链接。
posted @ 2012-05-17 06:30 刺猬的温驯 阅读(52) 评论(0) 编辑

摘要: LocaleSpring MVC缺省使用AcceptHeaderLocaleResolver来根据request header中的 Accept-Language 来确定访客的local。对于前端jsp页面上,spring提供了标签<spring:message>来提供从resource文件中获取的文字的动态加载功能。例如修改servlet context xml文件中的messageSource部分,增加对多国语言message的code resource的引入。Xml代码<beanid="messageSource"class="org.sp阅读全文
posted @ 2012-05-17 04:24 刺猬的温驯 阅读(43) 评论(0) 编辑

Servlet中的输入参数为都是string类型,而spring mvc通过data bind机制将这些string 类型的输入参数转换为相应的command object(根据view和controller之间传输数据的具体逻辑,也可称为model attributes, domain model objects)。在这个转换过程中,spring实际是先利用java.beans.PropertyEditor中的 setAdText方法来把string格式的输入转换为bean属性, 
亦可通过继承java.beans.PropertyEditorSupport来实现自定义的PropertyEditors,具体实现方式可参考spring reference 3.0.5 第 5.4节中的 Registering additional custom PropertyEditors部分。 
自定义完毕propertyEditor后,有以下几种方式来注册自定义的customer propertyEditor. 
1:直接将自定义的propertyEditor放到需要处理的java bean相同的目录下 
名称和java Bean相同但后面带Editor后缀。 
例如需要转换的java bean 名为User,则在相同的包中存在UserEditor类可实现customer propertyEditor的自动注册。 
2:利用@InitBinder来注册customer propertyEditor 
这个在之前的笔记中已经介绍过了,即在controller类中增加一个使用@InitBinder标注的方法,在其中注册customer Editor 
Java代码  收藏代码
  1. @InitBinder  
  2. public void initBinder(WebDataBinder binder) {  
  3.     SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");  
  4.     dateFormat.setLenient(false);  
  5.     binder.registerCustomEditor(Date.classnew CustomDateEditor(  
  6.             dateFormat, false));  
  7. }  

3:继承 WebBindingInitializer 接口来实现全局注册 
使用@InitBinder只能对特定的controller类生效,为注册一个全局的customer Editor,可以实现接口WebBindingInitializer 。 
Java代码  收藏代码
  1. public class CustomerBinding implements WebBindingInitializer {  
  2.     @Override  
  3.     public void initBinder(WebDataBinder binder, WebRequest request) {  
  4.         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");  
  5.         dateFormat.setLenient(false);  
  6.         binder.registerCustomEditor(Date.classnew CustomDateEditor(  
  7.                 dateFormat, false));  
  8.   
  9.     }  

并修改 servlet context xml配置文件 
Xml代码  收藏代码
  1. <bean  
  2.         class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">  
  3.         <property name="webBindingInitializer">  
  4.             <bean  
  5.                 class="net.zhepu.web.customerBinding.CustomerBinding" />  
  6.         </property>  
  7.     </bean>  

但这样一来就无法使用mvc:annotation-driven  了。 

使用conversion-service来注册自定义的converter 
DataBinder实现了PropertyEditorRegistry, TypeConverter这两个interface,而在spring mvc实际处理时,返回值都是return binder.convertIfNecessary(见HandlerMethodInvoker中的具体处理逻辑)。因此可以使用customer conversionService来实现自定义的类型转换。 

Xml代码  收藏代码
  1. <bean id="conversionService"  
  2. class="org.springframework.format.support.FormattingConversionServiceFactoryBean">  
  3.   
  4. <property name="converters">  
  5.     <list>  
  6.         <bean class="net.zhepu.web.customerBinding.CustomerConverter" />  
  7.     </list>  
  8. </property>  
  9.   
  10. lt;/bean>  


需要修改spring service context xml配置文件中的annotation-driven,增加属性conversion-service指向新增的conversionService bean。 

Xml代码  收藏代码
  1. <mvc:annotation-driven validator="validator"  
  2.     conversion-service="conversionService" />  


实际自定义的converter如下。 
Java代码  收藏代码
  1. public class CustomerConverter implements Converter<String, Date> {  
  2. @Override  
  3. public Date convert(String source) {  
  4.     SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");  
  5.     dateFormat.setLenient(false);  
  6.     try {  
  7.         return dateFormat.parse(source);  
  8.     } catch (ParseException e) {  
  9.         // TODO Auto-generated catch block  
  10.         e.printStackTrace();  
  11.     }         
  12.     return null;  
  13. }  


对于requestBody或httpEntity中数据的类型转换 
Spring MVC中对于requestBody中发送的数据转换不是通过databind来实现,而是使用HttpMessageConverter来实现具体的类型转换。 
例如,之前提到的json格式的输入,在将json格式的输入转换为具体的model的过程中,spring mvc首先找出request header中的contenttype,再遍历当前所注册的所有的HttpMessageConverter子类, 根据子类中的canRead()方法来决定调用哪个具体的子类来实现对requestBody中的数据的解析。如果当前所注册的httpMessageConverter中都无法解析对应contexttype类型,则抛出HttpMediaTypeNotSupportedException (http 415错误)。 
那么需要如何注册自定义的messageConverter呢,很不幸,在spring 3.0.5中如果使用annotation-driven的配置方式的话,无法实现自定义的messageConverter的配置,必须老老实实的自己定义AnnotationMethodHandlerAdapter的bean定义,再设置其messageConverters以注册自定义的messageConverter。 
在3.1版本中,将增加annotation-driven对自定义的messageConverter的支持 (SPR-7504),具体格式如下 
Xml代码  收藏代码
  1. <mvc:annotation-driven>  
  2.     <mvc:message-converters>  
  3.         <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>  
  4.         <bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>  
  5.         <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>  
  6.     </mvc:message-converters>  
  7. </mvc:annotation-driven>  
posted @ 2012-05-17 02:47 刺猬的温驯 阅读(18) 评论(0) 编辑

2012年5月16日 #

延迟加载过滤器 

Hibernate 允许对关联对象、属性进行延迟加载,但是必须保证延迟加载的操作限于同一个 Hibernate Session 范围之内进行。如果 Service 层返回一个启用了延迟加载功能的领域对象给 Web 层,当 Web 层访问到那些需要延迟加载的数据时,由于加载领域对象的 Hibernate Session 已经关闭,这些导致延迟加载数据的访问异常。 

Spring 为此专门提供了一个 OpenSessionInViewFilter 过滤器,它的主要功能是使每个请求过程绑定一个 Hibernate Session,即使最初的事务已经完成了,也可以在 Web 层进行延迟加载的操作。 

OpenSessionInViewFilter 过滤器将 Hibernate Session 绑定到请求线程中,它将自动被 Spring 的事务管理器探测到。所以 OpenSessionInViewFilter 适用于 Service 层使用HibernateTransactionManager 或 JtaTransactionManager 进行事务管理的环境,也可以用于非事务只读的数据操作中。 

要启用这个过滤器,必须在 web.xml 中对此进行配置: 

… 
<filter> 
    <filter-name>hibernateFilter</filter-name> 
    <filter-class> 
    org.springframework.orm.hibernate3.support.OpenSessionInViewFilter 
    </filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>hibernateFilter</filter-name> 
    <url-pattern>*.html</url-pattern> 
</filter-mapping> 
… 

上面的配置,我们假设使用 .html 的后缀作为 Web 框架的 URL 匹配模式,如果您使用 Struts 等 Web 框架,可以将其改为对应的“*.do”模型。 

OpenSessionInViewFilter是Spring提供的一个针对Hibernate的支持类,其主要意思是:当发起一个页面请求时,打开 Hibernate的Session,并一直保持住这个Session,直到这个请求结束。具体是通过一个Filter来实现的。 
假设在你的应用中Hibernate是通过spring来管理它的session.如果在你的应用中没有使用OpenSessionInViewFilter或者OpenSessionInViewInterceptor。session会在transaction结束后关闭。 
如果你采用了spring的声明式事务模式,它会对你的被代理对象的每一个方法进行事务包装(AOP的方式)。如下: 
<bean id="txProxyTemplate" abstract="true" 
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> 
        <property name="transactionManager" ref="transactionManager"/> 
        <property name="transactionAttributes"> 
            <props> 
                <prop key="save*">PROPAGATION_REQUIRED</prop> 
                <prop key="remove*">PROPAGATION_REQUIRED</prop> 
                <prop key="*">PROPAGATION_REQUIRED,readOnly</prop> 
            </props> 
        </property> 
    </bean> 
    <bean id="manager" parent="txProxyTemplate"> 
        <property name="target"> 
            <bean class="org.appfuse.service.impl.BaseManager"> 
                <property name="dao" ref="dao"/> 
            </bean> 
        </property> 
    </bean> 
目标类org.appfuse.service.impl.BaseManager 的  save *方法的事务类型PROPAGATION_REQUIRED  ,remove* 方法的事务类型PROPAGATION_REQUIRED 
其他的方法的事务类型是PROPAGATION_REQUIRED,readOnly。 
所以给你的感觉是调用这个名为“manager”的bean的方法之后session就关掉了。 
如果应用中使用了OpenSessionInViewFilter或者OpenSessionInViewInterceptor,所有打开的session会被保存在一个线程变量里。在线程退出前通过 
OpenSessionInViewFilter或者OpenSessionInViewInterceptor断开这些session。 为什么这么做?这主要是为了实现Hibernate的延迟加载功能。基于一个请求一个hibernate session的原则。
 
spring中对OpenSessionInViewFilter的描述如下: 
它是一个Servlet2.3过滤器,用来把一个Hibernate Session和一次完整的请求过程对应的线程相绑定。目的是为了实现"Open Session in View"的模式。 
例如: 它允许在事务提交之后延迟加载显示所需要的对象。 
这个过滤器和 HibernateInterceptor 有点类似:它是通过线程实现的。无论是没有事务的应用,还是有业务层事务的应用(通过HibernateTransactionManager 或 
JtaTransactionManager的方式实现)它都适用。在后一种情况下,事务会自动采用由这个filter绑定的Session来进行相关的操作以及根据实际情况完成提交操作。 
警告: 如果在你的应用中,一次请求的过程中使用了单一的一个HIbernate Session,在这种情况下,采用这个filter会产生一些以前没遇到的问题。特别需要注意的是通过 
Hibernate Session重新组织持久化对象之间关系的相关操作需要在请求的最开始进行。以免与已经加载的相同对象发生冲突。 
或者,我们可以通过指定"singleSession"="false"的方式把这个过滤器调到延期关闭模式。这样在一次请求的过程中不会使用一个单一的Session.每一次数据访问或事务相关 
操作都使用属于它自己的session(有点像不使用Open Session in View).这些session都被注册成延迟关闭模式,即使是在这一次的请求中它相关操作已经完成。 
"一次请求一个session" 对于一级缓存而言很有效,但是这样可以带来副作用。例如在saveOrUpdate的时候或事物回滚之后,虽然它和“no Open Session in View”同样安全。 
但是它却允许延迟加载。 
它会在spring的web应用的上下文根中查找Session工厂。它也支持通过在web.xml中定义的“SessionFactoryBeanName”的init-param元素 指定的Session工厂对应的bean的 
名字来查找session工厂。默认的bean的名字是"sessionFactory".他通过每一次请求查找一次SessionFactory的方式来避免由初始化顺序引起的问题(当使用ContextLoaderServlet 
来集成spring的时候 ,spring 的应用上下文是在这个filter 之后才被初始化的)。 
默认的情况下,这个filter 不会同步Hibernate Session.这是因为它认为这项工作是通过业务层的事务来完成的。而且HibernateAccessors 的FlushMode为FLUSH_EAGER.如果你 
想让这个filter在请求完成以后同步session.你需要覆盖它的closeSession方法,在这个方法中在调用父类的关闭session操作之前同步session.此外你需要覆盖它的getSession() 
方法。返回一个session它的FlushMode 不是默认的FlushMode.NEVER。需要注意的是getSession()和closeSession()方法只有在single session的模式中才被调用。 
在myfaces的wiki里提供了OpenSessionInViewFilter的一个子类如下: 
public class OpenSessionInViewFilter extends org.springframework.orm.hibernate3.support.OpenSessionInViewFilter { 
       
        /** 
         * we do a different flushmode than in the codebase 
         * here 
         */ 
        protected Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException { 
                Session session = SessionFactoryUtils.getSession(sessionFactory, true); 
                session.setFlushMode(FlushMode.COMMIT); 
                return session; 
        } 
        /** 
         * we do an explicit flush here just in case 
         * we do not have an automated flush 
         */ 
        protected void closeSession(Session session, SessionFactory factory) { 
                session.flush(); 
                super.closeSession(session, factory); 
        } 

posted @ 2012-05-16 21:02 刺猬的温驯 阅读(31) 评论(0) 编辑

1、通过继承JDK 中的 java.beans.PropertyEditorSupport 类来实现自己的编辑器类 ,该类用于实现将String 类型转换成您需要的数据类型。然后我们只需要在Spring 的容器中对这个编辑器进行有效的“注册”便可以实现Spring 在装配Bean 时自动的将String 类型转换成我们自定义的类型。


如何编辑自己的PropertyEditor,其实需要了解一点java.beans包的知识,在该包中,有一个 java.beans.PropertyEditor的接口,它定义了一套接口方法(12个),即通过这些方法如何将一个String变成内部的一个对 象,这两个方法是比较重要的: 
     a)setValue(Object value) 直接设置一个对象
     b)setAsText(String text) 通过一个字符串来构造对象,一般在此方法中解析字符串,将构造一个类对象,调用setValue(Object)来完成属性对象设置操作。 
  
  2)实现所有的接口方法是麻烦的,java.beans.PropertyEditorSupport 适时登场,一般情况下,我们通过扩展这个方便类即可。


2、CustomEditorConfigurer 类 用于实现在Spring 中注册自己定义的编辑器 。它是Spring 当中一个非常有用的工厂后处理类(工厂后处理通过Spring 的BeanFactoryPostProcessor 接口实现, 它是在Spring 容器启动并初始化之后进行对Spring 容器的操作类)。在Spring 中已经注册了不少编辑器类,他们都用于String 类型转换为其他的数据类型,如URL,Date等。


配置CustomEditorConfigurer 类:

      CustomEditorConfigurer 类中有一个customEditor属性,它是一个Map 类型。通过配置它便实现了自定义的编辑器注册。这个Map 的键值对对应着转换类型和编辑器(转换类型是Key,编辑器是Value)。


自定义编辑器可以简化Spring 的装配Bean。使其更加的简单。不容易发生配置错误。 PS:如果使用Spring 的ApplicationContext容器,那么只需在Spring 的配置文件中进行简单的装配,而对于Bean 工厂可能需要手动的注册才能使用。

 

Java代码  收藏代码
  1. //User.java  
  2.   
  3. public class User {  
  4.    private String name;  
  5.    private int age;  
  6.    。。。  
  7. }  
 
Java代码  收藏代码
  1. //用到User的类:UserContainer.java  
  2.   
  3. public class UserContainer {  
  4.   
  5. private User user;  
  6.   
  7. public void setUser(User user) {  
  8.    this.user = user;  
  9. }  
  10.   
  11. public void printUser() {  
  12.    System.out.println(user.getName() + " " + user.getAge());  
  13. }  
  14. }  
 
Java代码  收藏代码
  1. //将配置中的转换的类:TransformUser.java  
  2.   
  3. public class TransformUser extends PropertyEditorSupport {  
  4.   
  5.  public void setAsText(String text) {  
  6.     String[] data = text.split(",");  
  7.     User user = new User();  
  8.     user.setName(data[0]);  
  9.     user.setAge(Integer.parseInt(data[1]));  
  10.     this.setValue(user);  
  11.   }  
  12. }  
 
Java代码  收藏代码
  1. 在applicationContext.xml文件中。  
  2.   
  3. <bean id="user" class="User" />  
  4. <bean id="transformUser" class="TransformUser"/>  
  5.   
  6. <bean id="userContainer" class="UserContainer">  
  7.      <property name="user" value="liming,23"></property>  
  8. </bean>  
  9.   
  10. <bean id="configBean"   class="org.springframework.beans.factory.config.CustomEditorConfigurer">  
  11.    <property name="customEditors">  
  12.     <map>  
  13.        <entry key="User">  <!-- 属性类型 -->    
  14.              <bean class="TransformUser"/>  <!--对应Address的编辑器 -->    
  15.        </entry>  
  16.     </map>  
  17.    </property>  
  18. </bean>  
  19.   
  20. 将liming,23这种格式的转换成User类。  

例子1:http://www.iteye.com/topic/24660

例子2:http://gundumw100.iteye.com/blog/574440

posted @ 2012-05-16 20:58 刺猬的温驯 阅读(17) 评论(0) 编辑



Java代码  收藏代码
  1. public class Person {  
  2.     private String name;  
  3.     private int id;  
  4.     private int age;  
  5.   
  6.     public int getAge() {  
  7.         return age;  
  8.     }  
  9.   
  10.     public void setAge(int age) {  
  11.         this.age = age;  
  12.     }  
  13.   
  14.     public int getId() {  
  15.         return id;  
  16.     }  
  17.   
  18.     public void setId(int id) {  
  19.         this.id = id;  
  20.     }  
  21.   
  22.     public String getName() {  
  23.         return name;  
  24.     }  
  25.   
  26.     public void setName(String name) {  
  27.         this.name = name;  
  28.     }  
  29. }  
  30.   
  31. import java.beans.PropertyEditorSupport;  
  32. import org.springframework.util.StringUtils;  
  33.   
  34. public class BuildcusPE extends PropertyEditorSupport {  
  35.   
  36.     public void setAsText(String info) throws IllegalArgumentException {  
  37.         // super.setAsText(info);  
  38.         String[] personInfo = StringUtils.delimitedListToStringArray(info, "|");  
  39.         // 顺序为 id,age,name  
  40.         Person man = new Person();  
  41.         man.setId(Integer.parseInt(personInfo[0]));  
  42.         man.setAge(Integer.parseInt(personInfo[1]));  
  43.         man.setName(personInfo[2]);  
  44.         setValue(man);  
  45.     }  
  46. }  
  47.   
  48. import org.springframework.context.ApplicationContext;  
  49. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  50.   
  51. public class Testpe {  
  52.     private Person man;  
  53.   
  54.     public Person getMan() {  
  55.         return man;  
  56.     }  
  57.   
  58.     public void setMan(Person man) {  
  59.         this.man = man;  
  60.         System.out.println("员工姓名:" + man.getName());  
  61.         System.out.println("员工编号:" + man.getId());  
  62.         System.out.println("员工年龄:" + man.getAge());  
  63.     }  
  64.   
  65.     public static void main(String[] args) {  
  66.         ApplicationContext ctx = new ClassPathXmlApplicationContext("springmvc2-servlet.xml");  
  67.     }  
  68. }  
  69.   
  70.   
  71. <!-- Test PropertyEditorSupport -->  
  72.     <!-- Begin -->  
  73.     <bean name="customEditorConfigurer"  
  74.         class="org.springframework.beans.factory.config.CustomEditorConfigurer">  
  75.         <property name="customEditors">  
  76.             <map>  
  77.                 <entry key="com.alipay.yiyu.springmvc.testPropertyEditor.Person">  
  78.                     <bean class="com.alipay.yiyu.springmvc.testPropertyEditor.BuildcusPE"></bean>  
  79.                 </entry>  
  80.             </map>  
  81.         </property>  
  82.     </bean>  
  83.     <bean id="peTest" class="com.alipay.yiyu.springmvc.testPropertyEditor.Testpe">  
  84.         <property name="man">  
  85.             <value>3|29|David</value>  
  86.         </property>  
  87.     </bean>  
  88.     <!-- Test PropertyEditorSupport End -->  
posted @ 2012-05-16 20:57 刺猬的温驯 阅读(14) 评论(0) 编辑

仅列出标题  下一页