javaweb日記選(動態表單及表的實現)

   Java語言也能夠建立動態表單,如javaweb建立表單及表 css

應用場景
項目中每每須要動態的建立一個表單,或者添加一個新的數據模板,這時候由於須要在運行時動態的建立表以及動態的維護表字段甚至表關係 使得普通java解決方案變得困難重重。

實現工具
Hibernate + Spring + Groovy +Freemarker
Hibernate 做用很簡單負責建立數據庫表這樣能夠避免咱們本身去寫複雜的sql和判斷。
Spring 做爲橋樑起到鏈接紐帶的做用
Groovy 作爲動態語言,在項目運行時根據模板建立訪問數據庫,或者控制層代碼
Freamker 能夠根據提早定義好的模板生成 hibernate配置文件,以及Groovy代碼

實現原理
首先建立Form 和 FromAttribute 兩張表關係一對多。
Form表 記錄表單的名稱,類別,甚至是做爲在動態生成表單時的css樣式信息
FromAttribute表 記錄表單字段信息,如名稱,類別等。
有了表單以及表單項的信息後就能夠建立數據庫表了。

測試代碼:
public void testGenerator() {
         Form form = formService.getAll().get(0);
         List<FormAttribute> list = formAttributeService
                 .getAttributeListByFormId(form.getId());
         form.setFormAttributeList(list);
         DbGenerator dg = new DbGenerator(form, dataSource);
         dg.generator();
}
DbGenerator

import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
public class DbGenerator {

     private DataSource dataSource;
     protected Map root = new HashMap();
     private static Logger log = LoggerFactory.getLogger(FormGenerator.class);
     protected String path;
     protected String packageName;
     private Form form;
     protected Configuration getConfig(String resource) {
         Configuration cfg = new Configuration();
         cfg.setDefaultEncoding("UTF-8");
         cfg.setClassForTemplateLoading(this.getClass(), resource);
         return cfg;
     }
     public DbGenerator(Form form ,DataSource dataSource) {
         this.form = form;
         this.dataSource = dataSource;
     }
     public void generator() {
         if(null == form.getFormAttributeList() || form.getFormAttributeList().size() == 0){
             return ;
         }
         Template t;
         try {
             t = getConfig("/template").getTemplate("hibernate.ftl");
             Writer out = new StringWriter();
             t.process(getMapContext(), out);
             String xml = out.toString();
             createTable(xml);
             log.debug(xml);
         } catch (IOException e) {
             e.printStackTrace();
         } catch (TemplateException e) {
             e.printStackTrace();
         }
     }
     @SuppressWarnings("unchecked")
     Map getMapContext() {
         root.put("entity", form);
         return root;
     }
     public void createTable(String xml) {
         org.hibernate.cfg.Configuration conf = new org.hibernate.cfg.Configuration();
         conf.configure("/hibernate/hibernate.cfg.xml");
         Properties extraProperties = new Properties();
         extraProperties.put("hibernate.hbm2ddl.auto", "create");
         conf.addProperties(extraProperties);
         conf.addXML(xml);
         SchemaExport dbExport;
         try {
             dbExport = new SchemaExport(conf, dataSource.getConnection());
             // dbExport.setOutputFile(path);
             dbExport.create(false, true);
         } catch (SQLException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }
     }
}
hibernate.ftl
< xml version="1.0" encoding="UTF-8" >
<!DOCTYPE hibernate-mapping 
   PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
          "">
<hibernate-mapping>
     <class
         name="${entity.name}"
         table="`${entity.tableName}`"
         dynamic-update="false"
         dynamic-insert="false"
         select-before-update="false"
         optimistic-lock="version">
         <id
             name="id"
             column="id"
             type="java.lang.String"
             unsaved-value="null">
             <generator class="uuid" />
         </id>
         <#if entity.formAttributeList exists>
             <#list entity.formAttributeList as attr>
                 <#if attr.name == "id">
                 <#else>
         <property
             name="${attr.name}"
             type="java.lang.String"
             update="true"
             insert="true"
             access="property"
             column="`${attr.columnName}`"
             length="${attr.length}"
             not-null="false"
             unique="false"
         />

                 </#if>
             </#list>
         </#if>

     </class>
</hibernate-mapping>

hibernate.cfg.xml
<!DOCTYPE hibernate-configuration
     PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
     "">
<hibernate-configuration>
<session-factory>
         <property name="dialect">org.hibernate.dialect.SQLServerDialect</property>
     <property name="connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property>
     <property name="connection.url">jdbc:jtds:sqlserver://127.0.0.1:1433;databasename=struts;SelectMethod=cursor</property>
     <property name="connection.username">sa</property>
     <property name="connection.password">sa</property>

     <property name="show_sql">true</property>
     <property name="hibernate.hbm2ddl.auto">update</property>
<!--
     <mapping resource="hibernate/FormAttribute.hbm.xml" />
     <mapping resource="hibernate/Form.hbm.xml" />
     -->
</session-factory>
</hibernate-configuration>

