[项目实战] ibatis +spring+struts2+jquery.autocomplete实现产品自动补全功能(二) 附带源码...

这两天忙公司的项目,没有把项目的demo写出来。趁现在空闲,偷偷的写一下。奋斗
先上demo结构目录图:

大家看到了吧,项目层次分得很清楚。
config是spring和itatis的配置文件。接下来就是经典的mvc分层架构啦,bean ---- dao ---- service ----- action --- view。理论的东西,我就不多说了。下面我按照这个demo开发流程一步一步写出来:
一。在eclipse新建项目,导入jar包,有木有??!!!

二。集成spring和struts,web.xml文件配置如下:

<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>ctcoms</display-name> <description>A Java Forum System Based on Struts2</description> <!-- 加载spring 配置文件 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:config/spring*.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <!-- 定义Struts 2的FilterDispatcher的Filter --> <filter> <!-- 定义核心Filter的名字 --> <filter-name>struts2</filter-name> <!-- 定义核心Filter的实现类 --> <filter-class> org.apache.struts2.dispatcher.FilterDispatcher </filter-class> <!-- 设置编码 --> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> </filter> <!-- FilterDispatcher用来初始化Struts 2并且处理所有的Web请求 --> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- jsp等头文件的过滤器,解决乱码用 --> <filter> <filter-name>AddHeaderFilter</filter-name> <filter-class> org.mission.ctcoms.web.filter.AddHeaderFilter </filter-class> <init-param> <param-name>headers</param-name> <param-value>Content-Encoding=gzip</param-value> </init-param> </filter> <filter-mapping> <filter-name>AddHeaderFilter</filter-name> <url-pattern>*.gzjs</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>/login.jsp</welcome-file> <welcome-file>/index.jsp</welcome-file> </welcome-file-list> <error-page> <exception-type>java.lang.Exception</exception-type> <location>/error.jsp</location> </error-page> </web-app>


三。项目里,spring是用来配置数据库,事物管理,配置ibatis, 管理struts的action,管理dao层的bean,管理service的bean。相关的配置文件如下图:

四。在classpath路径下,新建struts.xml 和log4j.properties 文件,分别是 struts的映射文件 和 日志信息的配置。

五。把配置文件建好以后,就开始写代码了。这个demo业务很简单,只有一个bean,一张表就足够了。表的话 大家就自己建把,一个主键,一个产品名就OK啦。

bean的代码就不贴出来了,就是getter 和setting方法。

六。建立ibatis的sql配置文件,StoreProduct.xml如下:

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd"> <sqlMap namespace="StoreProduct"> <select id="findStoreProdctListNameForJson" parameterClass="java.lang.String" resultClass="java.lang.String" > select S.name from zy_store_product S where lower(S.name) LIKE lower('%$productName$%') </select> </sqlMap>

namespace 就是 sql的命名空间;findStoreProdctListNameForJson 为 调用sql 的唯一标识id; parameterClass 为参数类型,这里是传了一个产品名的字符串;resultClass为返回值类型。

select S.name from zy_store_product S where lower(S.name) LIKE lower('%$productName$%') 就是一句标准的sql语句了,$productName$ 代表参数。在这里可以执行任何复杂的sql语句,这就是

ibatis的灵活之处。ibatis的用法这里就不详细说了,以后有机会贴上一篇ibatis的增删查改的demo。

七。封装一个操作ibatis的类,用于简化ibatis的crud(增删查改)操作,每个dao都要继承这个类。BaseIbaitsDAO 如下:

package org.mission.ctcoms.ibatis; import java.util.Date; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.apache.struts2.ServletActionContext; import org.mission.ctcoms.exception.ApplicationException; import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport; /** * * @author 黄宇强 * @date 2011-8-5 上午09:27:06 * @description This base class is prepared for subclass to do CRUD easily. */ public class BaseIbaitsDAO extends SqlMapClientDaoSupport { private Logger log4j = Logger.getLogger(BaseIbaitsDAO.class); /** * 根据条件查询对象集合 * * @param sqlid * 对应IBATIS xml SQL_ID * @param paramObj * 参数对象 * @return */ @SuppressWarnings("unchecked") public <T> List<T> loadList(String sqlid, Object paramObj) { return (List<T>) getSqlMapClientTemplate() .queryForList(sqlid, paramObj); } /** * 根据条件查询对象所有数据 * * @param <T> * @param sqlid * 对应IBATIS xml SQL_ID * @return */ @SuppressWarnings("unchecked") public <T> List<T> loadList(String sqlid) { return (List<T>) getSqlMapClientTemplate().queryForList(sqlid); } /** * 根据ID查询ENTITY 对象 * * @param <T> * @param sqlid对应IBATIS * xml SQL_ID * @return <T> 实体对象 */ @SuppressWarnings("unchecked") public <T> T loadObject(String sqlid) { return (T) getSqlMapClientTemplate().queryForObject(sqlid); } /** * 根据ID查询ENTITY 对象 * * @param <T> * @param sqlid对应IBATIS * xml SQL_ID * @param id * 实体ID * @return <T> 实体对象 */ @SuppressWarnings("unchecked") public <T> T loadObject(String sqlid, String id) { return (T) getSqlMapClientTemplate().queryForObject(sqlid, id); } /** * 根据ID查询ENTITY 对象 * * @param <T> * @param sqlid对应IBATIS * xml SQL_ID * @param id * 实体ID * @return <T> 实体对象 */ @SuppressWarnings("unchecked") public <T> T loadObject(String sqlId, Long id) { return (T) getSqlMapClientTemplate().queryForObject(sqlId, id); } /** * 根据条件查询对象 * * @param <T> * @param sqlid对应IBATIS * xml SQL_ID * @param paramObj * 参数 * @return <T> 实体对象 */ @SuppressWarnings("unchecked") public <T> T loadObject(String sqlId, Object paramObj) { return (T) getSqlMapClientTemplate().queryForObject(sqlId, paramObj); } /** * 保存对象 * * @param sqlid * 对应IBATIS xml SQL_ID * @param entity * 保存的对象 */ public void save(String sqlid, Object entity) { getSqlMapClientTemplate().insert(sqlid, entity); } /** * 保存对象 * * @param sqlid * 对应IBATIS xml SQL_ID * @param entity * 保存的对象 */ public void save(String sqlid, Map<String, Object> entity) { getSqlMapClientTemplate().insert(sqlid, entity); } /** * 更新对象 * * @param sqlid * 对应IBATIS xml SQL_ID * @param entity * 修改对象 */ public void update(String sqlId, Map<String, Object> entity) { getSqlMapClientTemplate().update(sqlId, entity); } /** * 更新对象 * * @param sqlid * 对应IBATIS xml SQL_ID * @param entity * 修改对象 */ public void update(String sqlId, Object entity) { getSqlMapClientTemplate().update(sqlId, entity); } /** * 删除指定的对象 * * @param sqlId * @param object * 需要删除的对象 */ public void delete(String sqlId, Object object) { getSqlMapClientTemplate().delete(sqlId, object); } /** * 查询数据总条数 * * @param sqlid * @param object * @return */ public Long loadRecordCountObject(String sqlid, Object object) { log4j.info("sqlid====" + sqlid); return (Long) getSqlMapClientTemplate().queryForObject(sqlid, object); } /** * 查询数据总条数 * * @param sqlid * @param object * @return 返回Int */ public Integer loadRecordCount(String sqlid, Object object) { log4j.info("sqlid====" + sqlid); return (Integer) getSqlMapClientTemplate() .queryForObject(sqlid, object); } /** * @Title: findTNextId * @Description: 返回表中ID最大值加一 * @param: * @param tabName * 表名 * @return: * @returnType: Long * @throws */ public Long findTNextId(String tabName) { Long id = 0l; String seqName = tabName.substring(3) + "_S"; id = (Long) getSqlMapClientTemplate().queryForObject( "Common.findTNextId", seqName); if (id == null || id.equals(0l)) throw new ApplicationException("ID查询错误"); return id; } public Date findOracleSysdate() { return (Date) getSqlMapClientTemplate().queryForObject( "Common.findOracleSysdate", null); } }


八。用到spring ,是基于接口的编程了。分别实现 service、dao层的接口以及其实现类。需要注意的是,每个service、dao都要写进spring的相关配置文件去,实现spring对bean的管理。

九。crum的代码写好了,就到action层了。

