`
wsc830719
  • 浏览: 163450 次
  • 性别: Icon_minigender_1
  • 来自: 唐山
社区版块
存档分类
最新评论

netbeans(6):扩展struts插件预期讨论

阅读更多

      这几天在读netbeans关于struts部分的源码。因为前段时间看了传智博客的巴巴运动网视频,实体的数据库服务类的常见操作都可以用一个基类来完成,这样下来,其他的工作就是不断的重复,就是拷贝粘贴代码,然后再改改。可以说都是一些重复的工作,于是我想把这部分工作通过扩展插件来让IDE自动完成。

       大致思想如下:

将官网struts插件当作类库使用。

因为spring使用注释,不涉及操作配置文件,只有struts需要写配置文件,但是控制器可以使用注释。

spring服务类:

1 根据实体类生成服务类。
比如实体类为Product
public class ProductServiceBean extends DaoSupport<实体类Product> implements ProductService
public interface ProductService extends DAO<实体类Product>
选择 实体类,将自动匹配成上述名称,Product——ProductService(接口)——ProductServiceBean(服务类)
上述名称只是默认生成,可以更改。
关键:找到所有实体类,列入下拉选择框中;根据所选包,并根据相应模板生成相应文件;
此处使用注释,因此不需要读写配置文件。
2 根据实体类生成formbean类
   根据所选的实体类生成formbean类,默认继承BaseForm,并且:
   使用反射查找所有字段,并列入表格中,可以通过选择框勾选是否放入formbean的字段中。
   (可以通过添加按钮,可以添加字段,并设置其类型。这个是否能提高开发效率也难说,直接在类中添加也不慢
     因为IDE有自动完成功能,没必要通过弹出框来添加)
 
3 生成struts的Actions类。
选择实体类 服务类 formbean类
首先此处,除了标记其为Controller外,需要写配置文件。
生成一个ProductAction(默认,可以更改),默认继承DispatchAction
 该Action生成 list  addUI add editUI edit    delete等6个方法。

4 生成相应的页面
 1列表页面——包含链接: 添加、编辑、删除
 2添加页面——针对实体类中划入formbean类的字段生成input框。
 (添加成功后是转向列表页面 还是转向成功提示页?)
 3编辑页面——和添加页面类似
 4 删除页面——(删除成功后是转向列表页面 还是转向成功提示页?)
  此外,上述都需要考虑失败页面。

其实就是和netbeans的EJB+JSF的根据实体类生成更删查改的应用类似。

如果能实现这些功能,效率将提高很多。

 

其中使用的几个基础类如下:

1 BaseForm类

public class BaseForm extends org.apache.struts.action.ActionForm {

    private static Properties properties = new Properties();

    static {
        try {
            properties.load(BaseForm.class.getClassLoader().getResourceAsStream("arrowuploadfiletype.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**获取当前页数**/
    private int pageNum;

    public int getPageNum() {
        return pageNum < 1 ? 1 : pageNum;
    }

    public void setPageNum(int pageNum) {
        this.pageNum = pageNum;
    }

    public static Properties getProperties() {
        return properties;
    }

    public static void setProperties(Properties properties) {
        BaseForm.properties = properties;
    }

    /**
     * 验证上传文件类型是否属于图片格式
     * @return
     */
    public static boolean validateImageFileType(FormFile formfile) {
        if (formfile != null && formfile.getFileSize() > 0) {
            List<String> arrowType = Arrays.asList("image/bmp", "image/png", "image/gif", "image/jpg", "image/jpeg", "image/pjpeg");
            List<String> arrowExtension = Arrays.asList("gif", "jpg", "bmp", "png");
            String ext = getExt(formfile);
            return arrowType.contains(formfile.getContentType().toLowerCase()) && arrowExtension.contains(ext);
        }
        return true;
    }

    public static String getExt(FormFile formfile) {
        return formfile.getFileName().substring(formfile.getFileName().lastIndexOf('.') + 1).toLowerCase();
    }

    /**
     * 验证上传文件是否属于图片/flash动画/word文件/exe文件/pdf文件/TxT文件/xls文件/ppt文件
     * @param formfile
     * @return
     */
    public static boolean validateFileType(FormFile formfile) {
        if (formfile != null && formfile.getFileSize() > 0) {
            String ext = formfile.getFileName().substring(formfile.getFileName().lastIndexOf('.') + 1).toLowerCase();
            List<String> arrowType = new ArrayList<String>();
            for (Object key : properties.keySet()) {
                String value = (String) properties.get(key);
                String[] values = value.split(",");
                for (String v : values) {
                    arrowType.add(v.trim());
                }
            }
            return arrowType.contains(formfile.getContentType().toLowerCase()) && properties.keySet().contains(ext);
        }
        return true;
    }

    /**
     * 保存文件
     * @param savedir 存放目录
     * @param fileName 文件名称
     * @param data 保存的内容
     * @return 保存的文件
     * @throws Exception
     */
    public static File saveFile(File savedir, String fileName, byte[] data) throws Exception {
        if (!savedir.exists()) {
            savedir.mkdirs();//如果目录不存在就创建
        }
        File file = new File(savedir, fileName);
        FileOutputStream fileoutstream = new FileOutputStream(file);
        fileoutstream.write(data);
        fileoutstream.close();
        return file;
    }
}

 

2 DAO顶级接口类

 

package com.kks.service.base;

import java.io.Serializable;
import java.util.LinkedHashMap;

public interface DAO<T> {

    /**
     * 获取记录总数
     * @param entityClass 实体类
     * @return
     */
    public long getCount();

    /**
     * 清除一级缓存的数据
     */
    public void clear();

    /**
     * 保存实体
     * @param entity 实体id
     */
    public void save(Object entity);

    /**
     * 更新实体
     * @param entity 实体id
     */
    public void update(Object entity);

    /**
     * 删除实体
     * @param entityClass 实体类
     * @param entityids 实体id数组
     */
    public void delete(Serializable... entityids);

    /**
     * 获取实体
     * @param <T>
     * @param entityClass 实体类
     * @param entityId 实体id
     * @return
     */
    public T find(Serializable entityId);

    /**
     * 获取分页数据
     * @param <T>
     * @param entityClass 实体类
     * @param firstindex 开始索引
     * @param maxresult 需要获取的记录数
     * @return
     */
    public QueryResult<T> getScrollData(int firstindex, int maxresult, String wherejpql, Object[] queryParams, LinkedHashMap<String, String> orderby);

    public QueryResult<T> getScrollData(int firstindex, int maxresult, String wherejpql, Object[] queryParams);

    public QueryResult<T> getScrollData(int firstindex, int maxresult, LinkedHashMap<String, String> orderby);

    public QueryResult<T> getScrollData(String wherejpql, Object[] queryParams);

    public QueryResult<T> getScrollData(String wherejpql, Object[] queryParams, LinkedHashMap<String, String> orderby);

    public QueryResult<T> getScrollData(int firstindex, int maxresult);

    public QueryResult<T> getScrollData();
}

 

3 数据库操作基类DaoSupport

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.kks.service.base;

import com.kks.util.GenericsUtils;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 *
 */
@Transactional
public class DaoSupport<T> implements DAO<T> {

    protected Class<T> entityClass = GenericsUtils.getSuperClassGenricType(this.getClass());
    @PersistenceContext
    protected EntityManager em;

    public void clear() {
        em.clear();
    }

    public void delete(Serializable... entityids) {
        for (Object id : entityids) {
            em.remove(em.getReference(this.entityClass, id));
        }
    }

    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public T find(Serializable entityId) {
        if (entityId == null) {
            throw new RuntimeException(this.entityClass.getName() + ":传入的实体id不能为空");
        }
        return em.find(this.entityClass, entityId);
    }

    public void save(Object entity) {
        em.persist(entity);
    }

    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public long getCount() {
        return (Long) em.createQuery("select count(" + getCountField(this.entityClass) + ") from " + getEntityName(this.entityClass) + " o").getSingleResult();
    }

    public void update(Object entity) {
        em.merge(entity);
    }

    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public QueryResult<T> getScrollData(int firstindex, int maxresult, LinkedHashMap<String, String> orderby) {
        return getScrollData(firstindex, maxresult, null, null, orderby);
    }

    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public QueryResult<T> getScrollData(int firstindex, int maxresult, String wherejpql, Object[] queryParams) {
        return getScrollData(firstindex, maxresult, wherejpql, queryParams, null);
    }

    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public QueryResult<T> getScrollData(int firstindex, int maxresult) {
        return getScrollData(firstindex, maxresult, null, null, null);
    }

    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public QueryResult<T> getScrollData() {
        return getScrollData(-1, -1);
    }

    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public QueryResult<T> getScrollData(String wherejpql, Object[] queryParams) {
        return getScrollData(-1, -1, wherejpql, queryParams);
    }

    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public QueryResult<T> getScrollData(String wherejpql, Object[] queryParams, LinkedHashMap<String, String> orderby) {
        return getScrollData(-1, -1, wherejpql, queryParams, orderby);
    }

    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public QueryResult<T> getScrollData(int firstindex, int maxresult, String wherejpql, Object[] queryParams, LinkedHashMap<String, String> orderby) {
        QueryResult qr = new QueryResult<T>();
        String entityname = getEntityName(this.entityClass);
        Query query = em.createQuery("select o from " + entityname + " o " + (wherejpql == null || "".equals(wherejpql.trim()) ? "" : "where " + wherejpql) + buildOrderby(orderby));
        setQueryParams(query, queryParams);
        if (firstindex != -1 && maxresult != -1) {
            query.setFirstResult(firstindex).setMaxResults(maxresult);
        }
        qr.setResultlist(query.getResultList());
        query = em.createQuery("select count(" + getCountField(this.entityClass) + ") from " + entityname + " o " + (wherejpql == null || "".equals(wherejpql.trim()) ? "" : "where " + wherejpql));
        setQueryParams(query, queryParams);
        qr.setTotalrecord((Long) query.getSingleResult());
        return qr;
    }

    protected static void setQueryParams(Query query, Object[] queryParams) {
        if (queryParams != null && queryParams.length > 0) {
            for (int i = 0; i < queryParams.length; i++) {
                query.setParameter(i + 1, queryParams[i]);
            }
        }
    }

    /**
     * 组装order by语句
     * @param orderby
     * @return
     */
    protected static String buildOrderby(LinkedHashMap<String, String> orderby) {
        StringBuffer orderbyql = new StringBuffer("");
        if (orderby != null && orderby.size() > 0) {
            orderbyql.append(" order by ");
            for (String key : orderby.keySet()) {
                orderbyql.append("o.").append(key).append(" ").append(orderby.get(key)).append(",");
            }
            orderbyql.deleteCharAt(orderbyql.length() - 1);
        }
        return orderbyql.toString();
    }

    /**
     * 获取实体的名称
     * @param <E>
     * @param clazz 实体类
     * @return
     */
    protected static <E> String getEntityName(Class<E> clazz) {
        String entityname = clazz.getSimpleName();
        Entity entity = clazz.getAnnotation(Entity.class);
        if (entity.name() != null && !"".equals(entity.name())) {
            entityname = entity.name();
        }
        return entityname;
    }

    /**
     * 返回实体类的符合能够count的值,主要是考虑复合主键的情况,不是复合主键的话,直接实体即可
     * @param <E>
     * @param clazz
     * @return
     */
    protected static <E> String getCountField(Class<E> clazz) {
        String out = "o";
        try {
            PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(clazz).getPropertyDescriptors();
            for (PropertyDescriptor propertydesc : propertyDescriptors) {
                Method method = propertydesc.getReadMethod();
                if (method != null && method.isAnnotationPresent(EmbeddedId.class)) {
                    PropertyDescriptor[] ps = Introspector.getBeanInfo(propertydesc.getPropertyType()).getPropertyDescriptors();
                    out = "o." + propertydesc.getName() + "." + (!ps[1].getName().equals("class") ? ps[1].getName() : ps[0].getName());
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return out;
    }
}

 

其他的类都从上面继承,可以说结构非常类似,这样借助IDE自动生成,将极大提高效率。

不过使用注释,意味着必须使用jdk1.5及以上。

 

暂时想到这些,更详细的设计还在进行中,粗略的做了个对话框,证明可以使用struts插件已有的东西。现在就差我自己的实现了。 我也想放到kenail上,不知道有没有志同道合的,对netbeans RCP有一定了解,又想做这个插件的。该想法基于传智博客的巴巴视频的封装,有此封装,其他代码就是结构一致的代码,自动生成的价值非常高。

我的开发环境 spring2.5 ,jpa1.0(hibernate或toplink实现) ,struts1.3.8.

或者有一些想法可以留言,比如根据实体类拿到它的字段以及生成formbean类,还有再根据formbean类的原始字段生成

页面的添加的input(都先一致生成input,其他类型可以改),还是可以选择生成input或textarea呢?如果生成textarea是否就给它选择框,选择是否使用富文本支持呢(就是html编辑器)?如果使用html编辑器,这个也不好办,因为大家使用的编辑器不同。这些详细的可以作为未来版本的完善。目前围绕功能实现。如果能提供高效的查找机制就更好了。比如实体类的字段,我可以选择那些进入formbean类,然后我还要根据formbean类去生成页面,然后Action类的

添加和修改方法,还要去根据它们进行setter/getter的设置,然后调用合适的服务类调用基类的save update方法。

 

      可能开始并不会完善,集中体验就是不能拿来就运行,只是哪怕是生成框架呢,也是能极大减少代码输入量。希望我的想法最终变成现实。

 

 

 

 

 


 

0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics