运营平台框架整理(内部用)

1.页面入口的过滤字段定义:

<input name="filter_name_like" type="text" style="margin-left: 0px;100px;" class="box_ipt " value="$!filter_name_like"/>

 1)字段定义:统一用filter_开头,这样后面可以自动解析成需要过滤的字段,之后是filed名称,可以匹配到数据库里的字段,多单词的定义比如 userName 数据库里是user_name,这里可以直接写userName,后面会自动解析

 2)筛选条件:相等(eq),大于(gt),小于(lt),大于等于(ge),小于等于(le),模糊匹配(like),默认为相等 ,例如 filter_name

 3)value定义为name相同的名字,后续可以直接映射过来,方便查询和分页操作之后的回带

 4)分页部分的隐藏域中同样需要定义,方便分页的操作时可以把查询条件带上

<input type="hidden" name="filter_name_like"  value="$!filter_name_like"/>

2. 调度层Action

  1)实现modelDriven,方便后续增删改查的时候,相关value到bean的自动映射

public class AlarmCodeAction  extends BaseAction implements ModelDriven<AlarmCode> {

  2)在action的实现类里需要定义过滤的字段,以及SearchRet等常用的类型,get set方法

	/******************************** 页面映射信息  start***********************/
	public String filter_keyWord_like;
	public String filter_pageType_eq;
	public String filter_pageValue_like;
	public String filter_activeTime_ge;
	public String filter_endTime_le;
	public String filter_platform_eq;
	public String orderField="active_time"; //排序字段
	public String orderBy="desc";    //asc or desc
 	public String sendMsg="";
	public SearchRet sr;
	/********************************* 页面映射信息 end ************************/

  注:orderField和orderBy两个filed可以实现table中单击任意thead,实现按照该字段升序,降序的切换,后面会说到

 3)过滤方法:

public String list(){
        try{
            sr = service.list(request, AlarmCode.class, orderField, orderBy, curpage, pagesize, getLink());
        }catch(Throwable t){
            log.error("AlarmCodeAction|list|error:",t);
        }
        return "success";
    }

service会根据之前定义的filter开头的字段,自动解析request,省去了自己组装参数的事情,service是根据泛型自动解析的bean,也省去了service的开发,同时,新增修改删除也有泛型的实现方式,后面是代码

3.服务层

public class AlarmCodeService extends BaseService<AlarmCode>{

 自己相关业务的service实现baseService之后,增删改查的持久层操作自己就不用写了,BaseService代码片段如下

public class BaseService<T> {
    
    public SearchRet list(HttpServletRequest request,Class<T> clazz,String orderName,String orderBy,int curpage,int pagesize,String link){
        Pair<ArrayList<T>,Integer> pair = ConsoleDBUtil.queryPageList(clazz , true, DaoUtil.getConsoleUtf8(),PropertyFilterUtil.clazzNameToDBName(clazz.getSimpleName()) , null, PropertyFilterUtil.getParams(request), PropertyFilterUtil.getOrdersMap(orderName, orderBy), curpage, pagesize);
        SearchUtil su = new SearchUtil(pair.first,new ConvertService(),new Paging(pair.second, curpage, pagesize, link));
        SearchRet sr = su.searchNoPage();
        return sr;
    }
    public int insert(DBClientWrapper db,T o){
        int ret = ConsoleDBUtil.insert(db, o,null);
        return ret;
    }
    
    public int insert(T o){
        return insert(DaoUtil.getConsoleDB(),o);
    }
    public int update(DBClientWrapper db,T o,String [] updateFields,String [] whereFields){
        int ret = ConsoleDBUtil.update(db, o,updateFields , whereFields);
        return ret;
    }
    public int update(T o,String [] updateFields,String [] whereFields){
        int ret = ConsoleDBUtil.update(DaoUtil.getConsoleDB(), o,updateFields , whereFields);
        return ret;
    }
    //根据属性删除
    public int delete(DBClientWrapper db,T o,String [] whereFields){
        int ret = ConsoleDBUtil.delete(db, o, whereFields);
        return ret;
    }
可不看 可扩展

 BaseService会完成从页面的查询字段向数据库字段的映射,以及bean字段向数据库字段的映射保存等操作。

4.持久层

    依托现有bookUtil包下的consoleDB实现,可忽略

5.table支持按任意字段的升序,降序以及分页

<table width="100%" border="0" cellspacing="0" cellpadding="0" class="list_tb">
			<tr>
				<td width="100" class="toptd"  style="cursor:pointer;" onclick="javascript:toggleOrder('id');">ID</td>
				<td width="100" class="toptd"  style="cursor:pointer;" onclick="javascript:toggleOrder('model_type');">模板类型</td>
				<td width="100" class="toptd"  style="cursor:pointer;" onclick="javascript:toggleOrder('name');">绑定ID</td>
				<td width="100" class="toptd"  style="cursor:pointer;" onclick="javascript:toggleOrder('name');">名称</td>
				<td width="100" class="toptd"  style="cursor:pointer;" onclick="javascript:toggleOrder('priority');">优先级</td>
				<td width="100" class="toptd"  style="cursor:pointer;" onclick="javascript:toggleOrder('start_time');">发布时间</td>
				<td width="100" class="toptd"  style="cursor:pointer;" onclick="javascript:toggleOrder('end_time');">结束时间</td>
				<td width="100" class="toptd">操作</td>
		    </tr>

