171012_学习Jeebase笔记

这篇博客主要探讨了GitHub上的优秀项目Jeebase,提取了其中值得学习的工程结构和设计。包括BaseDao的泛型基础接口,提供增删改查功能;BaseService的只读事务处理;BaseModel的预插入和更新方法;Page类的配置文件读取和分页功能;Constant的可配置性增强;以及IOUtils的流关闭和Maps的使用。这些设计提供了高效的开发实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Jeebase是GitHub上一个比较棒的工程,里面许多东西值得我去学习,这只是其中我很想借鉴的几个点。
- 可以借鉴的工程结构:

  • BaseDao.java
public interface BaseDao<T> {
    /***
     * 获取单条数据
     * @param id
     * @return 实体对象
     */
    T get(String id);

    /***
     * 获取单条数据
     * @param entity 实体对象
     * @return 实体对象
     */
    T get(T entity);

    /***
     * 查询数据列表,如果需要分页,请设置分页对象,如:entity.setPage(new Page<T>());
     * @param entity 实体对象
     * @return 实体对象列表
     */
    List<T> getList(T entity);

    /***
     * 插入数据
     * @param entity 要插入的实体对象
     * @return
     */
    int insert(T entity);

    /***
     * 更新数据
     * @param entity 要更新的实体对象
     * @return
     */
    int update(T entity);

    /***
     * 删除数据(一般为逻辑删除,更新del_flag字段为1)[并不是真的删除]
     * @param entity 要删除的实体
     * @return
     */
    int delete(T entity);
}
  • 借鉴:

    • 使用泛型建立一个基础Interface BaseDao。里面有基本的增删改查方法:其中查询有三种,按主键查询,按条件查询(T entity),按条件查询列表(查询数据列表,如果需要分页,请设置分页对象,如:entity.setPage(new Page());)
    • 删除数据(一般为逻辑删除,更新del_flag字段为1)[并不是真的删除]
  • BaseService.java

package cn.support.base;

/**
 * Created by Ww on 2017/10/12.
 */

import cn.support.web.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * Service 基础接口
 */
@Transactional(readOnly = true)
public abstract class BaseService<D extends BaseDao<T>, T extends BaseModel<T>> {

    /***
     * 持久层对象
     */
    @Autowired
    protected D dao;

    /***
     * 获取单条数据
     * @param id 主键
     * @return
     */
    public T get(String id) {
        return dao.get(id);
    }

    /***
     *
     * @param entity
     * @return
     */
    public T get(T entity) {
        return dao.get(entity);
    }

    /**
     * 查询列表数据
     * @param entity 实体对象
     * @return 查询出的数据列表
     */
    public List<T> getList(T entity) {
        return dao.getList(entity);
    }

    /***
     * 查询分页数据
     * @param page 分页对象
     * @param entity 实体对象
     * @return 分页对象(包含查询出的数据列表)
     */
    public Page<T> getPage(Page<T> page, T entity) {
        entity.setPage(page);
        page.setList(dao.getList(entity));
        return page;
    }

    /***
     * 保存数据(插入或更新)
     * @param entity 要保存或更新的实体
     */
    @Transactional(readOnly = false)
    public void save(T entity) {
        if (StringUtils.isEmpty(entity.getId())) {
            entity.preInsert();
            dao.insert(entity);
        } else {
            entity.preUpdate();
            dao.update(entity);
        }
    }

