Jsp标签字典开发_基于Spring+Hibernate
目录
1. Jsp标签字典开发_基于Spring+Hibernate
1.1. 简述
1.2. 定义DictItem实体
1.3. 定义字典的@interface
1.4. 定义字典缓存类
1.5. 定义tld标签
1.6. 持久层实体使用注解
1.7. 页面调用jsp标签
2. 补充点
2.1. Hibernate设置属性成功后扫描字典
2.2. Annotation注解
2.2.1. 简述
2.2.2. 元注解
2.2.3. 自定义注解
1. Jsp标签字典开发_基于Spring+Hibernate
1.1. 简述
最近在项目中,发现一个很不错的jsp字典缓存开发。不过是基于Spring+Hibernate技术的,记录下来方便以后有个参考。
主要流程是这样的:
1、创建tdl,以及对应的后来处理类;
2、定义字典相关的@interface;
3、当项目创建启动开始创建sessionFactory时,扫描entity时候获取到已定义的字典@interface,然后存入到系统缓存(一般是定义一个静态的map存放)中;
4、页面使用定义的标签调用,去系统缓存里面取值。
1.2. 定义DictItem实体
一般来说,字典都是key-value的方式,这里的key就是group,value是DictItem.包含有一个text和value属性,text表示显示的值,value表示数据库的值。举个简单的例子说明:
假设表a有一个status字段,当status=1的时候,text为“成功”;当status=2的时候,text为“失败”。这样我们可以把表a的status作为一个字典。key可以是“status”,value为DictItem(简单表示为[{”value”:1,”text”:”成功”},{”value”:2,”text”:”失败”}])。
DictItem实体可以简单定义如下:
//显示值 private String text; //值 private String value; public String getText() { return text; } public void setText(String text) { this.text = text; } public String getValue() { return value; } public void setValue(String value) { this.value = value; }
1.3. 定义字典的@interface
在这里主要有DictDefine、DictGroup、DictItem几个注解定义,下面一一介绍具体的定义。
1、DictDefine的创建
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.FIELD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface DictDefine { public DictGroup[] value(); }
2、DictGroup的创建
public @interface DictGroup{ public String name(); public DictItem[] items(); }
3、DictItem的创建
public @interface DictItem{ public String value();//值 public String text();//显示值 }
1.4. 定义字典缓存类
这里可以定义一个简单的字典缓存变量,一般是静态的map。如:
private static Map<String,List<DictItem>> cache = new HashMap<String, List<DictItem>>();
这个java类(如SysDictCache)需要提供一个设置值和取值的方法。一般情况下,存值根据组(group)和字典(DictItem);取值的话,根据组(group)和值(value),具体的实现根据项目需求自行发挥,这里只是提供一个思路。
1.5. 定义tld标签
我们需要有jsp的tld文件,一般是放在项目的WEB-INF包下面的。举个简单的例子如下:
<?xml version="1.0" encoding="UTF-8" ?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"> <description>xmq自定义标签,扩展jstl标签</description> <display-name>xmq tag</display-name> <tlib-version>1.1</tlib-version> <short-name>xmq</short-name> <uri>http://com.xmq.tag/tld</uri> <validator> <description> Provides core validation features for JSTL tags. </description> <validator-class> org.apache.taglibs.standard.tlv.JstlCoreTLV </validator-class> </validator> <tag> <description>处理字典</description> <name>dict</name> <tag-class>com.xmq.tag.dictTag</tag-class> <body-content>JSP</body-content> <attribute> <description>处理分组</description> <name>group</name> <required>true</required> <rtexprvalue>true</rtexprvalue> <type>java.lang.String</type> </attribute> <attribute> <description>值</description> <name>dict</name> <required>true</required> <rtexprvalue>true</rtexprvalue> <type>java.lang.String</type> </attribute> </tag> </taglib>
还需要一个后台处理标签的java类,该类需要继承TagSupport,重写doStartTag方法,根据项目需求自行更改。下面给一个简单的例子:
public class dictTag extends TagSupport { private static final long serialVersionUID = 1L; private String group; private String dict; public String getGroup() { return group; } public void setGroup(String group) { this.group = group; } public String getdict() { return dict; } public void setdict(String dict) { this.dict = dict; } @Override public int doStartTag() throws JspException { //DictItem实体与上述的@interface DictItem要对应 //主要功能就是保存取出的具体字典 DictItem dictItem = SysdictCache.get(group, dict); if (dictItem != null) { JspWriter w = pageContext.getOut(); try { w.write(dictItem.getText()); } catch (IOException e) { throw new JspException(e.toString(), e); } } return SKIP_BODY; } }
1.6. 持久层实体使用注解
接下来需要对@Entity的实体进行字典引用定义,一般是定义在某个字段上的,如下述代码:
@DictDefine({ @DictGroup(name="TEST",items={ @DictItem(text="成功",value="1"), @DictItem(text="失败",value="2") }) }) @Column(name = "STATUS" , length = 3) private String status;
1.7. 页面调用jsp标签
页面引入自定义jsp标签:
<%@ taglib uri="http://com.xmq.tag/tld" prefix="xmq"%>
使用jsp标签:
<xmq:dict group="TEST" dict="1"/>
2. 补充点
2.1. Hibernate设置属性成功后扫描字典
在spring的applicationContext.xml中配置Hibernate的sessionFactory时候,指定一个类来处理字典的扫描工作。如:
<bean id="sessionFactory" class="com.xmq.database.DefaultSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
</bean>
后台扫描字典的bean需要继承LocalSessionFactoryBean,并重写afterPropertiesSet()方法。如:
public class DefaultSessionFactoryBean extends LocalSessionFactoryBean{ private static final Log logger = LogFactory.getLog(DefaultSessionFactoryBean.class); private String[] entityPackage; private static final String RESOURCE_PATTERN = "/**/*.class"; private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); private TypeFilter entityFilter = new AnnotationTypeFilter(Entity.class , false); @Override public void afterPropertiesSet() throws IOException { super.afterPropertiesSet(); try{ if(this.entityPackage != null){ for (String pkg : entityPackage) {
//entityPackage为spring的applicationContext.xml中的"com.xmq.core":<context:component-scan base-package="com.xmq.core" /> //ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX为classpath*:
//ClassUtils.convertClassNameToResourcePath(pkg)转换为带"/"路径,如:com.xmq.core->com/xmq/core
//pattern变量的值最后为:classpath*:com/hymake/sdic/**/*.class
String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(pkg) + RESOURCE_PATTERN; Resource[] resources = new PathMatchingResourcePatternResolver().getResources(pattern); //resources变量保存资源文件如:[file[..\classes\com\xmq\core\dbUtil.class],file[..\classes\com\xmq\core\stringUtil.class],file [D:\ec...] MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver); for (Resource resource : resources) { if (resource.isReadable()) { MetadataReader reader = readerFactory.getMetadataReader(resource); if(entityFilter.match(reader, readerFactory)){ //过滤出有@Entity注解的pojo scanEntitydictDefined(reader); } } } } } }catch(Exception e){ throw new SysException(e.getMessage() , e); } } /** * 扫描dictDefined * @param reader * @throws ClassNotFoundException */ private void scanEntityDictDefined(MetadataReader reader) throws ClassNotFoundException{ Class cls = Class.forName(reader.getClassMetadata().getClassName()); //过滤出有@DictDefine的@Entity注解的pojo DictDefine dd = (DictDefine)cls.getAnnotation(DictDefine.class); if(dd != null){ parseDictDefine(dd); } //没有就去遍历fileds,查找@DictDefine注解 Field[] fields = cls.getDeclaredFields(); for(Field field : fields){ DictDefine dd2 = (DictDefine)field.getAnnotation(DictDefine.class); if(dd2 != null){ parsedictDefine(dd2); } } } private void parseDictDefine(dictDefine cd) { DictGroup[] groups = cd.value(); for(DictGroup dg : groups){ for(DictItem item : dg.items()){ //字典加入系统缓存 SysDictCache.addToCache(dg.name(), new com.xmq.dict.DictItem(item.value(), item.text())); } } } @Override public void setPackagesToScan(String... packagesToScan) { super.setPackagesToScan(packagesToScan); this.entityPackage = packagesToScan; } }
2.2. Annotation注解
2.2.1. 简述
Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息和任何元数据(metadata)的途径和方法。Annotion(注解)是一个接口,程序可以通过反射来获取指定程序元素的Annotion对象,然后通过Annotion对象来获取注解里面的元数据。
2.2.2. 元注解
注解名 |
取值 |
备注 |
@Target |
1.CONSTRUCTOR:用于描述构造器 |
@Target定义了Annotation所修饰的对象范围 |
@Retention |
1.SOURCE:在源文件中有效(即源文件保留) |
定义了Annotation被保留的时间长短 |
@Documented |
|
@Documented用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员 |
@Inherited |
|
@Inherited是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。 |
2.2.3. 自定义注解
定义注解时候,会自动继承了java.lang.annotation.Annotation接口,在定义注解时,不能继承其他的注解或接口。
定义注解格式:
public @interface 注解名 {定义体}
示例如下:
public @interface DictItem{ public String value();//值 public String text();//显示值 }
//显示默认值的话,可以采用如下方法:
public @interface DictItem{ public String value() defalut “123”;//值 public String text() defalut “123”;//显示值 }