BOS项目 批量导入(ocupload插件,pinyin4J)/POI解析Excel/Combobox下拉框/分区组合条件分页查询(ajax)/分区数据导出(Excel)

1.    区域批量导入功能

*Ajax不支持文件上传。

*上传并且不刷新上传页面原理:

Target到一个0,0,0的隐藏iframe里,造成一个没有刷新的假象

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <form target="myIframe" action="abc" method="post" enctype="multipart/form-data">  
  2.     <input type="file" name="myFile">  
  3.     <input type="submit" value="上传">  
  4. </form>  
  5. <iframe width="0" height="0" frameborder="0" name="myIframe"></iframe>    

*选择上传文件后自动上传(无上传按钮)原理:

文件输入框onchange事件 内容一变化就自动提交

1.1   一键上传插件使用

    将js文件复制到项目中

jQuery.ocupload-1.1.2.js

ocupload jquery 的应用代码

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. $(function () {    
  2.             $(".uploadfile").upload({    
  3.                 action: 'CourseXMLFileUploadHander.ashx',    
  4.                 name: 'xml',    
  5.                 params: {    
  6.                     'type''uploadCourseXMLFile',    
  7.                     'rand': Math.random()    
  8.                 },    
  9.                 onSelect: function (self, element) {    
  10.                     this.autoSubmit = false;    
  11.                     var re = new RegExp("(xml){1}quot;, "i");    
  12.     
  13.                     if (!re.test(this.filename())) {    
  14.                         alert("Only xml file can be uploaded");    
  15.                     }    
  16.                     else {    
  17.                         this.submit();    
  18.                     }    
  19.                 },    
  20.                 onSubmit: function (self, element) {    
  21.                     $('.uploadfile').hide();    
  22.                     $('#ajax_update').parent().show();    
  23.                     //alert('Uploading file...');    
  24.                 },    
  25.                 onComplete: function (data, self, element) {    
  26.                     $('#ajax_update').parent().hide();    
  27.                     $('.uploadfile').show();    
  28.                     self.resetInput();    
  29.                     try {    
  30.                         var ret = data;    
  31.                         if (ret.indexOf("exception") >= 0) {    
  32.                             alert('Upload file exception: ' + eval(data)[0].exception);    
  33.                         }    
  34.                         else {    
  35.                             showSuccess('File is successfully Load.');    
  36.     
  37.                             uploadSuccess(ret);    
  38.     
  39.                         }    
  40.                     } catch (err) {    
  41.                         alert(data);    
  42.                     }    
  43.                 }    
  44.             });    
  45.         });    

    在需要使用一键上传插件的页面引入js文件,提供一个元素,调用插件的upload方法,动态修改html元素

 简单示例

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <body>  
  2.     <input id="but1" type="button" value="上传">  
  3.     <script type="text/javascript">  
  4.         $("#but1").upload({  
  5.             action : 'abc',//form表单提交地址  
  6.             name : 'myFile'  
  7.         });  
  8.     </script>  
  9. </body>  

原理:js插件会动态的创建form表单和iframe

1.1   在region.jsp页面应用一键上传插件

    引入js文件

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <script  
  2.     src="${pageContext.request.contextPath }/js/jquery.ocupload-1.1.2.js"  
  3.     type="text/javascript"></script>  

    调用插件的upload方法

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. $(function(){  
  2.     $("#button-import").upload({  
  3.         action:'${pageContext.request.contextPath}/regionAction_importXls.action',  
  4.         name:'upload',  
  5.         onComplete: function (data, self, element) {   
  6.             if(data == '1'){  
  7.                 $.messager.alert("提示信息","导入数据成功!","info");  
  8.             }else{  
  9.                 $.messager.alert("提示信息","导入数据失败!","warning");  
  10.             }  
  11.         }  
  12.     });  
  13. });  

1.2   创建RegionAction提供importXls方法

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Controller  
  2. @Scope("prototype")  
  3. public class RegionAction extends BaseAction<Region> {  
  4.     private File upload;// 用于接收上传的文件  
  5.   
  6.     public void setUpload(File upload) {  
  7.         this.upload = upload;  
  8.     }  
  9.   
  10.     // 导入区域数据  
  11.     public String importXls() throws FileNotFoundException, IOException {  
  12.         System.out.println(upload);  
  13.         // 加载Excel文件到内存中  
  14.         HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(upload));  
  15.         // 读取第一个Sheet页  
  16.         HSSFSheet sheet = workbook.getSheetAt(0);  
  17.   
  18.         List<Region> list = new ArrayList<Region>();  
  19.         for (Row row : sheet) {  
  20.             // int rowNum = row.getRowNum();  
  21.             String value1 = row.getCell(0).getStringCellValue();// id  
  22.             String value2 = row.getCell(1).getStringCellValue();// provice  
  23.             String value3 = row.getCell(2).getStringCellValue();// city  
  24.             String value4 = row.getCell(3).getStringCellValue();// district  
  25.             String value5 = row.getCell(4).getStringCellValue();// postcode  
  26.             Region region = new Region(value1, value2, value3, value4, value5);  
  27.   
  28.             // 简码  
  29.             String shortcode = StringUtils.join(  
  30.                     PinYin4jUtils.getHeadByString(value2 + value3), "");  
  31.             // 城市编码  
  32.             String citycode = PinYin4jUtils.hanziToPinyin(value3, "");  
  33.             region.setShortcode(shortcode);  
  34.             region.setCitycode(citycode);  
  35.             list.add(region);  
  36.         }  
  37.         String f = "1";  
  38.         try {  
  39.             regionService.saveBatch(list);  
  40.         } catch (Exception e) {  
  41.             f = "0";  
  42.         }  
  43.         ServletActionContext.getResponse().setContentType(  
  44.                 "text/html;charset=UTF-8");  
  45.         ServletActionContext.getResponse().getWriter().print(f);  
  46.         return NONE;  
  47.     }  

配置struts.xml

*重复导入时出现主键冲突:

Duplicate entry ......

解决方法:使用saveOrUpdate

1.3   使用apache POI解析Excel文件

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 测试POI解析Excel文件 
  3.  */  
  4. public class POITest {  
  5.     @Test  
  6.     public void test1() throws FileNotFoundException, IOException {  
  7.         HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(new File(  
  8.                 "d:\\abc.xls")));  
  9.         HSSFSheet sheet = workbook.getSheetAt(0);//读取第一个sheet页  
  10.         for (Row row : sheet) {//循环读取每一行  
  11.             String v1 = row.getCell(0).getStringCellValue();//获得当前行的第一个单元格的文字内容  
  12.             String v2 = row.getCell(1).getStringCellValue();  
  13.             String v3 = row.getCell(2).getStringCellValue();  
  14.             String v4 = row.getCell(3).getStringCellValue();  
  15.             String v5 = row.getCell(4).getStringCellValue();  
  16.             System.out.println(v1 + " " + v2 + " "  +v3 + " " + v4 + " " + v5);  
  17.         }  
  18.     }  
  19. }  

Pinyin4J

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1.     @Test  
  2.     public void test1() {  
  3.         String city = "北京市";  
  4.         String province = "河北省";  
  5.         String city2 = "石家庄市";  
  6.         String district = "长安区";  
  7.   
  8.         // 城市编码 北京市-----》beijing  
  9.         String str1 = PinYin4jUtils.hanziToPinyin(  
  10.                 city.substring(0, city.length() - 1), "");  
  11.         System.out.println(str1);  
  12.   
  13.         String info = province.substring(0, province.length() - 1)  
  14.                 + city2.substring(0, city2.length() - 1)  
  15.                 + district.substring(0, district.length() - 1);  
  16.         // 简码河北省石家庄市长安区-----》hbsjzca  
  17.         String[] strings = PinYin4jUtils.getHeadByString(info);  
  18.         String join = StringUtils.join(strings, "");  
  19.         System.out.println(join);  
  20.     }  
  21. }  

utils工具类

