欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

12cd.com 开发分享-- 示例代码 以及 如何简化JAVA WEB开发

程序员文章站 2022-06-05 15:53:30
...

 

         12cd.com 是我08年十二月份由我负责开发的第一个比较正式的项目。

         当时比较理想化 也比较雄心。网站是做原创音乐分享的,典型的web2.0,功能 实现 包括 流媒体,多种Flash播放器,实时搜 索,微博,用户空间装扮,论坛,新闻发布等

 

         呵呵 题外话了,现在回顾一下,心得是:精心思考如何构建你的基础设施,可以极大的简化java web的开发。

 

         通常使用SSH2开发,会有下面几部分组成:

 

            view                  

                              这一层你可以使用多种视图技术,比如freemarker 或者jsp.在12cd中使用的jsp,不过                                              freemarker在项目中也有使用。    

            controller   

                               这一层是直接和用户交互的一层。

             service                

                               对dao调用,封装一些业务操作。比如加好友就属于一个逻辑操作

             dao                      

                               对hibernate第二次封装

    
      12cd的开发思路是,构建薄dao,富service。使用struts Action类的方法作为相应用户的单元,一个类封装一系列相应,类属性对应输入。所有输出到页面的数据都通过request.
      有程序有真相。现在我们看看经过一些基础设施建设后,一个程序员要给12cd添加一个查看自己相册列表的功能,他的开发流程是怎么样的。

 

 

        假设我们是刚开始添加相册功能(ps:如果假设相册方面的功能之前已经有程序实现,现在只是简单添加自己查看相册列表的功能,那么下面的类应该已经存在,无需新建,你只要到相应的类上添加相应的方法即可

 

        首先 需要创建一个Controller,一个Serivce,我们分别叫他们AlbumsManager和AlbumsService(ps:项目中所有Controller   统一加Manager后缀,Service同理)。

        先瞧瞧Service的代码:

 

    package com.snail.example.album;

import java.util.Map;

import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import com.snail.base.impl.SBase_Service;
import com.snail.commons.util.FunnyHashMap;
import com.snail.component.beans.Xiangce;
import com.snail.component.viewbeans.Page;
@Service("s_albums_service")
public class AlbumsService extends SBase_Service{
	
	/*
	 * 结果值包含下面几个key值
	 * list               一个包含结果POJO的List集合
	 * pager              一个分页对象  如现在是第几页 总共数据库有多少条记录等
	 * paginate paginate  分页结果 比如  << 上一页  1 2 3 ... 7 8 下一页 >> 使用freemarker模版,所以样式可以自定义
	 * new_paginate       现在12cd 统一使用的一个新的默认分页模板
	 */
	public Map find_all(Page page) 
	{
		//hql 形式查询
		
		String hql="from Xiangce xangce where xiangce.huiyuan=:huiyuan order by xiangce.addTime desc";
		Map result=find_results(page, null, hql, new FunnyHashMap("huiyuan",page.getHuiyuan()));
		
		//criteria 形式查询
		    
		   result=find_results(page, Xiangce.class, new Order[]{Order.desc("addTime")},
		    		                                 new Criterion[]{Restrictions.eq("huiyuan", page.getHuiyuan())});
		    
//         detachedCretiria
		   DetachedCriteria _dc=DetachedCriteria.forClass(Xiangce.class);
		   _dc.add(Restrictions.eq("huiyuan", page.getHuiyuan()));
		   _dc.addOrder(Order.desc("addTime"));
		   
		    result=find_results(page, _dc);
		
		//此外 DAO类还提供了 远程hibernate session 的调用接口 ,原生sql,hibernte 命名查询等接口  如不过上面的三种查询
	    //已经基本能够满足12cd.com大大部分查询
		//	     s_base_dao.hibernate_session_execute(MethodObject.Function(new Object(){
		//	    	 public List find_xiangces(Session session)
		//	    	 {
		//	    		 
		//	    	 }
		//	     }, null));
		    
		return result;
	}


}
 

    Ok ,就这么多,实际上上面的代码讲了三种形式的查询,真正只要使用其中的一种即可,也就是说一个Service的方法可以简化到三行代码。精简之后的话你应该是只要添加如下一个方法即可

 

 

public Map find_all(Page page) 
	{
		String hql="from Xiangce as x where x.huiyuan=:huiyuan order by x.addTime desc";
		return find_results(page, null, hql, new FunnyHashMap("huiyuan",page.getHuiyuan()));
	}

   总共五行代码(注意service里面的注解使用,这样就不需要到spring配置文件中添加配置了)。

 

 

 

   完成service后,我们还需要一个额外的步骤 在所有Controller的基类SBaseManager 注册我们新添加的Service类

 

    

public class SBaseManager extends ActionSupport implements Preparable
@Resource(name="s_albums_service")
protected AlbumsService s_albums_service;

 

    也就添加了两行代码 不是很麻烦对吧

 

 

    现在让我们看看 controller类的写法:

 

 

package com.snail.example.album;
import com.snail.base.impl.SBaseManager;

@Controller("albums_manager")
public class AlbumsManager extends SBaseManager{
	
	
	public String index()
	{
		//将结果放在request中 这样 后续的jsp页面可以使用
		request("results",s_albums_service.find_all(page()));
		return default_view_dir("index");
	}
	
    //这个方法不是强制的。不过方便找到渲染结果jsp页面
	private String default_view_dir(String viewName)
	{
		view_url = "/com/snail/example/albums/"+viewName+".jsp";
		return SUCCESS;
	}

}
 

 

   Controller 中 default_view_dir 方法是每个Controller都推荐提供的,主要是方便找到页面渲染,自动不全jsp页面路径。

   这么看来Controller层的一个方法也就五行代码 。很少 对不对? 如果你接着要写查看某个相册所有照片的功能,连类也不用新建,直接在这个controller上添加一个show方法就可以了。哈哈

 

   接着看看 我们的 View层,jsp页面 看下面:

 

 

<%@ page language="java" import="java.util.*" pageEncoding="GBK"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <link href="css/index.css" rel="stylesheet" type="text/css" />
    <title>用户相册列表</title>
  </head>
  
  <body>
    <div class="content">
    <s:iterator value="#request.results['list']">
        <p><s:property value="xiangCeMing"/></p>
   </s:iterator>
   </div>
    <div class="page">
       <s:property value="#request.results['new_paginate']" escape="false"/>
    </div>
  </body>
</html>
 

 

   其中

 

 <s:property value="#request.results['new_paginate']" escape="false"/>

 

  这一句是输出分页标签的.很简单吧(个人不觉的比 <%=will_paginate @albums%> 麻烦多少。呵呵 开个玩笑)

 

  额 还忘了一件事情,struts的的url配置我们是使用xml文件配置的,为什么不用注解呢? 额 因为当时我们这个项目是08年年底12月开始的,那个时候好像struts2才刚出来没多久。当时作开发也是一边看教程 一边看开发的(有点像以前javaeye用rails改写的时候人手一册 Web开发敏捷之道一样 哈哈)

 

 看看配置文件里面的都要添加什么:

 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
    <!--我们的配置文件继承自  snail_auth_base 也就是默认会有登录验证拦截器。如果你某个Action不需要登录验证,那么
                     在写Action标签的时候加上
        <interceptor-ref name="normalStack"></interceptor-ref>即可
     -->
	<package name="salbums" extends="snail_auth_base"
		namespace="/salbums">
     
    <action name="index" method="index" class="albums_manager">
       <result>${view_url}</result>
    </action>
	</package>
	
	
</struts>
 

 

    不多 也就三行代码(红色标识)。Ok ,所有流程走完了。看看我们的结果吧

 

  额 现在访问一下 :

   http://www.12cd.com/salbums/index.action

  结果页面:

12cd.com 开发分享-- 示例代码 以及 如何简化JAVA WEB开发
            
    
    博客分类: 12cd分享系列 WebJava敏捷开发HibernateAjax 

 

   整个功能添加的流程相当简洁。分页,用户权限验证等都已经通过封装由系统自动完成。比如用户权限验证,在配置文件中 只要  package extends="snail_auth_base"就可以

  实现登录拦截。如果用户没有的登录访问这个url,那么就会被导向到登录页面。如果不需要权限或者想自己在代码中判断只需要加一行红色的配置。

 

 

<action name="index" method="index" class="albums_manager">
        <interceptor-ref name="normalStack"></interceptor-ref>
       <result>${view_url}</result>
    </action>

 

 

   那么这一切是如何实现的?

   我们看看12cd的四层结构(下面我只是讨论了三层)的基类是如何组织的。

    Controller

        Controller层 当然我把显示用的View层也算到了Controller层了。这一层对应的就是一个*Manager类和一张JSP页面。但是如何对Contoller进行划分是个难题,方法很多,比如根据功能,相同功能的比如登录,注册放在一个 Controller中。12cd采用的主体是根据Hibernate的POJO类,或者说是根据表来进行划分的(以资源来组织Contoller),辅助性的根据功能命名一些类。比如上面的相册,就是针对POJO Xiangce 设计的一个Controller.这有点像Rails里面Resources的处理方式,如果无法都用resrouce,还提供match 这种路由方式给你。

 

    所有Contoller类都必须继承我提供的这个基类,基本代码如下

SBaseManager

public class SBaseManager extends ActionSupport implements Preparable
	{
		
		@Resource(name="s_huiyuan_service")
		protected SHuiyuan_Service s_huiyuan_service;
		@Resource(name="s_comments_service")
		protected SComments_Service s_comments_service;
		@Resource(name="s_albums_service")
		protected AlbumsService s_albums_service;
																			 --end
		//常用数据 不允许在子类中重复定义
		protected String view_url="";
		protected HttpServletRequest request = null;
		protected HttpServletResponse response = null;
		protected HttpSession session = null;
		protected ActionInvocation invocation = null;
		public Huiyuan huiyuan = null;
		protected String pageMethod;
		protected Integer currentPage;
		protected Integer pageSize;
		protected Integer totalRows;
		protected ServletContext sc = null;
		protected String request_url=null;
		protected String request_url_referer=null;
		protected String div_id=null;
		protected String render_type;
		protected ICacheClient cache_client=null;
		//通常进行一个操作有三个状态 view->进入操作页面
		//                      process->处理页面
		//                      
		protected String s_operate_type=null;
		//header 常量定义//
		protected static final String ENCODING_PREFIX = "encoding";
		protected static final String NOCACHE_PREFIX = "no-cache";
		protected static final String ETAG_PREFIX = "ETag";
		protected static final String LASTMODIFIED_PREFIX = "Last-Modified";
		protected static final String ENCODING_DEFAULT = "GBK";
		protected static final boolean NOCACHE_DEFAULT = true;

		//content-type 定义 //
		protected static final String TEXT_TYPE = "text/plain";
		protected static final String JSON_TYPE = "application/json";
		protected static final String XML_TYPE = "text/xml";
		protected static final String HTML_TYPE = "text/html";
		
		//----------------------------------实用函数功能区-------------------------------------------- begin
		public boolean empty(Object _object)
			{
				return SUtils.empty(_object);
			}
		
		
		 public  boolean ajax_request()
			 {
				 String _temp=(String)request.getHeader("X-Requested-With");
				 return _temp.equalsIgnoreCase("XMLHttpRequest");
			 }
		
		 protected HttpServletRequest request(String key, Object object)
				{
					request.setAttribute(key, object);
					return request;
				}
		 public Page page()
				{
					Page page=new Page(currentPage, pageSize, pageMethod,"",construct_request_url(),construct_request_parameters(),huiyuan,request,session,sc,invocation);
					page.setDiv_id(div_id);
					return  page;
				}

			protected Object request(String key)
				{
					return request.getAttribute(key);
				}
			protected Object parameter(String key)
				{
					return request.getParameter(key);
				}

			protected HttpSession session(String key, Object object)
				{
					session.setAttribute(key, object);
					return session;
				}

			protected Object session(String key)
				{
					return session.getAttribute(key);
				}
			protected void s_config_page_size(Integer default_num)
			{
				if (this.pageSize == null)
					{
						this.pageSize = default_num;
					}
			}
			
		 
		 //如果是ajax请求则解码,否则返回原内容
		public String soft_decode(String _content,String..._char_set)
			{
				if(empty(_content))return "";
				if(ajax_request())
				return SUtils.decode(_content, _char_set);
				else
					return _content;
				
			}
	
		//强制解码
		public String force_decode(String _content,String..._char_set)
			{
				if(empty(_content))return "";
				return SUtils.decode(_content, _char_set);
			}
		
		
		/*
		 * 如果 _render_type 不为空且是渲染字符串,那么将_result_code_or_str_content(如果存在)
		 * 渲染到浏览器,并且返回null
		 * 否则 返回_result_code_or_str_content(如果存在,否则返回success)
		 * 
		 */
		protected String render(String _render_type,String _result_code_or_str_content)
			{
				Map<String,ResultConfig> _results=invocation.getProxy().getConfig().getResults();
				List _result_codes=new ArrayList(_results.keySet());
				if(!empty(_render_type)&&_render_type.equals(Constant.render_string)) 
					{
						if(empty(_result_code_or_str_content))return null;
						out(_result_code_or_str_content) ;return null;
					}
				return (empty(_result_code_or_str_content)||!_result_codes.contains(_result_code_or_str_content))?SUCCESS:_result_code_or_str_content;
			}
		
		protected void out(String s)
			{
				 
				response.setContentType(TEXT_TYPE+";charset="+ENCODING_DEFAULT);
				PrintWriter out = null;
				try
					{
						out = response.getWriter();
						out.print(s);
						out.flush();
						out.close();
					} catch (IOException e)
					{
						e.printStackTrace();
					}
				
			}
		
		
		
		/*
		 *   基础配置选项
		 */
		
		 public void prepare() throws Exception
			{
				this.request = ServletActionContext.getRequest();
				this.response = ServletActionContext.getResponse();
				this.session = this.request.getSession();
				this.invocation = ServletActionContext.getContext().getActionInvocation();
				this.sc = ServletActionContext.getServletContext();
				String _temp=construct_request_parameters();
				this.request_url = construct_request_url() +(empty(_temp)?"":("?" + construct_request_parameters()));
				this.request_url_referer=request.getHeader("Referer");
				cache_client=CacheManager.getCacheClient(CacheManager.memecached);
			    huiyuan=(Huiyuan)session(Constant.SESSION_KEY);
			}
		
		 protected String construct_request_parameters()
				{
					StringBuffer param = new StringBuffer();
					Map<String, String[]> zzMap = request.getParameterMap();
					if (zzMap != null)
						{
							for (String s : zzMap.keySet())
								{
									if (s.equals("pageSize") || s.equals("currentPage") || s.endsWith("pageMethod")||s.endsWith("totalRows"))
										{

										} else
										{
											String[] value = zzMap.get(s);
											for (String val : value)
												{
													param.append("&" + s + "=" + val);
												}
										}

								}
						}
					return param.toString();
				}
		

			protected String construct_request_url()
				{
					String url = "";
					String path = request.getContextPath();
					String actionName = invocation.getProxy().getActionName();
					String nameSpace = invocation.getProxy().getNamespace();
					if (StringUtils.isNotEmpty(nameSpace)&&nameSpace.length()>1)
						{
							url = url + path + nameSpace;

						}
					if (StringUtils.isNotEmpty(actionName))
						{
							url = url + "/" + actionName + ".action";
						}
					return url;
				}
		
	}
  

 

        上面去掉了一些Set/Get 方法。代码其实很简单。无非就是做了一些简单的封装。最简单的比如,

        request.之前如果你需要使用的话必须像这样:

 

request.setAttribute("key","value");
 

        但是经过简化继承这个基类,你在子类中就可以这么写:

 

 request("key","value")
       

        掰下手指,节省了多少个字符?上面的示例代码中也有例子:

 

request("results",s_albums_service.find_all(page()));

 

     其实通过基类继承,我们可以很简单的模拟PHP的函数编程,而不是通过静态类调用静态方法。 

 

     在SBaseManager中 很重要的一个是page 方法。

 

     java

 public Page page()
				{
					Page page=new Page(currentPage, pageSize, pageMethod,"",construct_request_url(),construct_request_parameters(),huiyuan,request,session,sc,invocation);
					page.setDiv_id(div_id);
					return  page;
				}

    该方法在Controller构造了一个Page对象传递给Service层,这也是为什么Service层可以实现自动分页。不过比较麻烦的是这就要求每个Service方法的签名都必须有一个Page。额 是否可以通过AOP解决呢?  


      Service

    Service层,基本对应Contoller层,封装一些数据库存取和逻辑相关的东东。在12CD中基本都和Controller一一对应。对于功能有交集的一些Service,我们把公用的方法放到了一个公共的Service类中。

 

   下面看看基类的设计:

 

   package com.snail.base.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;

import com.snail.base.inter.ISBaseDAO;
import com.snail.base.util.PagingFactory;
import com.snail.base.util.SUtils;
import com.snail.cache.impl.CacheManager;
import com.snail.cache.inter.ICacheClient;
import com.snail.commons.constant.Constant;
import com.snail.commons.page.action.PageBean;
import com.snail.commons.page.action.PageUtil;
import com.snail.commons.util.MethodObject;
import com.snail.component.beans.Huiyuan;
import com.snail.component.viewbeans.Page;
public class SBase_Service 
	{
	   @Resource(name = "s_base_dao")
		protected ISBaseDAO s_base_dao;
         
	   protected ICacheClient cache_client=CacheManager.getCacheClient(CacheManager.memecached);
       
	   //假设集合只有一个元素。如果是则返回该元素,法则返回null
	   protected Object uniqueResult(List lists)
			{
		  	   	return empty(lists)?null:lists.get(0);
			}
	 
	   //分页                             --begin
	   
	   //如果不需要排序或者不需要条件 将_orders和_criterions置为空数组即可,不可为null;
	   public Map  find_results(Page _contex,Class _clzz,Order[] _orders,Criterion[] _criterions)
		   {
			   int _totalRows=0;
			   if(!empty(_contex.getTotalRows())&&_contex.getTotalRows()>0) _totalRows=_contex.getTotalRows();
			   else{ _totalRows=s_base_dao.find_entities_count_with_criteria(_clzz, _orders, _criterions);}
				
			    PageBean pager = PageUtil.getPager(_contex.getCurrentPage(), _contex.getPageMethod(), _contex.getPageSize() == null ? 10 : _contex.getPageSize(), _totalRows);
				Map<String, Object> map = new HashMap<String, Object>();
				map.put("list", s_base_dao.find_entities_with_criteria(_clzz, _orders, _criterions, pager.getStartRow(), pager.getPageSize()));
				map.put("pager", pager);
				map.put("paginate", quick_page(_contex,pager));
				map.put("new_paginate", quick_page_new(_contex, pager));
				return map;
		   }
	   
	   //hql 查询,如果 _hql_count为""或者为null,那么层序会自动猜测统计语句
	   public Map  find_results(Page _contex,String _hql_count,String _hql_select,Map _params)
		   {
			   int _totalRows=0;
			   if(!empty(_contex.getTotalRows())&&_contex.getTotalRows()>0) _totalRows=_contex.getTotalRows();
			   else{

				   String _temp=_hql_count;
				   if(empty(_hql_count))_temp=SUtils.auto_create_hql_count(_hql_select);
				   _totalRows=s_base_dao.find_entities_count_with_hql(_temp,_params);}
				
			    PageBean pager = PageUtil.getPager(_contex.getCurrentPage(), _contex.getPageMethod(), _contex.getPageSize() == null ? 10 : _contex.getPageSize(), _totalRows);
				Map<String, Object> map = new HashMap<String, Object>();
				map.put("list", s_base_dao.find_entities_with_hql(_hql_select, _params, pager.getStartRow(), pager.getPageSize()));
				map.put("pager", pager);
				map.put("paginate", quick_page(_contex,pager));
				map.put("new_paginate", quick_page_new(_contex, pager));
				return map;
		   }
	   
	   //detachedCretiria查询
	   public Map  find_results(Page _contex,DetachedCriteria _dc)
		   {
			   int _totalRows=0;
			   if(!empty(_contex.getTotalRows())&&_contex.getTotalRows()>0) _totalRows=_contex.getTotalRows();
			   else{ _totalRows=s_base_dao.find_entities_count_with_detached_criteria(_dc);}
				
			    PageBean pager = PageUtil.getPager(_contex.getCurrentPage(), _contex.getPageMethod(), _contex.getPageSize() == null ? 10 : _contex.getPageSize(), _totalRows);
				Map<String, Object> map = new HashMap<String, Object>();
				map.put("list", s_base_dao.find_entities_with_detached_criteria(_dc, pager.getStartRow(), pager.getPageSize()));
				map.put("pager", pager);
				map.put("paginate", quick_page(_contex,pager));
				map.put("new_paginate", quick_page_new(_contex, pager));
				return map;
		   }
	   
	   // 输出分页内容(无模板) 格式为  首页 上一页 (下拉框) 下一页 最后一页
	   public String quick_page(Page _context,PageBean _pager, List... _config)
			{
				List list = _config.length == 0 ? new ArrayList() : _config[0];
				list.add(0, _context.getRequest_params());
				return PagingFactory.paging(_context.getRequest_url(), _pager, list);
			}
	   //输出分页内容(有模板) 格式为  首页 上一页 2 3 4 下一页 最后一页 统计
		public String quick_page_new(Page _context,PageBean _pager, List... _config)
		{
			List list = _config.length == 0 ? new ArrayList() : _config[0];
			list.add(0, _context.getRequest_params());
			return PagingFactory.paging_new(_context.getRequest_url(), _pager, list);
		}
		// ajax 版本 输出分页内容(无模板) 格式为  首页 上一页 (下拉框) 下一页 最后一页
		public String quick_ajax_page(Page _context,PageBean _pager, String _div_id,List... _config)
			{
				List list = _config.length == 0 ? new ArrayList() : _config[0];
				list.add(0, _context.getRequest_params());
				return PagingFactory.paging_ajax(_div_id, _context.getRequest_url(), _pager, list);
			}
		
		//ajax 版本 输出分页内容(有模板) 格式为  首页 上一页 2 3 4 下一页 最后一页 统计 
		public String quick_ajax_page_new(Page _context,PageBean _pager, String _div_id,List... _config)
			{
				List list = _config.length == 0 ? new ArrayList() : _config[0];
				list.add(0, _context.getRequest_params());
				return PagingFactory.paging_ajax_new(_div_id, _context.getRequest_url(), _pager, list);
			}
		public Map config_ajax_page(Page _context,Map map,String div_id,boolean isNewAjax,List...config)
		{
			if(empty(div_id)){
				map.put("new_paginate",quick_page_new(_context,(PageBean)map.get("pager"),config));
			}else{
				if(isNewAjax)
				{
					map.put("new_paginate", quick_ajax_page_new(_context,(PageBean)map.get("pager"),div_id,config));
				}
				else
				{
				   map.put("paginate", quick_ajax_page(_context,(PageBean)map.get("pager"),div_id,config));
				}
			}
			return map;
		}
	   // 														--end
	   

	   //该方法返回的Page对象适合不分页的存取,或者只是为了做占位符
	   public Page page(int num)
		   {
			   Page page=new Page(1, num, "","","","",null,null,null,null,null);
			   return  page;
		   }
	   public boolean empty(Object _object)
		   {
			   return SUtils.empty(_object);
		   }
	   

		
       
	}
 

    这个基类重点做了下面几件事情:

 

  1.   实现自动分页
  2.  提供了多个封装好的查询方法

 DAO

 DAO层。DAO层在12CD属于很薄的一层。只有一个接口和一个实现类。我觉得针对每个POJO设计一个DAO类是很愚蠢  的方式,或者说是一种过度设计吧。12cd项目中使用了一个泛型DAO.提供的功能基本够用

 

 下面是12CD的DAO接口

 

 

public interface ISBaseDAO<T>
	{
//基本增删改查             									--begin
		  
		public T find_entity(Class _clzz,Serializable _id);
		
		public void update_entity(T _entity);
		public void save_entity(T _entity);
		public void merge_entity(T _entity);
		public void save_update_entity(T _entity);
		public void save_update_entities(Collection<T> _entities);
		
		public  void delete_entity(T _entity);
		
		//dateType,如果是删除某一段日期的记录,必须指明是类型,timeStamp或者dateTime
		//可以使用Constant中的日期,例如Contant.time_stamp 和Contant.date_time,默认为time_stamp
		public  void delete_entities(String _hql,Map _params,String..._dateType);
		public  void delete_entities(Collection _entities);
		
//																			 --end
		
//查询  ps :推荐使用detached_crieria或者hql查询                    									--begin
		//使用criteria查询
		public List find_entities_with_criteria(Class clzz,Order[] _orders,Criterion[] _criterions,int _start,int _num);
		public List find_all_entities_with_criteria(Class clzz,Order[] _orders,Criterion[] _criterions);
		public int  find_entities_count_with_criteria(Class clzz,Order[] _orders,Criterion[] _criterions);
		//兼容之前的代码,使用不定参数
		public List find_entities_with_criteria(Class clzz,int _start,int _num,Order[] _orders,Criterion... criterions);
		
		//使用detached_criteria查询
		public List find_entities_with_detached_criteria(DetachedCriteria _dc,int _start,int _num);
		public List find_all_entities_with_detached_criteria(DetachedCriteria _dc);
		public int find_entities_count_with_detached_criteria(DetachedCriteria _dc);

		//使用hql查询
		public List find_entities_with_hql(String _hql,Map _params,int _start,int _num);
		public List find_all_entities_with_hql(String _hql,Map _params);
		public int find_entities_count_with_hql(String _hql,Map _params);
		
		//集合过滤查询,比如需要查出歌曲点击数大于30的歌曲,
		//可以用find_entities_with_filter(huiyuan.gequs,"this.dianJiShu>30")
		public List find_entities_with_filter(Collection _collections,String _filter,int _start,int _num);
		
		//hibernate 命名查询
		public List find_entities_with_named_query(String _query,Map _params,int _start,int _num);
//																			--end
		
//批量更新

         public int update_entities_with_hql(String _query,Map _params);

//统计或者有用的方法                    				--begin
		
		
		//由于hibernate必须初始化集合(即将集合中元素从数据库中的
		//取出)才能统计集合元素数目。所以额外添加该方法用于提高效率。
		//使用的时候注意
		public int count_collection_size(Collection _collection);
		
		
		//获得命名查询的待执行hql语句
		public String hql(String _name_query_string_name);
		 
//		                                                                     --end

//较为底层的方法														--begin
//通过mo回调获得session执行相应操作
public Object hibernate_session_execute(MethodObject _mo);
//执行本地sql语句
public List find_entities_with_native_sql(String hql,Map params,int start,int num);
public List find_entities_with_native_sql(String hql,Map params);
		 
//		                                                                     --end
	}
 

     个人觉得这些方法大部分情况下已经够用了。

 

     下面的内容是关于搜索方面的。12CD因为使用的的是Hibernate,搜索自然使用了以Lucene为基础的Compass.

     Compass和Hibenate可以很好的结合。目前我是将Compass的注解直接写在Hibernate的Pojo文件上的,Hibernate映射则使用xml配置文件。

 

    只要将Compass集成到Spring配置 就可以实现自动实时索引。基本不用担心太多。12cd提供了一个查询类,大家可以参考一下。(因为代码比较长,无关的代码已经被删除)

 

package com.snail.commons.service;

import static com.snail.commons.util.MethodObject.Function;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.compass.core.Compass;
import org.compass.core.CompassCallback;
import org.compass.core.CompassException;
import org.compass.core.CompassHit;
import org.compass.core.CompassHits;
import org.compass.core.CompassQuery;
import org.compass.core.CompassQueryBuilder;
import org.compass.core.CompassSession;
import org.compass.core.CompassTemplate;
import org.compass.core.CompassQuery.SortPropertyType;
import org.compass.core.CompassQueryBuilder.CompassBooleanQueryBuilder;
import org.compass.core.support.search.CompassSearchCommand;
import org.compass.core.support.search.CompassSearchResults;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Service;

import com.snail.commons.page.action.PageBean;
import com.snail.commons.util.DFUtil;
import com.snail.commons.util.FunnyHashMap;
import com.snail.commons.util.FunnyList;
import com.snail.commons.util.MethodObject;
import com.snail.component.beans.Searchstatistics;
import com.snail.component.viewbeans.Page;
import com.snail.search.action.AdvancedCompassSearchHelper;

@Service("search_service")
public class SearchService extends Base_Service
	{

		private final static Logger logger = Logger.getLogger(SearchService.class);

		

		
		
		public Map find(final Page page, final String keywords, final String[] clzz_names, final Map<String, String> highlightFields,
				final List<CompassQuery> queries)
			{

				return base_find(page, keywords, clzz_names, highlightFields, Function(new Object()
					{
						public CompassQuery construct_queries(CompassQueryBuilder cqb)
							{
								CompassBooleanQueryBuilder cbqb = cqb.bool();
								for (CompassQuery cq : queries)
									{
										cbqb.addMust(cq);

									}
								cbqb.addMust(cqb.queryString(keywords).toQuery());
							
								return empty(clzz_names) ? cbqb.toQuery() : cbqb.toQuery().setAliases(clzz_names);

							}

					}));

			}

		
		
		public Map base_find(final Page page, final String keywords, final String[] clzz_names, final Map<String, String> highlightFields, final MethodObject mo)
			{

				return process_index(new CompassCallback()
					{

						public Object doInCompass(CompassSession session) throws CompassException
							{
								Map result = new HashMap();
								List list = new ArrayList();
								AdvancedCompassSearchHelper search = new AdvancedCompassSearchHelper(compass, page.getPageSize());

								if (!empty(highlightFields))
									{
										search.setHighlightFields(highlightFields);
									}

								CompassQueryBuilder cq = session.queryBuilder();
								CompassQuery cqb = (CompassQuery) mo.invoke(cq);

								int totalRows = search.search(new CompassSearchCommand(cqb, 0)).getTotalHits();
								PageBean pageBean = convert_page_to_pagebean(page, totalRows);
								CompassSearchCommand csc = new CompassSearchCommand(cqb, pageBean.getCurrentPage() - 1);

								CompassSearchResults results = search.search(csc);

								CompassHit[] hits = results.getHits();

								for (int i = 0; i < hits.length; i++)
									{
										CompassHit hit = hits[i];

										list.add(new FunnyHashMap("data", hit.getData(), "hit", hit));

									}

							//	logger.info("结果总数:" + results.getTotalHits() + "==页数" + results.getPages().length + "当前页面=>" + pageBean.getCurrentPage() + "/"
							//			+ ((nil(csc.getPage())) ? "nil" : csc.getPage().intValue()));
								logger.info("结果总数:" + results.getTotalHits());
								result.put("list", list);
								result.put("hits", hits);
								result.put("search_time", results.getSearchTime());
								result.put("paginate", empty(page.getAjax()) ? quick_page(page, convert_page_to_pagebean(page, results.getTotalHits()))
										: quick_ajax_page(page, convert_page_to_pagebean(page, results.getTotalHits()), page.getDiv_id()));
								result.put("new_paginate", quick_page_new(page, convert_page_to_pagebean(page, results.getTotalHits())));
								result.put("pager", pageBean);
								return result;
							}
					});
			}


		

		@Resource(name = "compass")
		Compass compass;
		@Resource(name = "compassTemplate")
		CompassTemplate compassTemplate;

		

	}
 

    示例使用:

 

  public String music_search()

			{	
				
				
				String[] str ={ "Gequ" };
				List k_list = new ArrayList();
				config_page_size(24);
				Compass compass = search_service.getCompass();
				CompassQuery query = compass.queryBuilder().term("Gequ.gequKind",geQuKind);
				Map<String, String> hilights = new FunnyHashMap("Gequ","geQuMing");
				k_list.add(query);
				query = compass.queryBuilder().term("Gequ.shengHeZhuangTai",1);
				k_list.add(query);
				Map map = search_service.find(page(), keyword, str, hilights, k_list);

				request("search_map", map);
				
				return result(SUCCESS);
			}
 

 

 

 

 

 

 

   

 

    

 

 

 

 

 

 

 

  • 12cd.com 开发分享-- 示例代码 以及 如何简化JAVA WEB开发
            
    
    博客分类: 12cd分享系列 WebJava敏捷开发HibernateAjax 
  • 大小: 29 KB