利用groovy動態建立訪問代碼
建立好數據庫後 就要利用groovy動態建立訪問代碼了:
先看測試代碼 再看具體實現:

public void testGroovy() {
         Form form = formService.get("1");
         List<FormAttribute> list = formAttributeService
                 .getAttributeListByFormId(form.getId());
         form.setFormAttributeList(list);
         FormGenerator fg = new FormGenerator(form);
         String groovycode = fg.generator();
         ClassLoader parent = getClass().getClassLoader();
         GroovyClassLoader loader = new GroovyClassLoader(parent);
         Class groovyClass = loader.parseClass(groovycode);
         GroovyObject groovyObject = null;
         try {
             groovyObject = (GroovyObject) groovyClass.newInstance();
         } catch (InstantiationException e) {
             e.printStackTrace();
         } catch (IllegalAccessException e) {
             e.printStackTrace();
         }
         // map中key爲formAttribute中描述該表單字段在數據庫中的名稱c_columnName
         // 具體狀況根據formAttribute而定
         Map map = new HashMap();
         map.put("name", "limq");
         // 調用insert方法插入數據
         int c = (Integer) groovyObject.invokeMethod("insert", map);
         // 調用getAll方法得到全部動態表中的數據
         Object o = groovyObject.invokeMethod("getAll", null);
         List list2 = (List) o;
         Object obj = list2.get(0);
         try {
             String tname = (String) BeanUtils.getDeclaredProperty(obj, "name");
             System.out.println(tname);
         } catch (IllegalAccessException e) {
             e.printStackTrace();
         } catch (NoSuchFieldException e) {
             e.printStackTrace();
         }
         // 調用search方法查詢動態表
         List<Map> returnList = (List) groovyObject.invokeMethod("search", map);
         for (Map map2 : returnList) {
             // 同理此處根據FromAttribute而定
             System.out.println(map2.get("id"));
             System.out.println(map2.get("name"));
             System.out.println(map2.get("type"));
         }
     }


建立訪問數據庫Groovy代碼
public class FormGenerator {
     protected  Map root = new HashMap();
     private static Logger log = LoggerFactory.getLogger(FormGenerator.class);
         protected String path ;
         protected String packageName ;
         private Form form ;
         protected Configuration getConfig(String resource) {

              Configuration cfg = new Configuration();
             cfg.setDefaultEncoding("UTF-8");
             cfg.setClassForTemplateLoading(this.getClass(), resource);
             return cfg;
         }

         public FormGenerator(Form form){
             this.form = form;
         }

         public String generator(){
             String returnstr = null;
             Template t;
             try {
                 t = getConfig("/template").getTemplate("FormService.ftl");
                 //Writer out = new OutputStreamWriter(new FileOutputStream(new File(path)),"UTF-8");
                 Writer out = new StringWriter();
                 t.process(getMapContext(), out);
                 returnstr = out.toString();
                 log.debug(returnstr);
             } catch (IOException e) {
                 e.printStackTrace();
             } catch (TemplateException e) {
                 e.printStackTrace();
             }
             return returnstr;
         }

         @SuppressWarnings("unchecked")
         Map getMapContext() {
             root.put("entity", form);
             root.put("insert", SqlHelper.buildInsertStatement(form));
             root.put("update", SqlHelper.buildUpdateStatement(form));

             root.put("insertParameter", SqlHelper.buildInsertparameter(form));
             root.put("updateParameter", SqlHelper.buildUpdateparameter(form));

             root.put("delete", SqlHelper.buildDeleteStatement(form));
             root.put("query",  SqlHelper.buildQueryStatement(form));
             return root;
         }
}

利用 freemarker 生成 Groovy 和 hibernate 相關代碼
FormService.ftl
import org.springframeworre.RowMapper
import org.springframeworre.RowMapperResultSetExtractor
import core.dao.DataSourceFactory
import ormons.lang.builder.ToStringBuilder;
import ormons.lang.builder.ToStringStyle;
class ${entity.name cap_first}Dao {
      def insert = '${insert}'
      def delete = '${delete}'
      def update = '${update}'
      def int insert( entity){
         def Object[] params = [${insertParameter}]
         <#assign size = entity.formAttributeList size/>
         def int[] types=[<#list 1..size+1 as p>Types.VARCHAR,<#rt/$amp;>amp;$lt;/#list>]
         return DataSourceFactory.getJdbcTemplate().update(insert, params, types)
     }
      def int update( entity){
         def Object[] params = [${updateParameter}]
         return DataSourceFactory.getJdbcTemplate().update(update, params)
     }
      def int delete(String entityId){
         def Object[] params =[entityId]
         return DataSourceFactory.getJdbcTemplate().update(delete, params)
     }
     def search(entity){
         ${query}
         println(query);
         return DataSourceFactory.getJdbcTemplate().queryForList(query);

     }

}
瞭解以上的原理後就能夠方便的在運行時利用freemarker生成表示層頁面以及代碼來進行展現。 java

這是Javaweb建立的表單。 web

大功告成 spring

end sql

相關文章
相關標籤/搜索