[java]  view plain  copy
  1. package cn.itcast.bos.utils;  
  2.   
  3. import java.util.Arrays;  
  4.   
  5. import net.sourceforge.pinyin4j.PinyinHelper;  
  6. import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;  
  7. import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;  
  8. import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;  
  9. import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;  
  10.   
  11. public class PinYin4jUtils {  
  12.     /** 
  13.      * 将字符串转换成拼音数组 
  14.      *  
  15.      * @param src 
  16.      * @return 
  17.      */  
  18.     public static String[] stringToPinyin(String src) {  
  19.         return stringToPinyin(src, falsenull);  
  20.     }  
  21.   
  22.     /** 
  23.      * 将字符串转换成拼音数组 
  24.      *  
  25.      * @param src 
  26.      * @return 
  27.      */  
  28.     public static String[] stringToPinyin(String src, String separator) {  
  29.   
  30.         return stringToPinyin(src, true, separator);  
  31.     }  
  32.   
  33.     /** 
  34.      * 将字符串转换成拼音数组 
  35.      *  
  36.      * @param src 
  37.      * @param isPolyphone 
  38.      *            是否查出多音字的所有拼音 
  39.      * @param separator 
  40.      *            多音字拼音之间的分隔符 
  41.      * @return 
  42.      */  
  43.     public static String[] stringToPinyin(String src, boolean isPolyphone,  
  44.             String separator) {  
  45.         // 判断字符串是否为空  
  46.         if ("".equals(src) || null == src) {  
  47.             return null;  
  48.         }  
  49.         char[] srcChar = src.toCharArray();  
  50.         int srcCount = srcChar.length;  
  51.         String[] srcStr = new String[srcCount];  
  52.   
  53.         for (int i = 0; i < srcCount; i++) {  
  54.             srcStr[i] = charToPinyin(srcChar[i], isPolyphone, separator);  
  55.         }  
  56.         return srcStr;  
  57.     }  
  58.   
  59.     /** 
  60.      * 将单个字符转换成拼音 
  61.      *  
  62.      * @param src 
  63.      * @return 
  64.      */  
  65.     public static String charToPinyin(char src, boolean isPolyphone,  
  66.             String separator) {  
  67.         // 创建汉语拼音处理类  
  68.         HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();  
  69.         // 输出设置,大小写,音标方式  
  70.         defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);  
  71.         defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);  
  72.   
  73.         StringBuffer tempPinying = new StringBuffer();  
  74.   
  75.         // 如果是中文  
  76.         if (src > 128) {  
  77.             try {  
  78.                 // 转换得出结果  
  79.                 String[] strs = PinyinHelper.toHanyuPinyinStringArray(src,  
  80.                         defaultFormat);  
  81.   
  82.                 // 是否查出多音字,默认是查出多音字的第一个字符  
  83.                 if (isPolyphone && null != separator) {  
  84.                     for (int i = 0; i < strs.length; i++) {  
  85.                         tempPinying.append(strs[i]);  
  86.                         if (strs.length != (i + 1)) {  
  87.                             // 多音字之间用特殊符号间隔起来  
  88.                             tempPinying.append(separator);  
  89.                         }  
  90.                     }  
  91.                 } else {  
  92.                     tempPinying.append(strs[0]);  
  93.                 }  
  94.   
  95.             } catch (BadHanyuPinyinOutputFormatCombination e) {  
  96.                 e.printStackTrace();  
  97.             }  
  98.         } else {  
  99.             tempPinying.append(src);  
  100.         }  
  101.   
  102.         return tempPinying.toString();  
  103.   
  104.     }  
  105.   
  106.     public static String hanziToPinyin(String hanzi) {  
  107.         return hanziToPinyin(hanzi, " ");  
  108.     }  
  109.   
  110.     /** 
  111.      * 将汉字转换成拼音 
  112.      *  
  113.      * @param hanzi 
  114.      * @param separator 
  115.      * @return 
  116.      */  
  117.     public static String hanziToPinyin(String hanzi, String separator) {  
  118.   
  119.         // 创建汉语拼音处理类  
  120.         HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();  
  121.         // 输出设置,大小写,音标方式  
  122.         defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);  
  123.         defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);  
  124.   
  125.         String pinyingStr = "";  
  126.         try {  
  127.             pinyingStr = PinyinHelper.toHanyuPinyinString(hanzi, defaultFormat,  
  128.                     separator);  
  129.         } catch (BadHanyuPinyinOutputFormatCombination e) {  
  130.             // TODO Auto-generated catch block  
  131.             e.printStackTrace();  
  132.         }  
  133.         return pinyingStr;  
  134.     }  
  135.   
  136.     /** 
  137.      * 将字符串数组转换成字符串 
  138.      *  
  139.      * @param str 
  140.      * @param separator 
  141.      *            各个字符串之间的分隔符 
  142.      * @return 
  143.      */  
  144.     public static String stringArrayToString(String[] str, String separator) {  
  145.         StringBuffer sb = new StringBuffer();  
  146.         for (int i = 0; i < str.length; i++) {  
  147.             sb.append(str[i]);  
  148.             if (str.length != (i + 1)) {  
  149.                 sb.append(separator);  
  150.             }  
  151.         }  
  152.         return sb.toString();  
  153.     }  
  154.   
  155.     /** 
  156.      * 简单的将各个字符数组之间连接起来 
  157.      *  
  158.      * @param str 
  159.      * @return 
  160.      */  
  161.     public static String stringArrayToString(String[] str) {  
  162.         return stringArrayToString(str, "");  
  163.     }  
  164.   
  165.     /** 
  166.      * 将字符数组转换成字符串 
  167.      *  
  168.      * @param str 
  169.      * @param separator 
  170.      *            各个字符串之间的分隔符 
  171.      * @return 
  172.      */  
  173.     public static String charArrayToString(char[] ch, String separator) {  
  174.         StringBuffer sb = new StringBuffer();  
  175.         for (int i = 0; i < ch.length; i++) {  
  176.             sb.append(ch[i]);  
  177.             if (ch.length != (i + 1)) {  
  178.                 sb.append(separator);  
  179.             }  
  180.         }  
  181.         return sb.toString();  
  182.     }  
  183.   
  184.     /** 
  185.      * 将字符数组转换成字符串 
  186.      *  
  187.      * @param str 
  188.      * @return 
  189.      */  
  190.     public static String charArrayToString(char[] ch) {  
  191.         return charArrayToString(ch, " ");  
  192.     }  
  193.   
  194.     /** 
  195.      * 取汉字的首字母 
  196.      *  
  197.      * @param src 
  198.      * @param isCapital 
  199.      *            是否是大写 
  200.      * @return 
  201.      */  
  202.     public static char[] getHeadByChar(char src, boolean isCapital) {  
  203.         // 如果不是汉字直接返回  
  204.         if (src <= 128) {  
  205.             return new char[] { src };  
  206.         }  
  207.         // 获取所有的拼音  
  208.         String[] pinyingStr = PinyinHelper.toHanyuPinyinStringArray(src);  
  209.   
  210.         // 创建返回对象  
  211.         int polyphoneSize = pinyingStr.length;  
  212.         char[] headChars = new char[polyphoneSize];  
  213.         int i = 0;  
  214.         // 截取首字符  
  215.         for (String s : pinyingStr) {  
  216.             char headChar = s.charAt(0);  
  217.             // 首字母是否大写,默认是小写  
  218.             if (isCapital) {  
  219.                 headChars[i] = Character.toUpperCase(headChar);  
  220.             } else {  
  221.                 headChars[i] = headChar;  
  222.             }  
  223.             i++;  
  224.         }  
  225.   
  226.         return headChars;  
  227.     }  
  228.   
  229.     /** 
  230.      * 取汉字的首字母(默认是大写) 
  231.      *  
  232.      * @param src 
  233.      * @return 
  234.      */  
  235.     public static char[] getHeadByChar(char src) {  
  236.         return getHeadByChar(src, true);  
  237.     }  
  238.   
  239.     /** 
  240.      * 查找字符串首字母 
  241.      *  
  242.      * @param src 
  243.      * @return 
  244.      */  
  245.     public static String[] getHeadByString(String src) {  
  246.         return getHeadByString(src, true);  
  247.     }  
  248.   
  249.     /** 
  250.      * 查找字符串首字母 
  251.      *  
  252.      * @param src 
  253.      * @param isCapital 
  254.      *            是否大写 
  255.      * @return 
  256.      */  
  257.     public static String[] getHeadByString(String src, boolean isCapital) {  
  258.         return getHeadByString(src, isCapital, null);  
  259.     }  
  260.   
  261.     /** 
  262.      * 查找字符串首字母 
  263.      *  
  264.      * @param src 
  265.      * @param isCapital 
  266.      *            是否大写 
  267.      * @param separator 
  268.      *            分隔符 
  269.      * @return 
  270.      */  
  271.     public static String[] getHeadByString(String src, boolean isCapital,  
  272.             String separator) {  
  273.         char[] chars = src.toCharArray();  
  274.         String[] headString = new String[chars.length];  
  275.         int i = 0;  
  276.         for (char ch : chars) {  
  277.   
  278.             char[] chs = getHeadByChar(ch, isCapital);  
  279.             StringBuffer sb = new StringBuffer();  
  280.             if (null != separator) {  
  281.                 int j = 1;  
  282.   
  283.                 for (char ch1 : chs) {  
  284.                     sb.append(ch1);  
  285.                     if (j != chs.length) {  
  286.                         sb.append(separator);  
  287.                     }  
  288.                     j++;  
  289.                 }  
  290.             } else {  
  291.                 sb.append(chs[0]);  
  292.             }  
  293.             headString[i] = sb.toString();  
  294.             i++;  
  295.         }  
  296.         return headString;  
  297.     }  
  298.       
  299.     public static void main(String[] args) {  
  300.         // pin4j 简码 和 城市编码   
  301.         String s1 = "中华人民共和国";   
  302.         String[] headArray = getHeadByString(s1); // 获得每个汉字拼音首字母  
  303.         System.out.println(Arrays.toString(headArray));  
  304.           
  305.         String s2 ="长城" ;   
  306.         System.out.println(Arrays.toString(stringToPinyin(s2,true,",")));  
  307.           
  308.         String s3 ="长";  
  309.         System.out.println(Arrays.toString(stringToPinyin(s3,true,",")));  
  310.     }  
  311. }  

2.    区域分页查询

    修改region.jsp页面中datagrid的url地址

    在RegionAction中提供分页查询方法pageQuery

与上一天的代码重复需要提取到baseAction  

3.    重构分页代码

    在BaseAction中提取PageBean和DetachedCriteria对象

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. protected PageBean pageBean = new PageBean();  
  2. // 离线条件查询对象,用于包装查询条件  
  3. DetachedCriteria detachedCriteria = null;  

    在BaseAction中提供setPage和setRows方法