  如上,click方法里传入参数即对应的数据库字段名称

function toggleOrder(field){
	$('[name=orderField]').val(field);
	var orderby = $('[name=orderBy]').val();
	if(orderby=="desc"){
		$('[name=orderBy]').val('asc');
	}else{
		$('[name=orderBy]').val('desc');
	}
	$('#hideform').submit();
}

  引入这段js,即实现查询form的提交,之后如上面action定义所说,会自动完成排序的切换,同时,在分页部分的隐藏域中定义这两个字段,分页点击的时候可以保持排序方式不变

6.任务池

     背景介绍,据上次的统计,目前运营平台有28个定时任务在不停的执行,实现方式基本是各自开线程,在Action里或者spring配置文件里启动(这两种启动方式都需要手动触发,即访问到相关模块的时候才会触发),执行周期及逻辑方式各样,不方便维护,and,如果集中执行的时候会对系统性能造成冲击

新建了一个任务调度池,统一管理,支持相对周期的定时,绝对时间的定时,以及单词的异步执行。可以在运营平台搜TaskPoolCenter.java

相应代码如下:

public class TaskPoolCenter {
    
    private static Logger log = Logger.getLogger("service");
    
    private static int coreTaskNumber = 1;
    private static int maxTaskNumber = 3;
    private static long keepAlivetime = 50L;
    private static int capacity = 5;
    
    /******************************周期执行可以调用  相对时间 **********************************/
    public static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2); 
    
    /** 只是执行一次可以调用  有界队列存储任务  此拒绝策略 提供简单的反馈控制机制,能够减缓新任务的提交速度。 **/
    public static final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
            coreTaskNumber, maxTaskNumber, keepAlivetime,
            TimeUnit.MICROSECONDS, new ArrayBlockingQueue<Runnable>(capacity),
            new ThreadPoolExecutor.CallerRunsPolicy());
    
    public static Timer timer = new Timer();

    public static void init(){
        scheduleTimerTask(new NewUserBagTask(),1,1,0,24,TimeUnit.HOURS);//每天凌晨发送当天的bid新手包到zhiwei
        log.info("TaskPoolCenter|started");
    }
    /**
     * 周期执行某个任务
     * @param t
     * @param scehduleTime
     * @param unit
     */
    public static void schedule(Thread t,long scehduleTime,TimeUnit unit){
        scheduler.schedule(t, 6, TimeUnit.SECONDS); 
    }
    /**
     * 以绝对时间 周期 执行定时任务
     * @param task
     * @param hour
     * @param minute
     * @param second
     * @param period 间隔周期 毫秒数
     */
    public static void scheduleTimerTask(TimerTask task,int hour,int minute,int second,int delay,TimeUnit unit){
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, minute);
        calendar.set(Calendar.SECOND, second);
        Date date=calendar.getTime(); //每天零点把当天的bid推送过去
        if (date.before(new Date())) {
            int day = calendar.get(Calendar.DAY_OF_YEAR);
            calendar.set(Calendar.DAY_OF_YEAR, day+1);
            date = calendar.getTime();
        }
        timer.schedule(task, date, unit.toMillis(delay));
    }
    /**
     * 单次任务的异步执行
     * @param t
     */
    public static void execute(Thread t){
        threadPool.submit(t);
    }

 不推荐以后继续用Timer及TimerTask实现定时任务,原因有

     1:Timer只创建了一个线程。当你的任务执行的时间超过设置的延时时间将会产生一些问题。

     2:Timer创建的线程没有处理异常,因此一旦抛出非受检异常,该线程会立即终止。

  如果有绝对时间的定时任务可以参考quartz.xml里的配置实现。

7.前端的页面验证:

引入jquery.validate.js 简单的配置一下类似这样,可以参考demo.htm及demo.js里的实现

	$("#edit_demo").validate({
		rules: {
			    name: {
				    required: true,
				    minlength: 2
			    },
			    tlength:{
			    	required:true,
			    	minlength:5,
			    	maxlength:10
			    },
			valid: {
				required: true,
				number:true,
				range:[5,10]
			}
		},
		messages: {
			name: {
				required: "名称不能为空",
				minlength: "名称需多于两个字"
			},
			valid: {
				required: "测试数字不能为空",
				number: "输入内容必须为数字",
				range:"数字在5到10之间",
			},
			tlength: {
				required: "不能为空",
				minlength: "最小为5个字符",
				maxlength: "最多为10个字符"
			}
		}
	});

  不用手动的验证,可以实现实时的页面提示,不用alert,支持时间,整数,浮点字符长度等多种方式的验证

原文地址:https://www.cnblogs.com/ysuzhaixuefei/p/5073228.html