`
allwefantasy
  • 浏览: 45756 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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

阅读更多

 

         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

  结果页面:

 

   整个功能添加的流程相当简洁。分页,用户权限验证等都已经通过封装由系统自动完成。比如用户权限验证,在配置文件中 只要  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);
			}
 

 

 

 

 

 

 

   

 

    

 

 

 

 

 

 

 

  • 大小: 29 KB
分享到:
评论
1 楼 modiliany 2012-04-30  
sql或hql最好分离出去, 放到*.hbm.xml中较好吧

相关推荐

    海康威视设备网络SDK_V5.3.5.25(for Windows32) 内含SDK、开发文档 及Demo示例(C++、C#、Java)

    内含SDK、开发文档 及Demo示例(C++、C#、Java) 设备网络SDK是基于设备私有网络通信协议开发的,为后端设备(嵌入式网络硬盘录像机、视频服务器)、前端设备(网络摄像机、网络球机、IP模块)等产品服务的配套模块...

    新版Android开发教程.rar

    � 源代码完全开放,便于开发人员更清楚的把握实现细节,便于提高开发人员的技术水平,有利于开发 出 更具差异性的应用。 � 采用了对有限内存、电池和 CPU 优化过的虚拟机 Dalvik , Android 的运行速度比想象的要...

    单点登录源码

    └── zheng-demo -- 示例模块(包含一些示例代码等) ├── zheng-demo-rpc-api -- rpc接口包 ├── zheng-demo-rpc-service -- rpc服务提供者 └── zheng-demo-web -- 演示示例[端口:8888] ``` ### 技术...

    webtesting-action-classes:Serenity Dojo Web测试课程的示例代码

    这是在Java中使用JUnit和Serenity BDD的非常小的示例项目。 您可以将此项目用作自己项目的快速入门。 获取代码 Git: git clone https://github.com/serenity-bdd/serenity-junit-starter.git cd serenity-junit-...

    java源码api-RESO-WebAPI-Client-Java:用JAVA编写的RESOWebAPI开源参考客户端

    在运行测试或示例之前,您必须构建reso-web-api-client库并将其安装到本地maven存储库。 导航到库项目并执行maven install命令: cd lib/reso-web-api-client mvn install 依存关系 在构建期间,所有必需的依赖项都...

    JAVA_Thinking in Java(中文版 由yyc,spirit整理).chm

    13.19.12 滑杆和进度指示条 13.19.13 树 13.19.14 表格 13.19.15 卡片式对话框 13.19.16 Swing消息框 13.19.17 Swing更多的知识 13.20 总结 13.21 练习 第14章 多线程 14.1 反应灵敏的用户界面 14.1.1 从线程继承 ...

    xml执行java源码-spring-boot-docker:《动手玩Docker》示例代码:Docker+SpringBoot:快速搭建和部

    Web应用 0、你需要: JDK 1.8 : java -version Maven 3.0+ : mvn -v Git : git --version Source Code : Docker : docker version docker-machine ls docker-machine start docker-machine env eval $(docker-...

    Thinking in Java(中文版 由yyc,spirit整理).chm

    13.19.12 滑杆和进度指示条 13.19.13 树 13.19.14 表格 13.19.15 卡片式对话框 13.19.16 Swing消息框 13.19.17 Swing更多的知识 13.20 总结 13.21 练习 第14章 多线程 14.1 反应灵敏的用户界面 14.1.1 从线程继承 ...

    JavaCombat

    └─web-mvc-core 自研MVC框架核心代码 运行说明 运行命令如下: # 进入user-platform目录 cd user-platform mvn clean package -U java -jar . \u ser-web \t arget \u ser-web-v1-SNAPSHOT-war-exec.jar 相关...

    java 编程入门思考

    13.19.12 滑杆和进度指示条 13.19.13 树 13.19.14 表格 13.19.15 卡片式对话框 13.19.16 Swing消息框 13.19.17 Swing更多的知识 13.20 总结 13.21 练习 第14章 多线程 14.1 反应灵敏的用户界面 14.1.1 从线程继承 ...

    Java初学者入门教学

    13.19.12 滑杆和进度指示条 13.19.13 树 13.19.14 表格 13.19.15 卡片式对话框 13.19.16 Swing消息框 13.19.17 Swing更多的知识 13.20 总结 13.21 练习 第14章 多线程 14.1 反应灵敏的用户界面 14.1.1 从线程继承 ...

    java联想(中文)

    13.19.12 滑杆和进度指示条 13.19.13 树 13.19.14 表格 13.19.15 卡片式对话框 13.19.16 Swing消息框 13.19.17 Swing更多的知识 13.20 总结 13.21 练习 第14章 多线程 14.1 反应灵敏的用户界面 14.1.1 从线程继承 ...

    tinny-tiny-rack-app:一个示例,说明Ruby中的Web开发多么简单!

    当我第一次看到它时,来自.Net和Java的几行代码中的Web应用程序的想法就是一个启示。 但是,位于Rack之上的框架常常掩盖了这种简单的美。 该存储库是一个实验,可以剥离到最基本的层,然后以很小的增量进行构建,以...

    serenity-rest-starter

    获取代码Git: git clone https://github.com/serenity-bdd/serenity-rest-starter.gitcd serenity-rest-starter或只是文件。入门项目从Serenity和Cucumber开始的最佳位置是在Github( )上克隆或下载启动程序项目。...

    JAVA_Thinking in Java

    13.19.12 滑杆和进度指示条 13.19.13 树 13.19.14 表格 13.19.15 卡片式对话框 13.19.16 Swing消息框 13.19.17 Swing更多的知识 13.20 总结 13.21 练习 第14章 多线程 14.1 反应灵敏的用户界面 14.1.1 从线程继承 ...

    Thinking in Java简体中文(全)

    13.19.12 滑杆和进度指示条 13.19.13 树 13.19.14 表格 13.19.15 卡片式对话框 13.19.16 Swing消息框 13.19.17 Swing更多的知识 13.20 总结 13.21 练习 第14章 多线程 14.1 反应灵敏的用户界面 14.1.1 从线程继承 ...

    csb-sdk:CSB-SDK是由CSB(云服务总线)产品打开的,用于HTTP或Web服务API的客户端调用SDK。 它负责调用开放的API并签署请求信息

    使用上述SDK单元测试示例 其他HTTP-SDK,用于其他语言的实现,例如PHP,Go和Node.js 从源代码构建 # 1. download sourcefrom Github (once time only) git clone https://github.com/aliyun/csb-sdk.git cd csb-sdk ...

    Think in Java(中文版)chm格式

    13.19.12 滑杆和进度指示条 13.19.13 树 13.19.14 表格 13.19.15 卡片式对话框 13.19.16 Swing消息框 13.19.17 Swing更多的知识 13.20 总结 13.21 练习 第14章 多线程 14.1 反应灵敏的用户界面 14.1.1 ...

    apaw-practice:带弹簧的六角形建筑实例

    该项目是该主题的教学支持,也是遵循分层体系结构开发Web应用程序的实际示例。 代码状态 必要技术 Java Maven GitHub Travis-ci Sonarcloud Better Code Hub Slack Spring-boot Heroku OpenAPI :gear: 项目安装 ...

    java源码直接复制jsp-edu-java-jsp:供学习者练习使用servlet和jsps的JavaWeb应用程序的示例存根应用程序

    Web开发的示例项目 这个项目是一个有效的“存根”应用程序,供学习者用来开始。 使用这个存根 在 github.com 上 fork 这个项目,所以你有你自己的副本。 查找网页右上角的 Fork 按钮。 在页面中间或右下方,找到 URL...

Global site tag (gtag.js) - Google Analytics