把分页ajax相应的两个参数row和page直接注入到上面提取的pageBean中

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public void setPage(int page) {  
  2.     pageBean.setCurrentPage(page);// 当前页码  
  3. }  
  4.   
  5. public void setRows(int rows) {  
  6.     pageBean.setPageSize(rows);// 每页显示记录数  
  7. }  

    在BaseAction的构造方法中创建离线条件查询对象,并且注入给PageBean

 构造方法获取实体类型后创建离线查询条件对象并注入到pageBean中

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public BaseAction() {  
  2.     // 获得父类(BaseAction) 类型  
  3.     ParameterizedType superclass = (ParameterizedType) this.getClass()  
  4.             .getGenericSuperclass();  
  5.     // 获得父类上的泛型数组  
  6.     Type[] typeArguments = superclass.getActualTypeArguments();  
  7.     // 获得实体类型  
  8.     Class<T> domainClass = (Class<T>) typeArguments[0];  
  9.     // 获得实体类型后创建离线条件查询对象  
  10.     detachedCriteria = DetachedCriteria.forClass(domainClass);  
  11.     pageBean.setDetachedCriteria(detachedCriteria);  
  12.     try {  
  13.         model = domainClass.newInstance();  
  14.     } catch (InstantiationException e) {  
  15.         e.printStackTrace();  
  16.     } catch (IllegalAccessException e) {  
  17.         e.printStackTrace();  
  18.     }  
  19. }  

    在BaseAction中抽取方法writePageBean2Json和writeListBean2Json

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 将PageBean序列化为json返回 
  3.  */  
  4. public void writePageBean2Json(PageBean pageBean, String[] excludes) {  
  5.     // 使用jsonlib将PageBean对象序列化为json数据  
  6.     JsonConfig jsonConfig = new JsonConfig();  
  7.     jsonConfig.setExcludes(excludes);  
  8.     String json = JSONObject.fromObject(pageBean, jsonConfig).toString();  
  9.   
  10.     ServletActionContext.getResponse().setContentType(  
  11.             "text/json;charset=UTF-8");  
  12.     try {  
  13.         ServletActionContext.getResponse().getWriter().print(json);  
  14.     } catch (IOException e) {  
  15.         e.printStackTrace();  
  16.     }  
  17. }  
  18.   
  19. /** 
  20.  * 将List序列化为json返回 
  21.  */  
  22. public void writeListBean2Json(List list, String[] excludes) {  
  23.     // 使用jsonlib将PageBean对象序列化为json数据  
  24.     JsonConfig jsonConfig = new JsonConfig();  
  25.     jsonConfig.setExcludes(excludes);  
  26.     String json = JSONArray.fromObject(list, jsonConfig).toString();  
  27.   
  28.     ServletActionContext.getResponse().setContentType(  
  29.             "text/json;charset=UTF-8");  
  30.     try {  
  31.         ServletActionContext.getResponse().getWriter().print(json);  
  32.     } catch (IOException e) {  
  33.         e.printStackTrace();  
  34.     }  
  35. }  

    在RegionAction中的分页查询

分页查询代码简化为3条

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 分页查询方法 
  3.  * @throws IOException  
  4.  */  
  5. public String pageQuery() throws IOException{  
  6.     regionService.pageQuery(pageBean);  
  7.     this.writePageBean2Json(pageBean, new String[]{"currentPage","pageSize","detachedCriteria","subareas"});  
  8.     return NONE;  
  9. }  

4.    分区添加功能

4.1   Combobox下拉框使用

方式一:给静态的select标签应用

方式二:使用input标签通过url动态获取数据(json)

textField:为"option"下拉显示的内容

valueField::为最终提交的value值

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <body>  
  2.     <!-- 方式一 -->  
  3.     <select class="easyui-combobox">  
  4.         <option value="1">河北省石家庄市桥西区</option>  
  5.         <option value="2">河北省石家庄市桥东区</option>  
  6.         <option value="3">河北省石家庄市长安区</option>  
  7.     </select>  
  8.       
  9.     <!-- 方式二 -->  
  10.     <input  
  11.      data-options="url:'${pageContext.request.contextPath }/json/data.json',  
  12.                 textField:'name',valueField:'id'"  
  13.      type="text" class="easyui-combobox"/>  
  14. </body>  

subarea分区页面的添加分区弹窗区域选择下拉框数据获取(模糊查询)

及添加分区功能

第一步:修改subarea.jsp页面中combobox的url地址

mode属性

定义了当文本改变时如何读取列表数据。设置为'remote'时,下拉列表框将会从服务器加载数据。

当设置为“remote”模式时,用户输入将被发送到名为'q'的HTTP请求参数到服务器检索新数据。

 

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <td>  
  2.     <input class="easyui-combobox" name="region.id"    
  3.                     data-options="mode:'remote',valueField:'id',textField:'name',  
  4.                     url:'${pageContext.request.contextPath }/regionAction_list.action'" />    
  5. </td>  

对应分区类也应增加与下拉栏textField对应的name属性(省市区)

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private String id;//编号  
  2. private String province;//省  
  3. private String city;//市  
  4. private String district;//区  
  5. private String postcode;//邮编  
  6. private String shortcode;//简码  
  7. private String citycode;//城市编码  
  8. private Set subareas = new HashSet(0);//区域对应的多个分区  
  9.   
  10. public String getName(){  
  11.     return province + city + district;  
  12. }  

第二步:在RegionAction中提供list方法查询区域数据

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private String q;//模糊查询参数     
  2. public void setQ(String q) {  
  3.     this.q = q;  
  4. }  
  5. /**  
  6.  *  查询所有区域返回json  
  7.  */  
  8. public String list(){  
  9.     List<Region> list = null;  
  10.     if(StringUtils.isNotBlank(q)){  
  11.         //根据q进行模糊查询  
  12.         list = regionService.findByQ(q.trim());  
  13.     }else{  
  14.         //查询所有  
  15.         list = regionService.findAll();  
  16.     }  
  17.     String[] excludes = new String[]{"subareas"};  
  18.     this.writeListBean2Json(list, excludes);  
  19.     return NONE;  
  20. }  

Service中:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2. public List<Region> findByQ(String q) {     
  3.     return regionDao.findByNameQuery("findByQ","%"+q+"%","%"+q+"%","%"+q+"%");  
  4. }  
