javaweb日记选(动态表单及表的实现)

Java语言也可以创建动态表单,如javaweb创建表单及表

应用场景
项目中往往需要动态的创建一个表单,或者添加一个新的数据模板,这时候因为需要在运行时动态的创建表以及动态的维护表字段甚至表关系 使得普通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生成表示层页面以及代码来进行展示。

这是Javaweb创建的表单。

大功告成

end

时间: 2024-10-13 00:30:13

javaweb日记选(动态表单及表的实现)的相关文章

Bootstrap 表单和图片 (内联表单,表单合组,水平排列,复选框和单选框,下拉列表,校验状态,添加额外的图标,控制尺寸,图片)

一.表单 基本格式 注:只有正确设置了输入框的 type 类型,才能被赋予正确的样式. 支持的输入框控件 包括:text.password.datetime.datetime-local.date.month.time.week. number.email.url.search.tel 和 color. <form> <div class="form-group"> <label>电子邮件</label> <input type=&

MVC动态生成的表单:表单元素比较多 你就这样写

MVC动态生成的表单:表单元素比较多 你就这样写: public ActionResult ShoudaanActionResult(FormCollection from,T_UserM user) { List<string> daan = new List<string>(); for (int i = 4; i < from.Count; i++) { daan.Add(from[i].ToString()); } QSAcceptAnswer qaa = new Q

jquery验证表单 提交表单

问题: jquery中使用submit提交按钮时,当return false后,依然会提交表单. 解决: 使用button按钮,而不是submit按钮 <script type="text/javascript" src="scripts/jquery-2.0.2.js"></script> <script type="text/javascript"> function check(){ var npassw

JQuery ajax提交表单及表单验证

JQuery ajax提交表单及表单验证 博客分类: jsp/html/javascript/ajax/development Kit 开源项目 注:经过验证,formValidator只适合一个页面不超过一个表单的情况. 本例实现功能:通过ajax提交表单,并在提交表单前对表单的数据进行验证. 主要通过两个插件实现: 第一个: jQuery Form Plugin http://jquery.malsup.com/form 主要功能是ajax提交表单 第二个:jQuery formValida

js验证阻止表单提交(表单绑定onsubmit事件)

原始方式: <form action="http://www.cnblogs.com/zixueit/" onsubmit="return check()"> <input type="submit" value="提交" /> </form> <script type="text/javascript"> function check(){ if(!conf

ajaxSubmit 页面生成的html 中含有表单提交表单方式

$("#form_title").ajaxSubmit({ //页面生成的html 中含有表单提交表单方式 dataType: "json", success : function(obj){ lock_flag = false; if(obj.errno == 0){ lock_flag = false; layer.msg(obj.errdesc); setTimeout(function() { window.location.reload(); },2000

表单及表单新增元素

要想更好运用表单就要了解表单的的更多元素与属性,首先看看对表单基本了解. 表单的基本了解  <form> 元素用于用户输入数据的收集  <input> 元素是最重要的表单元素,有许多type其中<input type="submit">是用于向表单处理程序提交表单的按钮.  <select> 元素<option> 元素定义待选择的下拉列表选项,  <textarea> 元素定义文本区域.  <button&

表单and表单元素

表单 <form action="" method="get/post" ></form> 上传到服务器 表单元素 文本类 <input type="text" value=""> - 普通文本框 <input type="text" password=""> - 密码框 <textarea></textarea>-

Bootstrap_表单_表单控件

一.输入框input 单行输入框,常见的文本输入框,也就是input的type属性值为text. 在Bootstrap中使用input时也必须添加type类型,如果没有指定type类型,将无法得到正确的样式,因为Bootstrap框架都是通过input[type=“?”] (其中?号代表type类型,比如说text类型,对应的是input[type=“text”])的形式来定义样式的. 为了让控件在各种表单风格中样式不出错,需要添加类名“.form-control”. <form role=&quo