package org.mission.ctcoms.web.action.storage; import java.util.List; import org.apache.log4j.Logger; import org.mission.ctcoms.business.storage.IStoreProductService; import org.mission.ctcoms.web.code.BaseAction; public class StorageProductAction extends BaseAction { /** * */ private static final long serialVersionUID = 1L; private Logger log4j = Logger.getLogger(StorageProductAction.class); private IStoreProductService storeProductService; private List<String> content; //传到前台显示用 private String productName; // 产品名 public String findStoreProdctListNameForJson() { try { String newProductName = new String(productName.getBytes("ISO-8859-1"),"utf-8"); // !!!解决参数乱码 List<String> list = storeProductService.findStoreProdctListNameForJson(newProductName); this.setContent(list); } catch (Exception e) { log4j.error("findStoreProdctListNameForJson error", e); } return SUCCESS; } public Logger getLog4j() { return log4j; } public void setLog4j(Logger log4j) { this.log4j = log4j; } public IStoreProductService getStoreProductService() { return storeProductService; } public void setStoreProductService(IStoreProductService storeProductService) { this.storeProductService = storeProductService; } public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } public List<String> getContent() { return content; } public void setContent(List<String> content) { this.content = content; } }

然后,该action查询到的数据库数据是以json方传递到前台的,所以该action注册到struts的配置文件如下:

<?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> <package name="json-storage" extends="json-default"> <action name="findStoreProdctListNameForJson" method="findStoreProdctListNameForJson" class="storageProductAction"> <result type="json"> <param name="root">content</param> </result> </action> </package> <constant name="struts.action.extension" value="do" /> </struts>


其中 content是json的标识,与action的content和稍后提及的jquery调用 相对应。extends="json-default" 是继承 struts-json插件的方法。


注: 该action 继承了封装好了的BaseAction,该类如下:

package org.mission.ctcoms.web.code; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.log4j.Logger; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; /** * * @author 黄宇强 * @date 2011-8-5 上午09:25:04 * @description 抽象类 */ public class BaseAction extends ActionSupport { /** * */ private static final long serialVersionUID = -4025716041310497629L; private Logger log4j = Logger.getLogger(BaseAction.class); public String jsonString; public void outJsonString(String str) { getResponse().setContentType("text/javascript;charset=UTF-8"); outString(str); } public void outString(String str) { try { PrintWriter out = getResponse().getWriter(); out.write(str); } catch (IOException e) { e.printStackTrace(); log4j.error("out print failed:" + e); } } public void outXMLString(String xmlStr) { getResponse().setContentType("application/xml;charset=UTF-8"); outString(xmlStr); } /** * 获得request * * @return */ public HttpServletRequest getRequest() { return ServletActionContext.getRequest(); } /** * 获得response * * @return */ public HttpServletResponse getResponse() { return ServletActionContext.getResponse(); } /** * 获得session * * @return */ public HttpSession getSession() { return getRequest().getSession(); } /** * 获得servlet上下文 * * * * @return */ public ServletContext getServletContext() { return ServletActionContext.getServletContext(); } public String getRealyPath(String path) { return getServletContext().getRealPath(path); } }


十。最后一步了,就是到前台页面。如何调用jquery.autocomplete,这个很简单,下载官方的demo下来,很容易就看明白了。贴出jsp的实现页面:

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>产品自动补全</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <script type="text/javascript" src="jquery/jquery.js"></script> <script type="text/javascript" src="jquery/jquery.autocomplete.js"></script> <link rel="Stylesheet" type="text/css" href="jquery/jquery.autocomplete.css" /> <script type="text/javascript"> var v_product_Store ; $().ready(function() { $("#productName").autocomplete("findStoreProdctListNameForJson.do", { //当用户输入关键字的时候 ,通过 url的方式调用action的findStoreProdctListNameForJson方法 minChars: 1, //最小显示条数 max: 12, //最大显示条数 autoFill: false, dataType : "json", //指定数据类型的渲染方式 extraParams: { productName: function() { return $("#productName").val(); //url的参数传递 } }, //进行对返回数据的格式处理 parse: function(data) { var rows = []; for(var i=0; i<data.length; i++) { rows[rows.length] = { data:data[i], value:data[i], //result里面显示的是要返回到列表里面的值 result:data[i] }; } return rows; }, formatItem: function(item) { //没有特殊的要求,直接返回了 return item; } }); }); </script> </head> <body> <div> 产品名: <input type="text" id="productName" /> </div> </body> </html>


OK!搞定!再看一下效果图:

有什么问题,欢迎大家多多交流。上学的时候就不喜欢写作文,写完这篇博客就累趴了。但是能记录下自己编程道路下的点点滴滴 与大家分享,也是件乐事。写得不好的话,还请“砖家”们手下留情。。(ˇˍˇ)

源码地址 :http://download.csdn.net/source/3497182

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值