baseIDaompl命名查询
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2. public List<T> findByNameQuery(String hqlName, Object... params) {  
  3.      List findByNamedQuery = this.getHibernateTemplate().findByNamedQuery(hqlName,params);  
  4.      return findByNamedQuery;  

对应*hbm.xml提供query hql语句

注意:命名查询配置语句中不能出现双引号" "会报错,因为语句是按字符串来提取的,xml配置+" "来拼接也不行

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <query name="findByQ">  
  2.     FROM Region WHERE city LIKE ? OR province LIKE ? OR district LIKE ?   
  3. </query>  

第三步:为保存按钮绑定事件

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <a id="save" icon="icon-save" href="#" class="easyui-linkbutton" plain="true" >保存</a>  
  2. <script type="text/javascript">  
  3.     $(function(){  
  4.         //为保存按钮绑定事件  
  5.         $("#save").click(function(){  
  6.             var v = $("#addForm").form("validate");  
  7.             if(v){  
  8.                 $("#addForm").submit();  
  9.             }  
  10.         });  
  11.     });  
  12. </script><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>  

第四步:创建一个SubareaAction,提供add方法用于添加分区

 略

5.    分区组合条件分页查询

基于datagrid的load方法实现组合条件分页查询

*带关联查询的分页查询转换json会出错

freemarker.template.TemplateModelException:

Method public Java.lang.Stringorg.apache.commons.lang.exception

.NestableRuntimeException.getMessage(int)threw an exception when invoked on net.sf.json.JSONException:

java.lang.reflect.InvocationTargetException

原因:关联对象延迟加载是代理对象无法转换成json数据

解决: 修改对应需关联对象hbm,xml文件的lazy属性为false 解决关联查询问题

[html]  view plain  copy
  1. <many-to-one name="region" class="cn.feibai.bos.domain.Region" fetch="select" lazy="false">  
  2.     <column name="region_id" length="32" />  
  3. </many-to-one>  

第一步:提供组合条件查询窗口

第二步提供一个工具方法,将form表单中的输入项转为json数据,提交参数

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. $.fn.serializeJson=function(){    
  2.            var serializeObj={};    
  3.            var array=this.serializeArray();  
  4.            $(array).each(function(){    
  5.                if(serializeObj[this.name]){    
  6.                    if($.isArray(serializeObj[this.name])){    
  7.                        serializeObj[this.name].push(this.value);    
  8.                    }else{    
  9.                        serializeObj[this.name]=[serializeObj[this.name],this.value];    
  10.                    }    
  11.                }else{    
  12.                    serializeObj[this.name]=this.value;     
  13.                }    
  14.            });    
  15.            return serializeObj;    
  16.        };   

第三步:为查询按钮绑定事件,调用datagrid的load方法,重写发起ajax请求,提交参数

目的:这样发起的查询是ajax请求,条件参数会缓存在页面.

ajax没有全部刷新页面所以对应分页查询的条件也不会丢失

方法:load       

参数:param

详情:

加载和显示第一页的所有行。如果指定了'param',它将取代'queryParams'属性。通常可以通过传递一些参数执行一次查询,通过调用这个方法从服务器加载新数据。


 

[javascript]  view plain  copy
  1. <!-- 查询分区 -->  
  2. <script type="text/javascript">  
  3.     //为查询按钮绑定事件  
  4.     $(function(){  
  5.         $.fn.serializeJson=function(){    
  6.             var serializeObj={};    
  7.             var array=this.serializeArray();  
  8.             $(array).each(function(){    
  9.                 if(serializeObj[this.name]){    
  10.                     if($.isArray(serializeObj[this.name])){    
  11.                         serializeObj[this.name].push(this.value);    
  12.                     }else{    
  13.                         serializeObj[this.name]=[serializeObj[this.name],this.value];    
  14.                     }    
  15.                 }else{    
  16.                     serializeObj[this.name]=this.value;     
  17.                 }    
  18.             });    
  19.             return serializeObj;    
  20.         };   
  21.         $("#btn").click(function(){  
  22.             //获取查询条件---一次获取所有的查询条件,将查询条件封装成json数据  
  23.             var params = $("#searchForm").serializeJson();  
  24.             //重新发起一次ajax请求,提交参数  
  25.             $("#grid").datagrid("load",params);  
  26.             //关闭查询窗口  
  27.             $("#searchWindow").window("close");  
  28.         });  
  29.     });  
  30. </script>  

第四步:改造SubareaAction中的pageQuery方法,加入组合条件分页查询逻辑

Restrictions  API

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 分页组合条件查询 
  3.  */  
  4. public String pageQuery() {  
  5.     DetachedCriteria subareaDC = pageBean.getDetachedCriteria();  
  6.     // 从模型对象中获取提交的查询参数  
  7.     String addresskey = model.getAddresskey();// 关键字  
  8.     // 单表查询  
  9.     if (StringUtils.isNotBlank(addresskey)) {  
  10.         // 添加查询条件,根据关键字进行模糊查询  
  11.         subareaDC.add(Restrictions.like("addresskey",  
  12.                 "%" + addresskey.trim() + "%"));  
  13.     }  
  14.     Region region = model.getRegion();  
  15.     // 多表查询  
  16.     if (region != null) {  
  17.         String province = region.getProvince();  
  18.         String city = region.getCity();  
  19.         String district = region.getDistrict();  
  20.         DetachedCriteria regionDC = subareaDC.createCriteria("region");  
  21.         if (StringUtils.isNotBlank(province)) {  
  22.             // 添加查询条件,根据省进行模糊查询  
  23.             regionDC.add(Restrictions  
  24.                     .like("province""%" + province + "%"));  
  25.         }  
  26.         if (StringUtils.isNotBlank(city)) {  
  27.             // 添加查询条件,根据省进行模糊查询  
  28.             regionDC.add(Restrictions.like("city""%" + city + "%"));  
  29.         }  
  30.         if (StringUtils.isNotBlank(district)) {  
  31.             // 添加查询条件,根据省进行模糊查询  
  32.             regionDC.add(Restrictions  
  33.                     .like("district""%" + district + "%"));  
  34.         }  
  35.     }  
  36.     subareaService.pageQuery(pageBean);  
  37.     String[] excludes = new String[] { "decidedzone""subareas" };  
  38.     this.writePageBean2Json(pageBean, excludes);  
  39.     return NONE;  
  40. }  

6.    分区数据导出功能(Excel提供下载)

第一步:修改subarea.jsp页面中导出按钮的事件 

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. function doExport(){  
  2.     //发起请求Action,查询所有分区数据,写到Excel文件中并提供下载  
  3.     window.location.href = "${pageContext.request.contextPath}/subareaAction_exportXls.action";  
  4. }  

第二步:在Action中提供exportXls方法

两种方法:

方式一:原始手动设置响应下载

文件名乱码工具类

[java]  view plain  copy
  1. import java.io.IOException;  
  2. import java.net.URLEncoder;  
  3.   
  4. import sun.misc.BASE64Encoder;  
  5.   
  6. public class FileUtils {  
  7.         /** 
  8.          * 下载文件时,针对不同浏览器,进行附件名的编码 
  9.          *  
  10.          * @param filename 
  11.          *            下载文件名 
  12.          * @param agent 
  13.          *            客户端浏览器 
  14.          * @return 编码后的下载附件名 
  15.          * @throws IOException 
  16.          */  
  17.         public static String encodeDownloadFilename(String filename, String agent)  
  18.                 throws IOException {  
  19.             if (agent.contains("Firefox")) { // 火狐浏览器  
  20.                 filename = "=?UTF-8?B?"  
  21.                         + new BASE64Encoder().encode(filename.getBytes("utf-8"))  
  22.                         + "?=";  
  23.                 filename = filename.replaceAll("\r\n""");  
  24.             } else { // IE及其他浏览器  
  25.                 filename = URLEncoder.encode(filename, "utf-8");  
  26.                 filename = filename.replace("+"," ");  
  27.             }  
  28.             return filename;  
  29.         }  
  30. }  
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 导出分区数据到Excel文件并提供下载 
  3.  *  
  4.  * @throws IOException 
  5.  */  
  6. public String exportXls() throws IOException {  
  7.     List<Subarea> list = subareaService.findAll();  
  8.     // 使用POI将查询的数据写入Excel文件中  
  9.     HSSFWorkbook workbook = new HSSFWorkbook();  
  10.     // 在工作表中创建一个sheet页  
  11.     HSSFSheet sheet = workbook.createSheet("分区数据");  
  12.     // 创建标题行  
  13.     HSSFRow headRow = sheet.createRow(0);  
  14.     // 创建单元格  
  15.     headRow.createCell(0).setCellValue("分区编号");  
  16.     headRow.createCell(1).setCellValue("关键字");  
  17.     headRow.createCell(2).setCellValue("地址");  
  18.     headRow.createCell(3).setCellValue("省市区");  
  19.     for (Subarea subarea : list) {  
  20.         // 创建数据行  
  21.         HSSFRow dataRow = sheet.createRow(sheet.getLastRowNum() + 1);  
  22.         String id = subarea.getId();  
  23.         String addresskey = subarea.getAddresskey();  
  24.         String position = subarea.getPosition();  
  25.         Region region = subarea.getRegion();  
  26.         dataRow.createCell(0).setCellValue(id);  
  27.         dataRow.createCell(1).setCellValue(addresskey);  
  28.         dataRow.createCell(2).setCellValue(position);  
  29.         if (region != null) {  
  30.             String province = region.getProvince();  
  31.             String city = region.getCity();  
  32.             String district = region.getDistrict();  
  33.             String info = province + city + district;  
  34.             dataRow.createCell(3).setCellValue(info);  
  35.         }  
  36.     }  
  37.   
  38.     String filename = "分区数据.xls";  
  39.     String agent = ServletActionContext.getRequest().getHeader("user-agent");//浏览器类型  
  40.     filename = FileUtils.encodeDownloadFilename(filename, agent );  
  41.       
  42.     //根据文件名称动态获得类型  
  43.     String contentType = ServletActionContext.getServletContext()  
  44.             .getMimeType(filename);  
  45.     // 通知客户端下载文件的类型  
  46.     ServletActionContext.getResponse().setContentType(contentType);  
  47.       
  48.     //指定以附件形式下载,指定文件名称  
  49.     ServletActionContext.getResponse().setHeader("content-disposition""attachment;filename=" + filename);  
  50.     // 通过输出流向客户端浏览器写Excel文件  
  51.     ServletOutputStream out = ServletActionContext.getResponse().getOutputStream();  
  52.     workbook.write(out);  
  53.     return NONE;  
  54. }  

方式二:通过struts2的stream结果集下载

思路百度自博客(http://xiaowei-qi-epro-com-cn.iteye.com/blog/2030671):

思路是,先创建一个输出流,将这个excel写入到输出流里面,然后再通过这个输出流来得到我们所需要的输入流.

使用了ByteArrayOutputStreamByteArrayInputStream...处理的思想是,HSSFWorkbook 写入ByteArrayOutputStream.然后用ByteArrayOutputStream来转换为字节流..然后再将字节流转换为ByteArrayInputStream ..至此,我们就在内存中将excel转换成了输入流

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <pre name="code" class="java">    private InputStream target;    
  2.     public InputStream getTarget() {    
  3.         return target;    
  4.     }   
  5.     //下载文件名,存在中文乱码    
  6.     private String downloadFileName;    
  7.     public String getDownloadFileName() throws UnsupportedEncodingException {    
  8.         // 处理中文乱码    
  9.         if(downloadFileName != null){    
  10.             return new String(downloadFileName.getBytes("GBK"),"ISO-8859-1");    
  11.         }    
  12.         return downloadFileName;    
  13.     }    
  14.     /** 
  15.      * 下载所有分区信息以xls格式 
  16.      * @return 
  17.      * @throws IOException  
  18.      */  
  19.     public String export() throws IOException{  
  20.         List<Subarea> list=subareaService.findAll();  
  21.         //把list写入excel文档  
  22.         HSSFWorkbook book=new HSSFWorkbook();  
  23.         HSSFSheet sheet = book.createSheet("全部分区详情");  
  24.         //创建初始标题行  
  25.         HSSFRow row = sheet.createRow(0);  
  26.         row.createCell(0).setCellValue("分拣编号");  
  27.         row.createCell(1).setCellValue("省市区");  
  28.         row.createCell(2).setCellValue("关键字");  
  29.         row.createCell(3).setCellValue("位置");  
  30.         //遍历list  
  31.         for (Subarea subarea : list) {  
  32.             HSSFRow createRow = sheet.createRow(sheet.getLastRowNum()+1);  
  33.             String id = subarea.getId();  
  34.             String nameInfo = subarea.getRegion().getName();  
  35.             String addresskey = subarea.getAddresskey();  
  36.             String position = subarea.getPosition();  
  37.             createRow.createCell(0).setCellValue(id);  
  38.             createRow.createCell(1).setCellValue(nameInfo);  
  39.             createRow.createCell(2).setCellValue(addresskey);  
  40.             createRow.createCell(3).setCellValue(position);  
  41.         }  
  42.         ByteArrayOutputStream out = new ByteArrayOutputStream();  
  43.         book.write(out);  
  44.         target = new ByteArrayInputStream(out.toByteArray());    
  45.         out.close();    
  46.         downloadFileName="分区详情.xls";          
  47.         return "download";  
  48.     }  
 
配置文件 
[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <!-- 分区 -->  
  2. <action name="subareaAction_*" class="subareaAction" method="{1}">  
  3.     <result name="subareaList">/WEB-INF/pages/base/subarea.jsp</result>           
  4.     <result name="download" type="stream">    
  5.         <!-- 设置响应头 -->    
  6.         <param name="contentDisposition">attachment;filename=${downloadFileName}</param>    
  7.         <!-- 确定流 -->    
  8.         <param name="inputName">target</param>    
  9.     </result>               
  10. </action>  

1.    区域批量导入功能

*Ajax不支持文件上传。

*上传并且不刷新上传页面原理:

Target到一个0,0,0的隐藏iframe里,造成一个没有刷新的假象

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <form target="myIframe" action="abc" method="post" enctype="multipart/form-data">  
  2.     <input type="file" name="myFile">  
  3.     <input type="submit" value="上传">  
  4. </form>  
  5. <iframe width="0" height="0" frameborder="0" name="myIframe"></iframe>    

*选择上传文件后自动上传(无上传按钮)原理:

文件输入框onchange事件 内容一变化就自动提交

 

 

1.1   一键上传插件使用

    将js文件复制到项目中

 jQuery.ocupload-1.1.2.js

ocupload jquery 的应用代码

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. $(function () {    
  2.             $(".uploadfile").upload({    
  3.                 action: 'CourseXMLFileUploadHander.ashx',    
  4.                 name: 'xml',    
  5.                 params: {    
  6.                     'type''uploadCourseXMLFile',    
  7.                     'rand': Math.random()    
  8.                 },    
  9.                 onSelect: function (self, element) {    
  10.                     this.autoSubmit = false;    
  11.                     var re = new RegExp("(xml){1}quot;, "i");    
  12.     
  13.                     if (!re.test(this.filename())) {    
  14.                         alert("Only xml file can be uploaded");    
  15.                     }    
  16.                     else {    
  17.                         this.submit();    
  18.                     }    
  19.                 },    
  20.                 onSubmit: function (self, element) {    
  21.                     $('.uploadfile').hide();    
  22.                     $('#ajax_update').parent().show();    
  23.                     //alert('Uploading file...');    
  24.                 },    
  25.                 onComplete: function (data, self, element) {    
  26.                     $('#ajax_update').parent().hide();    
  27.                     $('.uploadfile').show();    
  28.                     self.resetInput();    
  29.                     try {    
  30.                         var ret = data;    
  31.                         if (ret.indexOf("exception") >= 0) {    
  32.                             alert('Upload file exception: ' + eval(data)[0].exception);    
  33.                         }    
  34.                         else {    
  35.                             showSuccess('File is successfully Load.');    
  36.     
  37.                             uploadSuccess(ret);    
  38.     
  39.                         }    
  40.                     } catch (err) {    
  41.                         alert(data);    
  42.                     }    
  43.                 }    
  44.             });    
  45.         });    


    在需要使用一键上传插件的页面引入js文件,提供一个元素,调用插件的upload方法,动态修改html元素

 简单示例

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <body>  
  2.     <input id="but1" type="button" value="上传">  
  3.     <script type="text/javascript">  
  4.         $("#but1").upload({  
  5.             action : 'abc',//form表单提交地址  
  6.             name : 'myFile'  
  7.         });  
  8.     </script>  
  9. </body>  

原理:js插件会动态的创建form表单和iframe

 

1.1   在region.jsp页面应用一键上传插件

    引入js文件

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <script  
  2.     src="${pageContext.request.contextPath }/js/jquery.ocupload-1.1.2.js"  
  3.     type="text/javascript"></script>  

    调用插件的upload方法

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. $(function(){  
  2.     $("#button-import").upload({  
  3.         action:'${pageContext.request.contextPath}/regionAction_importXls.action',  
  4.         name:'upload',  
  5.         onComplete: function (data, self, element) {   
  6.             if(data == '1'){  
  7.                 $.messager.alert("提示信息","导入数据成功!","info");  
  8.             }else{  
  9.                 $.messager.alert("提示信息","导入数据失败!","warning");  
  10.             }  
  11.         }  
  12.     });  
  13. });  

1.2   创建RegionAction提供importXls方法

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Controller  
  2. @Scope("prototype")  
  3. public class RegionAction extends BaseAction<Region> {  
  4.     private File upload;// 用于接收上传的文件  
  5.   
  6.     public void setUpload(File upload) {  
  7.         this.upload = upload;  
  8.     }  
  9.   
  10.     // 导入区域数据  
  11.     public String importXls() throws FileNotFoundException, IOException {  
  12.         System.out.println(upload);  
  13.         // 加载Excel文件到内存中  
  14.         HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(upload));  
  15.         // 读取第一个Sheet页  
  16.         HSSFSheet sheet = workbook.getSheetAt(0);  
  17.   
  18.         List<Region> list = new ArrayList<Region>();  
  19.         for (Row row : sheet) {  
  20.             // int rowNum = row.getRowNum();  
  21.             String value1 = row.getCell(0).getStringCellValue();// id  
  22.             String value2 = row.getCell(1).getStringCellValue();// provice  
  23.             String value3 = row.getCell(2).getStringCellValue();// city  
  24.             String value4 = row.getCell(3).getStringCellValue();// district  
  25.             String value5 = row.getCell(4).getStringCellValue();// postcode  
  26.             Region region = new Region(value1, value2, value3, value4, value5);  
  27.   
  28.             // 简码  
  29.             String shortcode = StringUtils.join(  
  30.                     PinYin4jUtils.getHeadByString(value2 + value3), "");  
  31.             // 城市编码  
  32.             String citycode = PinYin4jUtils.hanziToPinyin(value3, "");  
  33.             region.setShortcode(shortcode);  
  34.             region.setCitycode(citycode);  
  35.             list.add(region);  
  36.         }  
  37.         String f = "1";  
  38.         try {  
  39.             regionService.saveBatch(list);  
  40.         } catch (Exception e) {  
  41.             f = "0";  
  42.         }  
  43.         ServletActionContext.getResponse().setContentType(  
  44.                 "text/html;charset=UTF-8");  
  45.         ServletActionContext.getResponse().getWriter().print(f);  
  46.         return NONE;  
  47.     }  

配置struts.xml

*重复导入时出现主键冲突:

Duplicate entry ......

解决方法:使用saveOrUpdate


1.3   使用apache POI解析Excel文件

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 测试POI解析Excel文件 
  3.  */  
  4. public class POITest {  
  5.     @Test  
  6.     public void test1() throws FileNotFoundException, IOException {  
  7.         HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(new File(  
  8.                 "d:\\abc.xls")));  
  9.         HSSFSheet sheet = workbook.getSheetAt(0);//读取第一个sheet页  
  10.         for (Row row : sheet) {//循环读取每一行  
  11.             String v1 = row.getCell(0).getStringCellValue();//获得当前行的第一个单元格的文字内容  
  12.             String v2 = row.getCell(1).getStringCellValue();  
  13.             String v3 = row.getCell(2).getStringCellValue();  
  14.             String v4 = row.getCell(3).getStringCellValue();  
  15.             String v5 = row.getCell(4).getStringCellValue();  
  16.             System.out.println(v1 + " " + v2 + " "  +v3 + " " + v4 + " " + v5);  
  17.         }  
  18.     }  
  19. }  


Pinyin4J

 

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1.     @Test  
  2.     public void test1() {  
  3.         String city = "北京市";  
  4.         String province = "河北省";  
  5.         String city2 = "石家庄市";  
  6.         String district = "长安区";  
  7.   
  8.         // 城市编码 北京市-----》beijing  
  9.         String str1 = PinYin4jUtils.hanziToPinyin(  
  10.                 city.substring(0, city.length() - 1), "");  
  11.         System.out.println(str1);  
  12.   
  13.         String info = province.substring(0, province.length() - 1)  
  14.                 + city2.substring(0, city2.length() - 1)  
  15.                 + district.substring(0, district.length() - 1);  
  16.         // 简码河北省石家庄市长安区-----》hbsjzca  
  17.         String[] strings = PinYin4jUtils.getHeadByString(info);  
  18.         String join = StringUtils.join(strings, "");  
  19.         System.out.println(join);  
  20.     }  
  21. }  

utils工具类

[java]  view plain  copy
  1. package cn.itcast.bos.utils;  
  2.   
  3. import java.util.Arrays;  
  4.   
  5. import net.sourceforge.pinyin4j.PinyinHelper;  
  6. import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;  
  7. import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;  
  8. import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;  
  9. import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;  
  10.   
  11. public class PinYin4jUtils {  
  12.     /** 
  13.      * 将字符串转换成拼音数组 
  14.      *  
  15.      * @param src 
  16.      * @return 
  17.      */  
  18.     public static String[] stringToPinyin(String src) {  
  19.         return stringToPinyin(src, falsenull);  
  20.     }  
  21.   
  22.     /** 
  23.      * 将字符串转换成拼音数组 
  24.      *  
  25.      * @param src 
  26.      * @return 
  27.      */  
  28.     public static String[] stringToPinyin(String src, String separator) {  
  29.   
  30.         return stringToPinyin(src, true, separator);  
  31.     }  
  32.   
  33.     /** 
  34.      * 将字符串转换成拼音数组 
  35.      *  
  36.      * @param src 
  37.      * @param isPolyphone 
  38.      *            是否查出多音字的所有拼音 
  39.      * @param separator 
  40.      *            多音字拼音之间的分隔符 
  41.      * @return 
  42.      */  
  43.     public static String[] stringToPinyin(String src, boolean isPolyphone,  
  44.             String separator) {  
  45.         // 判断字符串是否为空  
  46.         if ("".equals(src) || null == src) {  
  47.             return null;  
  48.         }  
  49.         char[] srcChar = src.toCharArray();  
  50.         int srcCount = srcChar.length;  
  51.         String[] srcStr = new String[srcCount];  
  52.   
  53.         for (int i = 0; i < srcCount; i++) {  
  54.             srcStr[i] = charToPinyin(srcChar[i], isPolyphone, separator);  
  55.         }  
  56.         return srcStr;  
  57.     }  
  58.   
  59.     /** 
  60.      * 将单个字符转换成拼音 
  61.      *  
  62.      * @param src 
  63.      * @return 
  64.      */  
  65.     public static String charToPinyin(char src, boolean isPolyphone,  
  66.             String separator) {  
  67.         // 创建汉语拼音处理类  
  68.         HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();  
  69.         // 输出设置,大小写,音标方式  
  70.         defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);  
  71.         defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);  
  72.   
  73.         StringBuffer tempPinying = new StringBuffer();  
  74.   
  75.         // 如果是中文  
  76.         if (src > 128) {  
  77.             try {  
  78.                 // 转换得出结果  
  79.                 String[] strs = PinyinHelper.toHanyuPinyinStringArray(src,  
  80.                         defaultFormat);  
  81.   
  82.                 // 是否查出多音字,默认是查出多音字的第一个字符  
  83.                 if (isPolyphone && null != separator) {  
  84.                     for (int i = 0; i < strs.length; i++) {  
  85.                         tempPinying.append(strs[i]);  
  86.                         if (strs.length != (i + 1)) {  
  87.                             // 多音字之间用特殊符号间隔起来  
  88.                             tempPinying.append(separator);  
  89.                         }  
  90.                     }  
  91.                 } else {  
  92.                     tempPinying.append(strs[0]);  
  93.                 }  
  94.   
  95.             } catch (BadHanyuPinyinOutputFormatCombination e) {  
  96.                 e.printStackTrace();  
  97.             }  
  98.         } else {  
  99.             tempPinying.append(src);  
  100.         }  
  101.   
  102.         return tempPinying.toString();  
  103.   
  104.     }  
  105.   
  106.     public static String hanziToPinyin(String hanzi) {  
  107.         return hanziToPinyin(hanzi, " ");  
  108.     }  
  109.   
  110.     /** 
  111.      * 将汉字转换成拼音 
  112.      *  
  113.      * @param hanzi 
  114.      * @param separator 
  115.      * @return 
  116.      */  
  117.     public static String hanziToPinyin(String hanzi, String separator) {  
  118.   
  119.         // 创建汉语拼音处理类  
  120.         HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();  
  121.         // 输出设置,大小写,音标方式  
  122.         defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);  
  123.         defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);  
  124.   
  125.         String pinyingStr = "";  
  126.         try {  
  127.             pinyingStr = PinyinHelper.toHanyuPinyinString(hanzi, defaultFormat,  
  128.                     separator);  
  129.         } catch (BadHanyuPinyinOutputFormatCombination e) {  
  130.             // TODO Auto-generated catch block  
  131.             e.printStackTrace();  
  132.         }  
  133.         return pinyingStr;  
  134.     }  
  135.   
  136.     /** 
  137.      * 将字符串数组转换成字符串 
  138.      *  
  139.      * @param str 
  140.      * @param separator 
  141.      *            各个字符串之间的分隔符 
  142.      * @return 
  143.      */  
  144.     public static String stringArrayToString(String[] str, String separator) {  
  145.         StringBuffer sb = new StringBuffer();  
  146.         for (int i = 0; i < str.length; i++) {  
  147.             sb.append(str[i]);  
  148.             if (str.length != (i + 1)) {  
  149.                 sb.append(separator);  
  150.             }  
  151.         }  
  152.         return sb.toString();  
  153.     }  
  154.   
  155.     /** 
  156.      * 简单的将各个字符数组之间连接起来 
  157.      *  
  158.      * @param str 
  159.      * @return 
  160.      */  
  161.     public static String stringArrayToString(String[] str) {  
  162.         return stringArrayToString(str, "");  
  163.     }  
  164.   
  165.     /** 
  166.      * 将字符数组转换成字符串 
  167.      *  
  168.      * @param str 
  169.      * @param separator 
  170.      *            各个字符串之间的分隔符 
  171.      * @return 
  172.      */  
  173.     public static String charArrayToString(char[] ch, String separator) {  
  174.         StringBuffer sb = new StringBuffer();  
  175.         for (int i = 0; i < ch.length; i++) {  
  176.             sb.append(ch[i]);  
  177.             if (ch.length != (i + 1)) {  
  178.                 sb.append(separator);  
  179.             }  
  180.         }  
  181.         return sb.toString();  
  182.     }  
  183.   
  184.     /** 
  185.      * 将字符数组转换成字符串 
  186.      *  
  187.      * @param str 
  188.      * @return 
  189.      */  
  190.     public static String charArrayToString(char[] ch) {  
  191.         return charArrayToString(ch, " ");  
  192.     }  
  193.   
  194.     /** 
  195.      * 取汉字的首字母 
  196.      *  
  197.      * @param src 
  198.      * @param isCapital 
  199.      *            是否是大写 
  200.      * @return 
  201.      */  
  202.     public static char[] getHeadByChar(char src, boolean isCapital) {  
  203.         // 如果不是汉字直接返回  
  204.         if (src <= 128) {  
  205.             return new char[] { src };  
  206.         }  
  207.         // 获取所有的拼音  
  208.         String[] pinyingStr = PinyinHelper.toHanyuPinyinStringArray(src);  
  209.   
  210.         // 创建返回对象  
  211.         int polyphoneSize = pinyingStr.length;  
  212.         char[] headChars = new char[polyphoneSize];  
  213.         int i = 0;  
  214.         // 截取首字符  
  215.         for (String s : pinyingStr) {  
  216.             char headChar = s.charAt(0);  
  217.             // 首字母是否大写,默认是小写  
  218.             if (isCapital) {  
  219.                 headChars[i] = Character.toUpperCase(headChar);  
  220.             } else {  
  221.                 headChars[i] = headChar;  
  222.             }  
  223.             i++;  
  224.         }  
  225.   
  226.         return headChars;  
  227.     }  
  228.   
  229.     /** 
  230.      * 取汉字的首字母(默认是大写) 
  231.      *  
  232.      * @param src 
  233.      * @return 
  234.      */  
  235.     public static char[] getHeadByChar(char src) {  
  236.         return getHeadByChar(src, true);  
  237.     }  
  238.   
  239.     /** 
  240.      * 查找字符串首字母 
  241.      *  
  242.      * @param src 
  243.      * @return 
  244.      */  
  245.     public static String[] getHeadByString(String src) {  
  246.         return getHeadByString(src, true);  
  247.     }  
  248.   
  249.     /** 
  250.      * 查找字符串首字母 
  251.      *  
  252.      * @param src 
  253.      * @param isCapital 
  254.      *            是否大写 
  255.      * @return 
  256.      */  
  257.     public static String[] getHeadByString(String src, boolean isCapital) {  
  258.         return getHeadByString(src, isCapital, null);  
  259.     }  
  260.   
  261.     /** 
  262.      * 查找字符串首字母 
  263.      *  
  264.      * @param src 
  265.      * @param isCapital 
  266.      *            是否大写 
  267.      * @param separator 
  268.      *            分隔符 
  269.      * @return 
  270.      */  
  271.     public static String[] getHeadByString(String src, boolean isCapital,  
  272.             String separator) {  
  273.         char[] chars = src.toCharArray();  
  274.         String[] headString = new String[chars.length];  
  275.         int i = 0;  
  276.         for (char ch : chars) {  
  277.   
  278.             char[] chs = getHeadByChar(ch, isCapital);  
  279.             StringBuffer sb = new StringBuffer();  
  280.             if (null != separator) {  
  281.                 int j = 1;  
  282.   
  283.                 for (char ch1 : chs) {  
  284.                     sb.append(ch1);  
  285.                     if (j != chs.length) {  
  286.                         sb.append(separator);  
  287.                     }  
  288.                     j++;  
  289.                 }  
  290.             } else {  
  291.                 sb.append(chs[0]);  
  292.             }  
  293.             headString[i] = sb.toString();  
  294.             i++;  
  295.         }  
  296.         return headString;  
  297.     }  
  298.       
  299.     public static void main(String[] args) {  
  300.         // pin4j 简码 和 城市编码   
  301.         String s1 = "中华人民共和国";   
  302.         String[] headArray = getHeadByString(s1); // 获得每个汉字拼音首字母  
  303.         System.out.println(Arrays.toString(headArray));  
  304.           
  305.         String s2 ="长城" ;   
  306.         System.out.println(Arrays.toString(stringToPinyin(s2,true,",")));  
  307.           
  308.         String s3 ="长";  
  309.         System.out.println(Arrays.toString(stringToPinyin(s3,true,",")));  
  310.     }  
  311. }  


2.    区域分页查询

    修改region.jsp页面中datagrid的url地址

    在RegionAction中提供分页查询方法pageQuery

与上一天的代码重复需要提取到baseAction  

3.    重构分页代码

    在BaseAction中提取PageBean和DetachedCriteria对象

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. protected PageBean pageBean = new PageBean();  
  2. // 离线条件查询对象,用于包装查询条件  
  3. DetachedCriteria detachedCriteria = null;  

    在BaseAction中提供setPage和setRows方法

把分页ajax相应的两个参数row和page直接注入到上面提取的pageBean中

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public void setPage(int page) {  
  2.     pageBean.setCurrentPage(page);// 当前页码  
  3. }  
  4.   
  5. public void setRows(int rows) {  
  6.     pageBean.setPageSize(rows);// 每页显示记录数  
  7. }  

    在BaseAction的构造方法中创建离线条件查询对象,并且注入给PageBean

 构造方法获取实体类型后创建离线查询条件对象并注入到pageBean中

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public BaseAction() {  
  2.     // 获得父类(BaseAction) 类型  
  3.     ParameterizedType superclass = (ParameterizedType) this.getClass()  
  4.             .getGenericSuperclass();  
  5.     // 获得父类上的泛型数组  
  6.     Type[] typeArguments = superclass.getActualTypeArguments();  
  7.     // 获得实体类型  
  8.     Class<T> domainClass = (Class<T>) typeArguments[0];  
  9.     // 获得实体类型后创建离线条件查询对象  
  10.     detachedCriteria = DetachedCriteria.forClass(domainClass);  
  11.     pageBean.setDetachedCriteria(detachedCriteria);  
  12.     try {  
  13.         model = domainClass.newInstance();  
  14.     } catch (InstantiationException e) {  
  15.         e.printStackTrace();  
  16.     } catch (IllegalAccessException e) {  
  17.         e.printStackTrace();  
  18.     }  
  19. }  

    在BaseAction中抽取方法writePageBean2Json和writeListBean2Json

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 将PageBean序列化为json返回 
  3.  */  
  4. public void writePageBean2Json(PageBean pageBean, String[] excludes) {  
  5.     // 使用jsonlib将PageBean对象序列化为json数据  
  6.     JsonConfig jsonConfig = new JsonConfig();  
  7.     jsonConfig.setExcludes(excludes);  
  8.     String json = JSONObject.fromObject(pageBean, jsonConfig).toString();  
  9.   
  10.     ServletActionContext.getResponse().setContentType(  
  11.             "text/json;charset=UTF-8");  
  12.     try {  
  13.         ServletActionContext.getResponse().getWriter().print(json);  
  14.     } catch (IOException e) {  
  15.         e.printStackTrace();  
  16.     }  
  17. }  
  18.   
  19. /** 
  20.  * 将List序列化为json返回 
  21.  */  
  22. public void writeListBean2Json(List list, String[] excludes) {  
  23.     // 使用jsonlib将PageBean对象序列化为json数据  
  24.     JsonConfig jsonConfig = new JsonConfig();  
  25.     jsonConfig.setExcludes(excludes);  
  26.     String json = JSONArray.fromObject(list, jsonConfig).toString();  
  27.   
  28.     ServletActionContext.getResponse().setContentType(  
  29.             "text/json;charset=UTF-8");  
  30.     try {  
  31.         ServletActionContext.getResponse().getWriter().print(json);  
  32.     } catch (IOException e) {  
  33.         e.printStackTrace();  
  34.     }  
  35. }  
 

    在RegionAction中的分页查询