    @Transactional(readOnly = false)
    public void delete(T entity) {
        dao.delete(entity);
    }

}
  • 借鉴:

    • 事物设成只读(@Transactional(readOnly = true))
    • 设置两个泛型(public abstract class BaseService
package cn.support.base;

import cn.support.web.Page;

import java.io.Serializable;
import java.sql.Time;
import java.util.Date;
import java.util.UUID;

/**
 * Created by Ww on 2017/10/12.
 */
public abstract class BaseModel<T> implements Serializable {
    protected String id;//实体编号

//    protected User createBy;//创建者

    protected Date createTime;    // 创建日期

//    protected User updateBy;//更新者

    protected Date updateTime;    // 更新日期

    protected String remarks;    // 备注

    protected String delStatus;    // 删除标记(0:正常;1:删除;2:审核)

    public static final String NORMAL = "0";//正常数据

    public static final String DELETE = "1";//已删除数据

    public static final String AUDIT = "2";//待审核数据

    /***
     * 当前实体分页对象
     */
    protected Page<T> page;

    public BaseModel() {
        this.delStatus  = NORMAL;
    }

    public BaseModel(String id) {
        this.id = id;
        this.delStatus = NORMAL;
    }

    /***
     * 插入之前执行此方法
     */
    public void preInsert() {
        this.setId(UUID.randomUUID().toString().replaceAll("-",""));
        this.createTime = new Date();
        this.updateTime = createTime;
//        User user = ShiroUtils.getCurrentUser();
//        if(user != null){
//            this.createBy = new User(user.getId());
//            this.updateBy = new User(user.getId());
//        }else {
//            this.createBy = new User("0");
//            this.updateBy = new User("0");
//        }
    };

    /***
     * 更新前执行此方法
     */
    public void preUpdate() {
        this.updateTime = new Date();
//        User user = ShiroUtils.getCurrentUser();
//        if(user != null){
//            this.updateBy = new User(user.getId());
//        }else {
//            this.updateBy = new User("0");
//        }
    };

    public Page<T> getPage() {
        return page;
    }

    public void setPage(Page<T> page) {
        this.page = page;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    public String getRemarks() {
        return remarks;
    }

    public void setRemarks(String remarks) {
        this.remarks = remarks;
    }

    public String getDelStatus() {
        return delStatus;
    }

    public void setDelStatus(String delStatus) {
        this.delStatus = delStatus;
    }
}
  • 借鉴:

    • 都有实体编号,创建者,更新者等。
    • 以前UUID都是一句一句的写,现在放到BaseModel中只需要在插入前执行一下preInsert()就可以了。更新同理。
  • Page.java

package cn.support.web;


import com.doubleview.jeebase.support.config.Constant;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * 分页支持类
 */
public class Page<T> {

    private static String pageNoParam = "pageNo";//当前页面请求参数
    private static String pageSizeParam = "pageSize";//当前页面大小请求参数
    private static String orderByParam = "orderByParam";//当前页面排序请求参数


    private int pageNo = 1; // 当前页码
    private int pageSize = Integer.valueOf(Constant.getConfig("page.pageSize")); // 页面大小
    private long totalSize;// 总记录数


    private int first;// 首页索引
    private int last;// 尾页索引

    private boolean firstPage;//是否是第一页
    private boolean lastPage;//是否是最后一页

    private List<T> list = new ArrayList();

    private String orderBy = ""; // 标准查询有效

    /**
     * 默认构造器
     */
    public Page() {
        this(1 , Integer.valueOf(Constant.getConfig("page.pageSize")));
    }

    /**
     *分页构造函数 ,默认第一页
     * @param request
     */
    public Page(HttpServletRequest request){
        this(request,Integer.valueOf(Constant.getConfig("page.pageSize")));
    }

    /**
     * 分页构造函数
     * @param request
     * @param defaultPageSize
     */
    public Page(HttpServletRequest request, int defaultPageSize){
        String pageNo = request.getParameter(pageNoParam);
        String pageSize = request.getParameter(pageSizeParam);
        String orderBy = request.getParameter(orderByParam);
        this.pageNo = StringUtils.isNotBlank(pageNo) ? Integer.parseInt(pageNo) : 1;
        this.pageSize = StringUtils.isNotBlank(pageSize) ? Integer.parseInt(pageSize): defaultPageSize;
        this.orderBy = orderBy;
    }

    /**
     * 构造方法
     * @param pageNo 当前页码
     * @param pageSize 分页大小
     */
    public Page(int pageNo, int pageSize) {
        this(pageNo, pageSize, 0);
    }

    /**
     * 构造方法
     * @param pageNo 当前页码
     * @param pageSize 分页大小
     * @param totalSize 数据条数
     */
    public Page(int pageNo, int pageSize, long totalSize) {
        this.pageNo = pageNo;
        this.pageSize = pageSize;
        this.totalSize = totalSize;
    }


    /**
     * 初始化参数
     */
    public void initialize(){
        //设置首页和尾页
        this.first = 1;
        this.last = (int)(totalSize / (this.pageSize < 1 ? 20 : this.pageSize));
        if (this.totalSize % this.pageSize != 0 || this.last == 0) {
            this.last++;
        }
        if (this.last < this.first) {
            this.last = this.first;
        }
        //设置当前页
        if (this.pageNo <= 1) {
            this.pageNo = this.first;
            this.firstPage=true;
        }
        if (this.pageNo >= this.last) {
            this.pageNo = this.last;
            this.lastPage=true;
        }
    }

    /**
     * 默认输出当前分页标签
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("<ul class=\"pagination\">");
        sb.append("<li class=\"page-first \"><a href=\"javascript:void(0)\" data-pageNo=\""+this.getFirst()+"\">«</a></li>");
        sb.append("<li class=\"page-pre \"><a href=\"javascript:void(0)\" data-pageNo=\""+this.getPrev()+"\">‹</a></li>");
        int pageNo = this.getPageNo();
        if(pageNo <=3){
            for(int i = 1; i< pageNo ;i++){
                sb.append("<li class=\"page-number\"><a href=\"javascript:void(0)\" data-pageNo=\""+i+"\">"+i+"</a></li>");
            }
            sb.append("<li class=\"page-number active\"><a href=\"javascript:void(0)\" data-pageNo=\"" + pageNo + "\">"+pageNo+"</a></li>");
            int lastPage = this.getTotalPage() > 5 ? 5: this.getTotalPage();
            for(int i = pageNo + 1; i <= lastPage;i++){
                sb.append("<li class=\"page-number\"><a href=\"javascript:void(0)\" data-pageNo=\"" + i + "\">"+i+"</a></li>");
            }
        }else if(this.getTotalPage() - pageNo <= 2){
            int firstPage = this.getTotalPage() - 4;
            for(int i = firstPage; i< pageNo ; i++){
                sb.append("<li class=\"page-number\"><a href=\"javascript:void(0)\" data-pageNo=\"" + i + "\">"+i+"</a></li>");
            }
            sb.append("<li class=\"page-number active\"><a href=\"javascript:void(0)\" data-pageNo=\"" + pageNo+ "\">"+pageNo+"</a></li>");
            for(int i = pageNo + 1; i <= this.getTotalPage();i++){
                sb.append("<li class=\"page-number\"><a href=\"javascript:void(0)\" data-pageNo=\"" + i + "\">"+i+"</a></li>");
            }
        }else {
            int firstPage = this.getPageNo() - 2;
            for(int i = firstPage; i < pageNo;i++){
                sb.append("<li class=\"page-number\"><a href=\"javascript:void(0)\" data-pageNo=\"" + i + "\">"+i+"</a></li>");
            }
            sb.append("<li class=\"page-number active\"><a href=\"javascript:void(0)\" data-pageNo=\"" + pageNo + "\">"+pageNo+"</a></li>");
            for(int i = pageNo + 1; i < pageNo + 3 ; i++){
                sb.append("<li class=\"page-number\"><a href=\"javascript:void(0)\" data-pageNo=\"" + i + "\">"+i+"</a></li>");
            }
        }
        sb.append(" <li class=\"page-next\"><a href=\"javascript:void(0)\" data-pageNo=\"" + this.getNext()+ "\">›</a></li>");
        sb.append("<li class=\"page-last\"><a href=\"javascript:void(0)\" data-pageNo=\"" + this.getLast() + "\">»</a></li>");
        sb.append(String.format("<li class=\"pagination-info\"><a>当前%s到%s条,共%s条</a></li></ul>" ,this.getFirstResult() + 1, this.getLastResult() , this.getTotalSize()));
        return sb.toString();
    }

    /**
     * 获取分页HTML代码
     * @return
     */
    public String getHtml(){
        return toString();
    }

    /**
     * 获取设置总数
     * @return
     */
    public long getTotalSize(){
        return totalSize;
    }

    /**
     * 设置数据总数
     * @param totalSize
     */
    public void setTotalSize(long totalSize) {
        this.totalSize = totalSize;
        if (pageSize >= totalSize){
            pageNo = 1;
        }
    }

    /**
     * 获取当前页码
     * @return
     */
    public int getPageNo() {
        return pageNo;
    }

    /**
     * 设置当前页码
     * @param pageNo
     */
    public void setPageNo(int pageNo) {
        this.pageNo = pageNo;
    }

    /**
     * 获取页面大小
     * @return
     */
    public int getPageSize() {
        return pageSize;
    }

    /**
     * 设置页面大小,最大为100条
     * @param pageSize
     */
    public void setPageSize(int pageSize) {
        this.pageSize = pageSize <= 0 ? 10 : pageSize > 100 ? 100 : pageSize;
    }

    /**
     * 首页索引
     * @return
     */
    public int getFirst() {
        return first;
    }

    /**
     * 尾页索引
     * @return
     */
    public int getLast() {
        return last;
    }

    /**
     * 获取页面总数
     * @return getLast();
     */
    public int getTotalPage() {
        return getLast();
    }

    /**
     * 是否为第一页
     * @return
     */
    public boolean isFirstPage() {
        return firstPage;
    }

    /**
     * 是否为最后一页
     * @return
     */
    public boolean isLastPage() {
        return lastPage;
    }

    /**
     * 上一页索引值
     * @return
     */
    public int getPrev() {
        if (isFirstPage()) {
            return pageNo;
        } else {
            return pageNo - 1;
        }
    }

    /**
     * 下一页索引值
     * @return
     */
    public int getNext() {
        if (isLastPage()) {
            return pageNo;
        } else {
            return pageNo + 1;
        }
    }

    /**
     * 得到起始条数
     * @return
     */
    public int getFirstResult(){
        int firstResult = (getPageNo() - 1) * getPageSize();
        if (firstResult >= getTotalSize()) {
            firstResult = 0;
        }
        return firstResult;
    }

    /**
     * 得到结尾条数
     * @return
     */
    public int getLastResult(){
        int lastResult = getFirstResult() + getPageSize() -1;
        if(lastResult > getTotalSize()){
            return Long.valueOf(getTotalSize()).intValue();
        }
        return lastResult;
    }

    /**
     * 获取本页数据对象列表
     * @return List<T>
     */
    public List<T> getList() {
        return list;
    }

    /**
     * 设置本页数据对象列表
     * @param list
     */
    public Page<T> setList(List<T> list) {
        this.list = list;
        initialize();
        return this;
    }

    /**
     * 获取查询排序字符串
     * @return
     */
    public String getOrderBy() {
        // SQL过滤,防止注入
        String reg = "(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|"
                + "(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)";
        Pattern sqlPattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE);
        if (sqlPattern.matcher(orderBy).find()) {
            return "";
        }
        return orderBy;
    }

    /**
     * 设置查询排序,标准查询有效
     */
    public void setOrderBy(String orderBy) {
        this.orderBy = orderBy;
    }

}
  • 借鉴:
    • Constant.getConfig(“page.pageSize”);这样都从配置文件里读取。
    • 通过泛型,Page里有一个List可以存放对应类型变量的类的List。
    • BaseModel中也有一个Page,使用来分页的。
  • Constant.java——扩大可配置性。
package com.doubleview.jeebase.support.config;

import com.google.common.collect.Maps;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Properties;

/**
 * 全局常量类
 */
public class Constant {

    private static Logger logger = LoggerFactory.getLogger(Constant.class);

    private static Properties props;

    private static String defaultLoadProperties = "jeebase.properties";//默认加载配置文件

    /**
     * 静态加载配置文件
     */
    static{
        props = new Properties();
        InputStream is = null;
            try {
                is = Thread.currentThread().getContextClassLoader().getResourceAsStream(defaultLoadProperties);
                props.load(is);
            } catch (IOException ex) {
                logger.warn("Could not load jeebase.properties {}" , ex.getMessage());
            } finally {
                IOUtils.closeQuietly(is);
            }
    }


    /**
     * 保存全局属性值(缓存)
     */
    private static Map<String, String> map = Maps.newHashMap();

    /**
     * 显示/隐藏
     */
    public static final String SHOW = "1";
    public static final String HIDE = "0";

    /**
     * 是/否
     */
    public static final String YES = "1";
    public static final String NO = "0";

    /**
     * 对/错
     */
    public static final String TRUE = "true";
    public static final String FALSE = "false";

    /**
     * 树形结构跟级id
     */
    public static final String rootId = "0";

    public static final String defaultCharset = "UTF-8";//默认编码

    /**
     * 获取配置属性
     * @param key
     * @return
     */
    public static String getConfig(String key) {
        String value = map.get(key);
        if (value == null){
            value = props.getProperty(key);
            map.put(key, value != null ? value : StringUtils.EMPTY);
        }
        return value;
    }

    /**
     * 获取管理端路径
     * @return
     */
    public static String getAdminPath() {
        return getConfig("adminPath");
    }

    /**
     * 获取前端路径
     * @return
     */
    public static String getFrontPath() {
        return getConfig("frontPath");
    }

    /**
     * 获取静态资源路径
     * @return
     */
    public static String getStaticPath(){
        return getConfig("staticPath");
    }
    /**
     * 获取产品名称
     * @return
     */
    public static String getProductName(){
        return getConfig("productName");
    }

    /**
     * 获取URL后缀
     * @return
     */
    public static String getUrlSuffix() {
        return getConfig("urlSuffix");
    }

    public static Integer getInt(String key) {
        return getInt(key, null);
    }

    public static  Integer getInt(String key, Integer defaultValue) {
        String value = getConfig(key);
        if (value != null)
            return Integer.parseInt(value.trim());
        return defaultValue;
    }

    public static Long getLong(String key) {
        return getLong(key, null);
    }

    public static Long getLong(String key, Long defaultValue) {
        String value = getConfig(key);
        if (value != null)
            return Long.parseLong(value.trim());
        return defaultValue;
    }


    public static Boolean getBoolean(String key) {
        return getBoolean(key, null);
    }


    public static Boolean getBoolean(String key, Boolean defaultValue) {
        String value = getConfig(key);
        if (value != null) {
            value = value.toLowerCase().trim();
            if ("true".equals(value))
                return true;
            else if ("false".equals(value))
                return false;
            throw new RuntimeException("The value can not parse to Boolean : "
                    + value);
        }
        return defaultValue;
    }

}
  • 借鉴:

    • IOUtils.closeQuietly(is);的安静关闭(忽略null和异常)流。
    • Maps.newHashMap();来自com.google.common.collect包。
    • private static Map< String, String> map = Maps.newHashMap();缓存导入的key-value。
    • 如下代码片:

      
       public static String getConfig(String key) {
          String value = map.get(key);
          if (value == null){
              value = props.getProperty(key);
              map.put(key, value != null ? value : StringUtils.EMPTY);
          }
          return value;
      }
    • 实现了缓存的效果。

    • 还有就是一些常用的key有专门的方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值