分页查询代码简化为3条

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 分页查询方法 
  3.  * @throws IOException  
  4.  */  
  5. public String pageQuery() throws IOException{  
  6.     regionService.pageQuery(pageBean);  
  7.     this.writePageBean2Json(pageBean, new String[]{"currentPage","pageSize","detachedCriteria","subareas"});  
  8.     return NONE;  
  9. }  

  

4.    分区添加功能

4.1   Combobox下拉框使用

方式一:给静态的select标签应用

方式二:使用input标签通过url动态获取数据(json)

textField:为"option"下拉显示的内容

valueField::为最终提交的value值

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <body>  
  2.     <!-- 方式一 -->  
  3.     <select class="easyui-combobox">  
  4.         <option value="1">河北省石家庄市桥西区</option>  
  5.         <option value="2">河北省石家庄市桥东区</option>  
  6.         <option value="3">河北省石家庄市长安区</option>  
  7.     </select>  
  8.       
  9.     <!-- 方式二 -->  
  10.     <input  
  11.      data-options="url:'${pageContext.request.contextPath }/json/data.json',  
  12.                 textField:'name',valueField:'id'"  
  13.      type="text" class="easyui-combobox"/>  
  14. </body>  


subarea分区页面的添加分区弹窗区域选择下拉框数据获取(模糊查询)

及添加分区功能

 

第一步:修改subarea.jsp页面中combobox的url地址

mode属性

定义了当文本改变时如何读取列表数据。设置为'remote'时,下拉列表框将会从服务器加载数据。

当设置为“remote”模式时,用户输入将被发送到名为'q'的HTTP请求参数到服务器检索新数据。

 

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <td>  
  2.     <input class="easyui-combobox" name="region.id"    
  3.                     data-options="mode:'remote',valueField:'id',textField:'name',  
  4.                     url:'${pageContext.request.contextPath }/regionAction_list.action'" />    
  5. </td>  

对应分区类也应增加与下拉栏textField对应的name属性(省市区)

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private String id;//编号  
  2. private String province;//省  
  3. private String city;//市  
  4. private String district;//区  
  5. private String postcode;//邮编  
  6. private String shortcode;//简码  
  7. private String citycode;//城市编码  
  8. private Set subareas = new HashSet(0);//区域对应的多个分区  
  9.   
  10. public String getName(){  
  11.     return province + city + district;  
  12. }  


第二步:在RegionAction中提供list方法查询区域数据

 

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private String q;//模糊查询参数     
  2. public void setQ(String q) {  
  3.     this.q = q;  
  4. }  
  5. /**  
  6.  *  查询所有区域返回json  
  7.  */  
  8. public String list(){  
  9.     List<Region> list = null;  
  10.     if(StringUtils.isNotBlank(q)){  
  11.         //根据q进行模糊查询  
  12.         list = regionService.findByQ(q.trim());  
  13.     }else{  
  14.         //查询所有  
  15.         list = regionService.findAll();  
  16.     }  
  17.     String[] excludes = new String[]{"subareas"};  
  18.     this.writeListBean2Json(list, excludes);  
  19.     return NONE;  
  20. }  

Service中:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2. public List<Region> findByQ(String q) {     
  3.     return regionDao.findByNameQuery("findByQ","%"+q+"%","%"+q+"%","%"+q+"%");  
  4. }  
baseIDaompl命名查询

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. @Override  
  2. public List<T> findByNameQuery(String hqlName, Object... params) {  
  3.      List findByNamedQuery = this.getHibernateTemplate().findByNamedQuery(hqlName,params);  
  4.      return findByNamedQuery;  
  5. }  

对应*hbm.xml提供query hql语句

注意:命名查询配置语句中不能出现双引号" "会报错,因为语句是按字符串来提取的,xml配置+" "来拼接也不行

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <query name="findByQ">  
  2.     FROM Region WHERE city LIKE ? OR province LIKE ? OR district LIKE ?   
  3. </query>  

第三步:为保存按钮绑定事件

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <a id="save" icon="icon-save" href="#" class="easyui-linkbutton" plain="true" >保存</a>  
  2. <script type="text/javascript">  
  3.     $(function(){  
  4.         //为保存按钮绑定事件  
  5.         $("#save").click(function(){  
  6.             var v = $("#addForm").form("validate");  
  7.             if(v){  
  8.                 $("#addForm").submit();  
  9.             }  
  10.         });  
  11.     });  
  12. </script><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>  

第四步:创建一个SubareaAction,提供add方法用于添加分区

 略

 

5.    分区组合条件分页查询

基于datagrid的load方法实现组合条件分页查询

 

*带关联查询的分页查询转换json会出错

freemarker.template.TemplateModelException:

Method public Java.lang.Stringorg.apache.commons.lang.exception

.NestableRuntimeException.getMessage(int)threw an exception when invoked on net.sf.json.JSONException:

java.lang.reflect.InvocationTargetException

原因:关联对象延迟加载是代理对象无法转换成json数据

解决: 修改对应需关联对象hbm,xml文件的lazy属性为false 解决关联查询问题

[html]  view plain  copy
  1. <many-to-one name="region" class="cn.feibai.bos.domain.Region" fetch="select" lazy="false">  
  2.     <column name="region_id" length="32" />  
  3. </many-to-one>  

第一步:提供组合条件查询窗口

第二步提供一个工具方法,将form表单中的输入项转为json数据,提交参数

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. $.fn.serializeJson=function(){    
  2.            var serializeObj={};    
  3.            var array=this.serializeArray();  
  4.            $(array).each(function(){    
  5.                if(serializeObj[this.name]){    
  6.                    if($.isArray(serializeObj[this.name])){    
  7.                        serializeObj[this.name].push(this.value);    
  8.                    }else{    
  9.                        serializeObj[this.name]=[serializeObj[this.name],this.value];    
  10.                    }    
  11.                }else{    
  12.                    serializeObj[this.name]=this.value;     
  13.                }    
  14.            });    
  15.            return serializeObj;    
  16.        };   


第三步:为查询按钮绑定事件,调用datagrid的load方法,重写发起ajax请求,提交参数

目的:这样发起的查询是ajax请求,条件参数会缓存在页面.

ajax没有全部刷新页面所以对应分页查询的条件也不会丢失

方法:load       

参数:param

详情:

加载和显示第一页的所有行。如果指定了'param',它将取代'queryParams'属性。通常可以通过传递一些参数执行一次查询,通过调用这个方法从服务器加载新数据。

 

[javascript]  view plain  copy
  1. <!-- 查询分区 -->  
  2. <script type="text/javascript">  
  3.     //为查询按钮绑定事件  
  4.     $(function(){  
  5.         $.fn.serializeJson=function(){    
  6.             var serializeObj={};    
  7.             var array=this.serializeArray();  
  8.             $(array).each(function(){    
  9.                 if(serializeObj[this.name]){    
  10.                     if($.isArray(serializeObj[this.name])){    
  11.                         serializeObj[this.name].push(this.value);    
  12.                     }else{    
  13.                         serializeObj[this.name]=[serializeObj[this.name],this.value];    
  14.                     }    
  15.                 }else{    
  16.                     serializeObj[this.name]=this.value;     
  17.                 }    
  18.             });    
  19.             return serializeObj;    
  20.         };   
  21.         $("#btn").click(function(){  
  22.             //获取查询条件---一次获取所有的查询条件,将查询条件封装成json数据  
  23.             var params = $("#searchForm").serializeJson();  
  24.             //重新发起一次ajax请求,提交参数  
  25.             $("#grid").datagrid("load",params);  
  26.             //关闭查询窗口  
  27.             $("#searchWindow").window("close");  
  28.         });  
  29.     });  
  30. </script>  


第四步:改造SubareaAction中的pageQuery方法,加入组合条件分页查询逻辑

Restrictions  API

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 分页组合条件查询 
  3.  */  
  4. public String pageQuery() {  
  5.     DetachedCriteria subareaDC = pageBean.getDetachedCriteria();  
  6.     // 从模型对象中获取提交的查询参数  
  7.     String addresskey = model.getAddresskey();// 关键字  
  8.     // 单表查询  
  9.     if (StringUtils.isNotBlank(addresskey)) {  
  10.         // 添加查询条件,根据关键字进行模糊查询  
  11.         subareaDC.add(Restrictions.like("addresskey",  
  12.                 "%" + addresskey.trim() + "%"));  
  13.     }  
  14.     Region region = model.getRegion();  
  15.     // 多表查询  
  16.     if (region != null) {  
  17.         String province = region.getProvince();  
  18.         String city = region.getCity();  
  19.         String district = region.getDistrict();  
  20.         DetachedCriteria regionDC = subareaDC.createCriteria("region");  
  21.         if (StringUtils.isNotBlank(province)) {  
  22.             // 添加查询条件,根据省进行模糊查询  
  23.             regionDC.add(Restrictions  
  24.                     .like("province""%" + province + "%"));  
  25.         }  
  26.         if (StringUtils.isNotBlank(city)) {  
  27.             // 添加查询条件,根据省进行模糊查询  
  28.             regionDC.add(Restrictions.like("city""%" + city + "%"));  
  29.         }  
  30.         if (StringUtils.isNotBlank(district)) {  
  31.             // 添加查询条件,根据省进行模糊查询  
  32.             regionDC.add(Restrictions  
  33.                     .like("district""%" + district + "%"));  
  34.         }  
  35.     }  
  36.     subareaService.pageQuery(pageBean);  
  37.     String[] excludes = new String[] { "decidedzone""subareas" };  
  38.     this.writePageBean2Json(pageBean, excludes);  
  39.     return NONE;  
  40. }  

 

6.    分区数据导出功能(Excel提供下载)

第一步:修改subarea.jsp页面中导出按钮的事件 

[javascript]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. function doExport(){  
  2.     //发起请求Action,查询所有分区数据,写到Excel文件中并提供下载  
  3.     window.location.href = "${pageContext.request.contextPath}/subareaAction_exportXls.action";  
  4. }  

第二步:在Action中提供exportXls方法

两种方法:

方式一:原始手动设置响应下载

文件名乱码工具类

[java]  view plain  copy
  1. import java.io.IOException;  
  2. import java.net.URLEncoder;  
  3.   
  4. import sun.misc.BASE64Encoder;  
  5.   
  6. public class FileUtils {  
  7.         /** 
  8.          * 下载文件时,针对不同浏览器,进行附件名的编码 
  9.          *  
  10.          * @param filename 
  11.          *            下载文件名 
  12.          * @param agent 
  13.          *            客户端浏览器 
  14.          * @return 编码后的下载附件名 
  15.          * @throws IOException 
  16.          */  
  17.         public static String encodeDownloadFilename(String filename, String agent)  
  18.                 throws IOException {  
  19.             if (agent.contains("Firefox")) { // 火狐浏览器  
  20.                 filename = "=?UTF-8?B?"  
  21.                         + new BASE64Encoder().encode(filename.getBytes("utf-8"))  
  22.                         + "?=";  
  23.                 filename = filename.replaceAll("\r\n""");  
  24.             } else { // IE及其他浏览器  
  25.                 filename = URLEncoder.encode(filename, "utf-8");  
  26.                 filename = filename.replace("+"," ");  
  27.             }  
  28.             return filename;  
  29.         }  
  30. }  


[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 导出分区数据到Excel文件并提供下载 
  3.  *  
  4.  * @throws IOException 
  5.  */  
  6. public String exportXls() throws IOException {  
  7.     List<Subarea> list = subareaService.findAll();  
  8.     // 使用POI将查询的数据写入Excel文件中  
  9.     HSSFWorkbook workbook = new HSSFWorkbook();  
  10.     // 在工作表中创建一个sheet页  
  11.     HSSFSheet sheet = workbook.createSheet("分区数据");  
  12.     // 创建标题行  
  13.     HSSFRow headRow = sheet.createRow(0);  
  14.     // 创建单元格  
  15.     headRow.createCell(0).setCellValue("分区编号");  
  16.     headRow.createCell(1).setCellValue("关键字");  
  17.     headRow.createCell(2).setCellValue("地址");  
  18.     headRow.createCell(3).setCellValue("省市区");  
  19.     for (Subarea subarea : list) {  
  20.         // 创建数据行  
  21.         HSSFRow dataRow = sheet.createRow(sheet.getLastRowNum() + 1);  
  22.         String id = subarea.getId();  
  23.         String addresskey = subarea.getAddresskey();  
  24.         String position = subarea.getPosition();  
  25.         Region region = subarea.getRegion();  
  26.         dataRow.createCell(0).setCellValue(id);  
  27.         dataRow.createCell(1).setCellValue(addresskey);  
  28.         dataRow.createCell(2).setCellValue(position);  
  29.         if (region != null) {  
  30.             String province = region.getProvince();  
  31.             String city = region.getCity();  
  32.             String district = region.getDistrict();  
  33.             String info = province + city + district;  
  34.             dataRow.createCell(3).setCellValue(info);  
  35.         }  
  36.     }  
  37.   
  38.     String filename = "分区数据.xls";  
  39.     String agent = ServletActionContext.getRequest().getHeader("user-agent");//浏览器类型  
  40.     filename = FileUtils.encodeDownloadFilename(filename, agent );  
  41.       
  42.     //根据文件名称动态获得类型  
  43.     String contentType = ServletActionContext.getServletContext()  
  44.             .getMimeType(filename);  
  45.     // 通知客户端下载文件的类型  
  46.     ServletActionContext.getResponse().setContentType(contentType);  
  47.       
  48.     //指定以附件形式下载,指定文件名称  
  49.     ServletActionContext.getResponse().setHeader("content-disposition""attachment;filename=" + filename);  
  50.     // 通过输出流向客户端浏览器写Excel文件  
  51.     ServletOutputStream out = ServletActionContext.getResponse().getOutputStream();  
  52.     workbook.write(out);  
  53.     return NONE;  
  54. }  


方式二:通过struts2的stream结果集下载

思路百度自博客(http://xiaowei-qi-epro-com-cn.iteye.com/blog/2030671):

思路是,先创建一个输出流,将这个excel写入到输出流里面,然后再通过这个输出流来得到我们所需要的输入流.

使用了ByteArrayOutputStreamByteArrayInputStream...处理的思想是,HSSFWorkbook 写入ByteArrayOutputStream.然后用ByteArrayOutputStream来转换为字节流..然后再将字节流转换为ByteArrayInputStream ..至此,我们就在内存中将excel转换成了输入流

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <pre name="code" class="java">    private InputStream target;    
  2.     public InputStream getTarget() {    
  3.         return target;    
  4.     }   
  5.     //下载文件名,存在中文乱码    
  6.     private String downloadFileName;    
  7.     public String getDownloadFileName() throws UnsupportedEncodingException {    
  8.         // 处理中文乱码    
  9.         if(downloadFileName != null){    
  10.             return new String(downloadFileName.getBytes("GBK"),"ISO-8859-1");    
  11.         }    
  12.         return downloadFileName;    
  13.     }    
  14.     /** 
  15.      * 下载所有分区信息以xls格式 
  16.      * @return 
  17.      * @throws IOException  
  18.      */  
  19.     public String export() throws IOException{  
  20.         List<Subarea> list=subareaService.findAll();  
  21.         //把list写入excel文档  
  22.         HSSFWorkbook book=new HSSFWorkbook();  
  23.         HSSFSheet sheet = book.createSheet("全部分区详情");  
  24.         //创建初始标题行  
  25.         HSSFRow row = sheet.createRow(0);  
  26.         row.createCell(0).setCellValue("分拣编号");  
  27.         row.createCell(1).setCellValue("省市区");  
  28.         row.createCell(2).setCellValue("关键字");  
  29.         row.createCell(3).setCellValue("位置");  
  30.         //遍历list  
  31.         for (Subarea subarea : list) {  
  32.             HSSFRow createRow = sheet.createRow(sheet.getLastRowNum()+1);  
  33.             String id = subarea.getId();  
  34.             String nameInfo = subarea.getRegion().getName();  
  35.             String addresskey = subarea.getAddresskey();  
  36.             String position = subarea.getPosition();  
  37.             createRow.createCell(0).setCellValue(id);  
  38.             createRow.createCell(1).setCellValue(nameInfo);  
  39.             createRow.createCell(2).setCellValue(addresskey);  
  40.             createRow.createCell(3).setCellValue(position);  
  41.         }  
  42.         ByteArrayOutputStream out = new ByteArrayOutputStream();  
  43.         book.write(out);  
  44.         target = new ByteArrayInputStream(out.toByteArray());    
  45.         out.close();    
  46.         downloadFileName="分区详情.xls";          
  47.         return "download";  
  48.     }  
 

 
 

配置文件

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <!-- 分区 -->  
  2. <action name="subareaAction_*" class="subareaAction" method="{1}">  
  3.     <result name="subareaList">/WEB-INF/pages/base/subarea.jsp</result>           
  4.     <result name="download" type="stream">    
  5.         <!-- 设置响应头 -->    
  6.         <param name="contentDisposition">attachment;filename=${downloadFileName}</param>    
  7.         <!-- 确定流 -->    
  8.         <param name="inputName">target</param>    
  9.     </result>               
  10. </action>  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值