收藏列表
- 全部 [31]
- 默认 [6]
- tomcat [1]
- sql [2]
- mvc [1]
- 多线程 [1]
- 类型转换 [1]
- 下拉框 [1]
- arraycopy [1]
- 联动 [1]
- 银行取款 [1]
- 定义一个涨工资的接口类类 [1]
- 复制功能 [1]
- 银行存取款 [1]
- 继承重写 [1]
- 基本测试 [2]
- 邮箱测试 [1]
- 状态模式(state) [1]
- js多级 [1]
- ajaxjquery请求方式 [1]
- springmvc定时器配置 [1]
- 图片压缩代码 [1]
- tomcat内存配置 [1]
- 事件驱动模型简介 [1]
- java @override报错的解决方法 [1]
- 数据库查询优化方案 [1]
- hibernate 使用sql 分页写法 [1]
标题 | 标签 | 来源 | |
hibernate 使用SQL 分页写法 | hibernate 使用sql 分页写法 | ||
hibernate 使用SQL 分页写法 博客分类: hibernate SQLHibernate 前几天系统中用到复杂的SQL,想用HQL 来实现结果HQl语句写不出来。想想hibernate也支持SQL 的,就只能写SQL 封装来实现了。 SQL Sql代码 收藏代码 select * from wcsc_service_log a, (select id, max(end_time) as end_time from wcsc_service_log group by id) b where a.id = b.id and a.end_time = b.end_time and COMPCODE = '0001' JAVA 代码封装这段SQL Java代码 收藏代码 public Pagination getServiceLog(String compcode, int pageNo, int pageSize) { String sql ="select a.* from wcsc_service_log a ,(select id,max(end_time)as end_time from wcsc_service_log group by id)b"+ " where a.id=b.id and a.end_time=b.end_time and a.COMPCODE='"+compcode+"'"; Query queryObject =getSession().createSQLQuery(sql).addEntity(ServiceLog.class); queryObject.setFirstResult((pageNo - 1) * pageSize); queryObject.setMaxResults(pageSize); List<ServiceLog> list =queryObject.list(); int count=getCount(compcode); Pagination p = new Pagination(pageNo, pageSize, count); if (count < 1) { p.setList(new ArrayList<ServiceLog>()); return p; } p.setList(list); return p; } 代码说明 Query queryObject =getSession().createSQLQuery(sql).addEntity(ServiceLog.class); 这句是执行SQL映射HIBERNATE 查询,注意createSQLQuery 该方法是SQL 语句,我们知道HQL 的方法是 createQuery 另外封装成映射对象addEntity(ServiceLog.class),ServiceLog是你SQL JavaBEAN 返回查询语句这样就可以HIBERNATE待用SQL 了 queryObject.setFirstResult((pageNo - 1) * pageSize); queryObject.setMaxResults(pageSize); 这2端是分页的语句 如果不分页可以不需要了 这样就实现了HIBERNATE 调用复杂的SQL |
|||
代码收集 | |||
String resetPwd = RandomStringUtils.randomNumeric(10);//随机数 @Override public List<StatisticProduct> statistic(Date beginDate, Date endDate) { String sql = "SELECT p.product_id,p.product_name,p.sale_price,p.purchase_price," + " (sale_price-purchase_price) profit,total_count.sale_count," + " (sale_price*total_count.sale_count) sale_sum," + " (purchase_price*total_count.sale_count) sale_purchase," + " (sale_price*total_count.sale_count - purchase_price*total_count.sale_count)sale_profit " + " FROM jc_product p"; // Finder f = Finder.create(hql); sql += " JOIN " + " (SELECT e.product_id,SUM(e.product_count) sale_count FROM jc_order_ext e " + " JOIN jc_order o ON e.order_id = o.order_id " + " WHERE 1=1 "; SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); String begin = format.format(beginDate); String end = format.format(endDate); if (null != beginDate) { sql += " and o.order_date >='"+begin+"'"; } if (null != endDate) { sql += " and o.order_date <='"+end+"'"; } sql += " GROUP BY e.product_id ) total_count ON total_count.product_id= p.product_id "; SQLQuery query = (SQLQuery) getSession().createSQLQuery(sql).setResultTransformer(Transformers.aliasToBean(StatisticProduct.class)); List<StatisticProduct> list = query.list(); return list; } /** * 按时间条件查询 * * @param response * @param request * @param fromDate * @param ToDate * @return String */ @RequestMapping("/productstatistic/searchOutPut.do") public void searchDownExcel(HttpServletResponse response, HttpServletRequest request, Date beginDate, Date endDate,ModelMap model) { StringBuffer p = request.getRequestURL(); String path = "/yiwen/WEB-INF/jeecms_sys/product/产品销售统计.xls"; String aa=request.getSession().getServletContext().getRealPath(""); Integer index= aa.lastIndexOf("\\")+1; String path1=aa.substring(0, index); path=path1+path; //path = path1 + path; List<StatisticProduct> list =statisticProductMng.statistic(beginDate, endDate); for (StatisticProduct statisticProduct : list) { gernerate(path, request, statisticProduct, beginDate, endDate); } ExcelUtil.downloadFile(request, response, path); (new File(path)).delete();// 下载后并删除文件 List<StatisticProduct> list1 =statisticProductMng.statistic(beginDate, endDate); Integer size = list.size(); model.addAttribute("list", list1); model.addAttribute("beginDate", beginDate); model.addAttribute("endDate", endDate); model.addAttribute("size", size); //return "product/statistic"; } public void gernerate(String path,HttpServletRequest request,StatisticProduct bean,Date beginDate,Date endDate) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); String begin="开店始"; if(null!=beginDate) begin= format.format(beginDate); String end="今"; if(null!=endDate) end= format.format(endDate); OutputStream out=null; File file=new File(path); if (!file.exists()) { try { file.createNewFile(); HSSFWorkbook hwb = new HSSFWorkbook();//建立新HSSFWorkbook对象 HSSFSheet sheet=hwb.createSheet(begin+"至"+end+"--产品销售统计"); HSSFRow rows=sheet.createRow(0); HSSFCell[] firstcell = new HSSFCell[9]; String[] names = new String[9]; names[0] = "产品ID"; names[1] = "产品名"; names[2] = "售价"; names[3] = "进价"; names[4] = "单件利润"; names[5] = "销售量"; names[6] = "销售总额"; names[7] = "销售成本"; names[8] = "销售利润"; for (int j = 0; j < 9; j++) { firstcell[j] = rows.createCell(j); firstcell[j].setCellValue(new HSSFRichTextString(names[j])); sheet.setColumnHidden(j,false); } HSSFRow row = sheet.createRow(1); HSSFCell xh=row.createCell(0); xh.setCellValue(bean.getProduct_id()); HSSFCell xh1=row.createCell(1); xh1.setCellValue(bean.getProduct_name()); HSSFCell xh2=row.createCell(2); xh2.setCellValue(bean.getSale_price()); HSSFCell xh3=row.createCell(3); xh3.setCellValue(bean.getPurchase_price()); HSSFCell xh4=row.createCell(4); xh4.setCellValue(bean.getProfit()); HSSFCell xh5=row.createCell(5); xh5.setCellValue(bean.getSale_count().floatValue()); HSSFCell xh6=row.createCell(6); xh6.setCellValue(bean.getSale_sum()); HSSFCell xh7=row.createCell(7); xh7.setCellValue(bean.getSale_purchase()); HSSFCell xh8=row.createCell(8); xh8.setCellValue(bean.getSale_profit()); out = new FileOutputStream(file); hwb.write(out); out.close(); } catch (IOException e) { e.printStackTrace(); } System.out.println(file + "已创建!"); } else if (file.exists()) { try { FileInputStream fs=new FileInputStream(file); POIFSFileSystem ps=new POIFSFileSystem(fs); HSSFWorkbook wb=new HSSFWorkbook(ps); HSSFSheet sheet=wb.getSheetAt(0); HSSFRow row=null; FileOutputStream fileOut=new FileOutputStream(file); row=sheet.createRow((short)(sheet.getLastRowNum()+1)); HSSFCell xh=row.createCell(0); xh.setCellValue(bean.getProduct_id()); HSSFCell xh1=row.createCell(1); xh1.setCellValue(bean.getProduct_name()); HSSFCell xh2=row.createCell(2); xh2.setCellValue(bean.getSale_price()); HSSFCell xh3=row.createCell(3); xh3.setCellValue(bean.getPurchase_price()); HSSFCell xh4=row.createCell(4); xh4.setCellValue(bean.getProfit()); HSSFCell xh5=row.createCell(5); xh5.setCellValue(bean.getSale_count().floatValue()); HSSFCell xh6=row.createCell(6); xh6.setCellValue(bean.getSale_sum()); HSSFCell xh7=row.createCell(7); xh7.setCellValue(bean.getSale_purchase()); HSSFCell xh8=row.createCell(8); xh8.setCellValue(bean.getSale_profit()); wb.write(fileOut);//把Workbook对象输出到路径path中 fileOut.close(); } catch (IOException e) { e.printStackTrace(); } } } @SuppressWarnings("unchecked") public List<Content> getListByIdsForTag(Integer[] ids, int orderBy) { Finder f = Finder.create("from Content bean where bean.id in (:ids)"); f.setParamList("ids", ids); appendOrder(f, orderBy); f.setCacheable(true); return find(f); } StringBuffer p = request.getRequestURL(); int endp = p.length() - "order/v_orderPay.jspx".length(); String path1 = p.toString().substring(0, endp); |
|||
数据库查询优化方案 | 数据库查询优化方案 | ||
大数据量高并发的数据库优化 (2011-07-29 17:21:03)转载▼ 标签: it 分类: 技术 一、数据库结构的设计 为了保证数据库的一致性和完整性,在逻辑设计的时候往往会设计过多的表间关联,尽可能的降低数据的冗余。(例如用户表的地区,我们可以把地区另外存放到一个地区表中)如果数据冗余低,数据的完整性容易得到保证,提高了数据吞吐速度,保证了数据的完整性,清楚地表达数据元素之间的关系。而对于多表之间的关联查询(尤其是大数据表)时,其性能将会降低,同时也提高了客户端程序的编程难度,因此,物理设计需折衷考虑,根据业务规则,确定对关联表的数据量大小、数据项的访问频度,对此类数据表频繁的关联查询应适当提高数据冗余设计但增加了表间连接查询的操作,也使得程序的变得复杂,为了提高系统的响应时间,合理的数据冗余也是必要的。设计人员在设计阶段应根据系统操作的类型、频度加以均衡考虑。 另外,最好不要用自增属性字段作为主键与子表关联。不便于系统的迁移和数据恢复。对外统计系统映射关系丢失(******************)。 原来的表格必须可以通过由它分离出去的表格重新构建。使用这个规定的好处是,你可以确保不会在分离的表格中引入多余的列,所有你创建的表格结构都与它们的实际需要一样大。应用这条规定是一个好习惯,不过除非你要处理一个非常大型的数据,否则你将不需要用到它。(例如一个通行证系统,我可以将 USERID,USERNAME,USERPASSWORD,单独出来作个表,再把USERID作为其他表的外键) 表的设计具体注意的问题: 1、数据行的长度不要超过8020字节,如果超过这个长度的话在物理页中这条数据会占用两行从而造成存储碎片,降低查询效率。 2、能够用数字类型的字段尽量选择数字类型而不用字符串类型的(电话号码),这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接回逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。 3、对于不可变字符类型char和可变字符类型varchar 都是8000字节,char查询快,但是耗存储空间,varchar查询相对慢一些但是节省存储空间。在设计字段的时候可以灵活选择,例如用户名、密码等长度变化不大的字段可以选择CHAR,对于评论等长度变化大的字段可以选择VARCHAR。 4、字段的长度在最大限度的满足可能的需要的前提下,应该尽可能的设得短一些,这样可以提高查询的效率,而且在建立索引的时候也可以减少资源的消耗。 二、查询的优化 保证在实现功能的基础上,尽量减少对数据库的访问次数;通过搜索参数,尽量减少对表的访问行数,最小化结果集,从而减轻网络负担;能够分开的操作尽量分开处理,提高每次的响应速度;在数据窗口使用SQL时,尽量把使用的索引放在选择的首列;算法的结构尽量简单;在查询时,不要过多地使用通配符如SELECT * FROM T1语句,要用到几列就选择几列如:SELECT COL1,COL2 FROM T1;在可能的情况下尽量限制尽量结果集行数如:SELECT TOP 300 COL1,COL2,COL3 FROM T1,因为某些情况下用户是不需要那么多的数据的。 在没有建索引的情况下,数据库查找某一条数据,就必须进行全表扫描了,对所有数据进行一次遍历,查找出符合条件的记录。在数据量比较小的情况下,也许看不出明显的差别,但是当数据量大的情况下,这种情况就是极为糟糕的了。 SQL语句在SQL SERVER中是如何执行的,他们担心自己所写的SQL语句会被SQL SERVER误解。比如: select * from table1 where name='zhangsan' and tID > 10000 和执行: select * from table1 where tID > 10000 and name='zhangsan' 一些人不知道以上两条语句的执行效率是否一样,因为如果简单的从语句先后上看,这两个语句的确是不一样,如果tID是一个聚合索引,那么后一句仅仅从表的 10000条以后的记录中查找就行了;而前一句则要先从全表中查找看有几个name='zhangsan'的,而后再根据限制条件条件tID> 10000来提出查询结果。 事实上,这样的担心是不必要的。SQL SERVER中有一个“查询分析优化器”,它可以计算出where子句中的搜索条件并确定哪个索引能缩小表扫描的搜索空间,也就是说,它能实现自动优化。虽然查询优化器可以根据where子句自动的进行查询优化,但有时查询优化器就会不按照您的本意进行快速查询。 在查询分析阶段,查询优化器查看查询的每个阶段并决定限制需要扫描的数据量是否有用。如果一个阶段可以被用作一个扫描参数(SARG),那么就称之为可优化的,并且可以利用索引快速获得所需数据。 SARG的定义:用于限制搜索的一个操作,因为它通常是指一个特定的匹配,一个值的范围内的匹配或者两个以上条件的AND连接。形式如下: 列名 操作符 <常数 或 变量> 或 <常数 或 变量> 操作符 列名 列名可以出现在操作符的一边,而常数或变量出现在操作符的另一边。如: Name=’张三’ 价格>5000 5000<价格 Name=’张三’ and 价格>5000 如果一个表达式不能满足SARG的形式,那它就无法限制搜索的范围了,也就是SQL SERVER必须对每一行都判断它是否满足WHERE子句中的所有条件。所以一个索引对于不满足SARG形式的表达式来说是无用的。 所以,优化查询最重要的就是,尽量使语句符合查询优化器的规则避免全表扫描而使用索引查询。 具体要注意的: 1.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: select id from t where num=0 2.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。优化器将无法通过索引来确定将要命中的行数,因此需要搜索该表的所有行。 3.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num=10 or num=20 可以这样查询: select id from t where num=10 union all select id from t where num=20 4.in 和 not in 也要慎用,因为IN会使系统无法使用索引,而只能直接搜索表中的数据。如: select id from t where num in(1,2,3) 对于连续的数值,能用 between 就不要用 in 了: select id from t where num between 1 and 3 5.尽量避免在索引过的字符数据中,使用非打头字母搜索。这也使得引擎无法利用索引。 见如下例子: SELECT * FROM T1 WHERE NAME LIKE ‘%L%’ SELECT * FROM T1 WHERE SUBSTING(NAME,2,1)=’L’ SELECT * FROM T1 WHERE NAME LIKE ‘L%’ 即使NAME字段建有索引,前两个查询依然无法利用索引完成加快操作,引擎不得不对全表所有数据逐条操作来完成任务。而第三个查询能够使用索引来加快操作。 6.必要时强制查询优化器使用某个索引,如在 where 子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描: select id from t where num=@num 可以改为强制查询使用索引: select id from t with(index(索引名)) where num=@num 7.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如: SELECT * FROM T1 WHERE F1/2=100 应改为: SELECT * FROM T1 WHERE F1=100*2 SELECT * FROM RECORD WHERE SUBSTRING(CARD_NO,1,4)=’5378’ 应改为: SELECT * FROM RECORD WHERE CARD_NO LIKE ‘5378%’ SELECT member_number, first_name, last_name FROM members WHERE DATEDIFF(yy,datofbirth,GETDATE()) > 21 应改为: SELECT member_number, first_name, last_name FROM members WHERE dateofbirth < DATEADD(yy,-21,GETDATE()) 即:任何对列的操作都将导致表扫描,它包括数据库函数、计算表达式等等,查询时要尽可能将操作移至等号右边。 8.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如: select id from t where substring(name,1,3)='abc'--name以abc开头的id select id from t where datediff(day,createdate,'2005-11-30')=0--‘2005-11-30’生成的id 应改为: select id from t where name like 'abc%' select id from t where createdate>='2005-11-30' and createdate<'2005-12-1' 9.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。 10.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。 11.很多时候用 exists是一个好的选择: elect num from a where num in(select num from b) 用下面的语句替换: select num from a where exists(select 1 from b where num=a.num) SELECT SUM(T1.C1)FROM T1 WHERE( (SELECT COUNT(*)FROM T2 WHERE T2.C2=T1.C2>0) SELECT SUM(T1.C1) FROM T1WHERE EXISTS( SELECT * FROM T2 WHERE T2.C2=T1.C2) 两者产生相同的结果,但是后者的效率显然要高于前者。因为后者不会产生大量锁定的表扫描或是索引扫描。 如果你想校验表里是否存在某条纪录,不要用count(*)那样效率很低,而且浪费服务器资源。可以用EXISTS代替。如: IF (SELECT COUNT(*) FROM table_name WHERE column_name = 'xxx') 可以写成: IF EXISTS (SELECT * FROM table_name WHERE column_name = 'xxx') 经常需要写一个T_SQL语句比较一个父结果集和子结果集,从而找到是否存在在父结果集中有而在子结果集中没有的记录,如: SELECT a.hdr_key FROM hdr_tbl a---- tbl a 表示tbl用别名a代替 WHERE NOT EXISTS (SELECT * FROM dtl_tbl b WHERE a.hdr_key = b.hdr_key) SELECT a.hdr_key FROM hdr_tbl a LEFT JOIN dtl_tbl b ON a.hdr_key = b.hdr_key WHERE b.hdr_key IS NULL SELECT hdr_key FROM hdr_tbl WHERE hdr_key NOT IN (SELECT hdr_key FROM dtl_tbl) 三种写法都可以得到同样正确的结果,但是效率依次降低。 12.尽量使用表变量来代替临时表。如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。 13.避免频繁创建和删除临时表,以减少系统表资源的消耗。 14.临时表并不是不可使用,适当地使用它们可以使某些例程更有效,例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。 15.在新建临时表时,如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。 16.如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。 17.在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送 DONE_IN_PROC 消息。 18.尽量避免大事务操作,提高系统并发能力。 19.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。 20. 避免使用不兼容的数据类型。例如float和int、char和varchar、binary和varbinary是不兼容的。数据类型的不兼容可能使优化器无法执行一些本来可以进行的优化操作。例如: SELECT name FROM employee WHERE salary > 60000 在这条语句中,如salary字段是money型的,则优化器很难对其进行优化,因为60000是个整型数。我们应当在编程时将整型转化成为钱币型,而不要等到运行时转化。 21.充分利用连接条件,在某种情况下,两个表之间可能不只一个的连接条件,这时在 WHERE 子句中将连接条件完整的写上,有可能大大提高查询速度。 例: SELECT SUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO SELECT SUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO AND A.ACCOUNT_NO=B.ACCOUNT_NO 第二句将比第一句执行快得多。 22、使用视图加速查询 把表的一个子集进行排序并创建视图,有时能加速查询。它有助于避免多重排序 操作,而且在其他方面还能简化优化器的工作。例如: SELECT cust.name,rcvbles.balance,……other columns FROM cust,rcvbles WHERE cust.customer_id = rcvlbes.customer_id AND rcvblls.balance>0 AND cust.postcode>“98000” ORDER BY cust.name 如果这个查询要被执行多次而不止一次,可以把所有未付款的客户找出来放在一个视图中,并按客户的名字进行排序: CREATE VIEW DBO.V_CUST_RCVLBES AS SELECT cust.name,rcvbles.balance,……other columns FROM cust,rcvbles WHERE cust.customer_id = rcvlbes.customer_id AND rcvblls.balance>0 ORDER BY cust.name 然后以下面的方式在视图中查询: SELECT * FROM V_CUST_RCVLBES WHERE postcode>“98000” 视图中的行要比主表中的行少,而且物理顺序就是所要求的顺序,减少了磁盘I/O,所以查询工作量可以得到大幅减少。 23、能用DISTINCT的就不用GROUP BY SELECT OrderID FROM Details WHERE UnitPrice > 10 GROUP BY OrderID 可改为: SELECT DISTINCT OrderID FROM Details WHERE UnitPrice > 10 24.能用UNION ALL就不要用UNION UNION ALL不执行SELECT DISTINCT函数,这样就会减少很多不必要的资源 35.尽量不要用SELECT INTO语句。 SELECT INOT 语句会导致表锁定,阻止其他用户访问该表。 上面我们提到的是一些基本的提高查询速度的注意事项,但是在更多的情况下,往往需要反复试验比较不同的语句以得到最佳方案。最好的方法当然是测试,看实现相同功能的SQL语句哪个执行时间最少,但是数据库中如果数据量很少,是比较不出来的,这时可以用查看执行计划,即:把实现相同功能的多条SQL语句考到查询分析器,按CTRL+L看查所利用的索引,表扫描次数(这两个对性能影响最大),总体上看询成本百分比即可。 三、算法的优化 尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。与临时表一样,游标并不是不可使用。对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括“合计”的例程通常要比使用游标执行的速度快。如果开发时间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。 游标提供了对特定集合中逐行扫描的手段,一般使用游标逐行遍历数据,根据取出的数据不同条件进行不同的操作。尤其对多表和大表定义的游标(大的数据集合)循环很容易使程序进入一个漫长的等特甚至死机。 在有些场合,有时也非得使用游标,此时也可考虑将符合条件的数据行转入临时表中,再对临时表定义游标进行操作,可时性能得到明显提高。 (例如:对内统计第一版) 封装存储过程 四、建立高效的索引 创建索引一般有以下两个目的:维护被索引列的唯一性和提供快速访问表中数据的策略。大型数据库有两种索引即簇索引和非簇索引,一个没有簇索引的表是按堆结构存储数据,所有的数据均添加在表的尾部,而建立了簇索引的表,其数据在物理上会按照簇索引键的顺序存储,一个表只允许有一个簇索引,因此,根据B树结构,可以理解添加任何一种索引均能提高按索引列查询的速度,但会降低插入、更新、删除操作的性能,尤其是当填充因子(Fill Factor)较大时。所以对索引较多的表进行频繁的插入、更新、删除操作,建表和索引时因设置较小的填充因子,以便在各数据页中留下较多的自由空间,减少页分割及重新组织的工作。 索引是从数据库中获取数据的最高效方式之一。95% 的数据库性能问题都可以采用索引技术得到解决。作为一条规则,我通常对逻辑主键使用唯一的成组索引,对系统键(作为存储过程)采用唯一的非成组索引,对任何外键列[字段]采用非成组索引。不过,索引就象是盐,太多了菜就咸了。你得考虑数据库的空间有多大,表如何进行访问,还有这些访问是否主要用作读写。 实际上,您可以把索引理解为一种特殊的目录。微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引、簇集索引)和非聚集索引(nonclustered index,也称非聚类索引、非簇集索引)。下面,我们举例来说明一下聚集索引和非聚集索引的区别: 其实,我们的汉语字典的正文本身就是一个聚集索引。比如,我们要查“安”字,就会很自然地翻开字典的前几页,因为“安”的拼音是“an”,而按照拼音排序汉字的字典是以英文字母“a”开头并以 “z”结尾的,那么“安”字就自然地排在字典的前部。如果您翻完了所有以“a”开头的部分仍然找不到这个字,那么就说明您的字典中没有这个字;同样的,如果查“张”字,那您也会将您的字典翻到最后部分,因为“张”的拼音是“zhang”。也就是说,字典的正文部分本身就是一个目录,您不需要再去查其他目录来找到您需要找的内容。 我们把这种正文内容本身就是一种按照一定规则排列的目录称为“聚集索引”。 如果您认识某个字,您可以快速地从自动中查到这个字。但您也可能会遇到您不认识的字,不知道它的发音,这时候,您就不能按照刚才的方法找到您要查的字,而需要去根据“偏旁部首”查到您要找的字,然后根据这个字后的页码直接翻到某页来找到您要找的字。但您结合“部首目录”和“检字表”而查到的字的排序并不是真正的正文的排序方法,比如您查 “张”字,我们可以看到在查部首之后的检字表中“张”的页码是672页,检字表中“张”的上面是“驰”字,但页码却是63页,“张”的下面是“弩”字,页面是390页。很显然,这些字并不是真正的分别位于“张”字的上下方,现在您看到的连续的“驰、张、弩”三字实际上就是他们在非聚集索引中的排序,是字典正文中的字在非聚集索引中的映射。我们可以通过这种方式来找到您所需要的字,但它需要两个过程,先找到目录中的结果,然后再翻到您所需要的页码。 我们把这种目录纯粹是目录,正文纯粹是正文的排序方式称为“非聚集索引”。 进一步引申一下,我们可以很容易的理解:每个表只能有一个聚集索引,因为目录只能按照一种方法进行排序。 (一)何时使用聚集索引或非聚集索引 下面的表总结了何时使用聚集索引或非聚集索引(很重要)。 动作描述 使用聚集索引 使用非聚集索引 列经常被分组排序 应 应 返回某范围内的数据 应 不应 一个或极少不同值 不应 不应 小数目的不同值 应 不应 大数目的不同值 不应 应 频繁更新的列 不应 应 外键列 应 应 主键列 应 应 频繁修改索引列 不应 应 事实上,我们可以通过前面聚集索引和非聚集索引的定义的例子来理解上表。如:返回某范围内的数据一项。比如您的某个表有一个时间列,恰好您把聚合索引建立在了该列,这时您查询2004年1月1日至2004年10月1日之间的全部数据时,这个速度就将是很快的,因为您的这本字典正文是按日期进行排序的,聚类索引只需要找到要检索的所有数据中的开头和结尾数据即可;而不像非聚集索引,必须先查到目录中查到每一项数据对应的页码,然后再根据页码查到具体内容。 (二)结合实际,谈索引使用的误区 理论的目的是应用。虽然我们刚才列出了何时应使用聚集索引或非聚集索引,但在实践中以上规则却很容易被忽视或不能根据实际情况进行综合分析。下面我们将根据在实践中遇到的实际问题来谈一下索引使用的误区,以便于大家掌握索引建立的方法。 1、主键就是聚集索引 这种想法笔者认为是极端错误的,是对聚集索引的一种浪费。虽然SQL SERVER默认是在主键上建立聚集索引的。 通常,我们会在每个表中都建立一个ID列,以区分每条数据,并且这个ID列是自动增大的,步长一般为1。我们的这个办公自动化的实例中的列Gid就是如此。此时,如果我们将这个列设为主键,SQL SERVER会将此列默认为聚集索引。这样做有好处,就是可以让您的数据在数据库中按照ID进行物理排序,但笔者认为这样做意义不大。 显而易见,聚集索引的优势是很明显的,而每个表中只能有一个聚集索引的规则,这使得聚集索引变得更加珍贵。 从我们前面谈到的聚集索引的定义我们可以看出,使用聚集索引的最大好处就是能够根据查询要求,迅速缩小查询范围,避免全表扫描。在实际应用中,因为ID号是自动生成的,我们并不知道每条记录的ID号,所以我们很难在实践中用ID号来进行查询。这就使让ID号这个主键作为聚集索引成为一种资源浪费。其次,让每个ID号都不同的字段作为聚集索引也不符合“大数目的不同值情况下不应建立聚合索引”规则;当然,这种情况只是针对用户经常修改记录内容,特别是索引项的时候会负作用,但对于查询速度并没有影响。 在办公自动化系统中,无论是系统首页显示的需要用户签收的文件、会议还是用户进行文件查询等任何情况下进行数据查询都离不开字段的是“日期”还有用户本身的“用户名”。 通常,办公自动化的首页会显示每个用户尚未签收的文件或会议。虽然我们的where语句可以仅仅限制当前用户尚未签收的情况,但如果您的系统已建立了很长时间,并且数据量很大,那么,每次每个用户打开首页的时候都进行一次全表扫描,这样做意义是不大的,绝大多数的用户1个月前的文件都已经浏览过了,这样做只能徒增数据库的开销而已。事实上,我们完全可以让用户打开系统首页时,数据库仅仅查询这个用户近3个月来未阅览的文件,通过“日期”这个字段来限制表扫描,提高查询速度。如果您的办公自动化系统已经建立的2年,那么您的首页显示速度理论上将是原来速度8倍,甚至更快。 2、只要建立索引就能显著提高查询速度 事实上,我们可以发现上面的例子中,第2、3条语句完全相同,且建立索引的字段也相同;不同的仅是前者在fariqi字段上建立的是非聚合索引,后者在此字段上建立的是聚合索引,但查询速度却有着天壤之别。所以,并非是在任何字段上简单地建立索引就能提高查询速度。 从建表的语句中,我们可以看到这个有着1000万数据的表中fariqi字段有5003个不同记录。在此字段上建立聚合索引是再合适不过了。在现实中,我们每天都会发几个文件,这几个文件的发文日期就相同,这完全符合建立聚集索引要求的:“既不能绝大多数都相同,又不能只有极少数相同”的规则。由此看来,我们建立“适当”的聚合索引对于我们提高查询速度是非常重要的。 3、把所有需要提高查询速度的字段都加进聚集索引,以提高查询速度 “日期”还有用户本身的“用户名,可以把他们合并起来,建立一个复合索引(compound index)。 记住:无论您是否经常使用聚合索引的其他列,但其前导列一定要是使用最频繁的列。 |
|||
Java @override报错的解决方法 | java @override报错的解决方法 | ||
Java @override报错的解决方法 标签: javaeclipsejdk 2011-11-02 09:28 43578人阅读 评论(12) 收藏 举报 分类: Java(5) 版权声明:本文为博主原创文章,未经博主允许不得转载。 有时候Java的Eclipse工程换一台电脑后编译总是@override报错,把@override去掉就好了,但不能从根本上解决问题,因为有时候有@override的地方超级多。 这是jdk的问题,@Override是JDK5就已经有了,但是不支持对接口的实现,认为这不是Override而报错。JDK6修正了这个Bug,无论是对父类的方法覆盖还是对接口的实现都可以加上@Override。 要解决该问题,首先要确保机器上安装了jdk 1.6, 然后,选择eclipse菜单Windows->Preferences-->java->Compiler-->compiler compliance level选择 1.6,刷新工程,重新编译。 如果问题还没解决,就在报错的工程上,鼠标右键选择 Properties-->Java Compiler-->compiler compliance level 中选择 1.6,刷新工程,重新编译 |
|||
java事件驱动模型简介 | 事件驱动模型简介 | 事件驱动模型简介 | |
事件驱动模型简介 事件驱动模型也就是我们常说的观察者,或者发布-订阅模型;理解它的几个关键点: 首先是一种对象间的一对多的关系;最简单的如交通信号灯,信号灯是目标(一方),行人注视着信号灯(多方); 当目标发送改变(发布),观察者(订阅者)就可以接收到改变; 观察者如何处理(如行人如何走,是快走/慢走/不走,目标不会管的),目标无需干涉;所以就松散耦合了它们之间的关系。 接下来先看一个用户注册的例子: 用户注册成功后,需要做这么多事: 1、加积分 2、发确认邮件 3、如果是游戏帐户,可能赠送游戏大礼包 4、索引用户数据 ………… 问题: UserService和其他Service耦合严重,增删功能比较麻烦; 有些功能可能需要调用第三方系统,如增加积分/索引用户,速度可能比较慢,此时需要异步支持;这个如果使用Spring,可以轻松解决,后边再介绍; 从如上例子可以看出,应该使用一个观察者来解耦这些Service之间的依赖关系,如图: 增加了一个Listener来解耦UserService和其他服务,即注册成功后,只需要通知相关的监听器,不需要关系它们如何处理。增删功能非常容易。 这就是一个典型的事件处理模型/观察者,解耦目标对象和它的依赖对象,目标只需要通知它的依赖对象,具体怎么处理,依赖对象自己决定。比如是异步还是同步,延迟还是非延迟等。 上边其实也使用了DIP(依赖倒置原则),依赖于抽象,而不是具体。 还是就是使用了IoC思想,即以前主动去创建它依赖的Service,现在只是被动等待别人注册进来。 其他的例子还有如GUI中的按钮和动作的关系,按钮和动作本身都是一种抽象,每个不同的按钮的动作可能不一样;如“文件-->新建”打开新建窗口;点击“关闭”按钮关闭窗口等等。 主要目的是:松散耦合对象间的一对多的依赖关系,如按钮和动作的关系; 如何实现呢?面向接口编程(即面向抽象编程),而非面向实现。即按钮和动作可以定义为接口,这样它俩的依赖是最小的(如在Java中,没有比接口更抽象的了)。 有朋友会问,我刚开始学的时候也是这样:抽象类不也行吗?记住一个原则:接口目的是抽象,抽象类目的是复用;所以如果接触过servlet/struts2/spring等框架,大家都应该知道: Servlet<-----GenericServlet<-----HttpServlet<------我们自己的 Action<------ActionSupport<------我们自己的 DaoInterface<------××DaoSupport<-----我们自己的 从上边大家应该能体会出接口、抽象类的主要目的了。现在想想其实很简单。 在Java中接口还一个非常重要的好处:接口是可以多实现的,类/抽象类只能单继承,所以使用接口可以非常容易扩展新功能(还可以实现所谓的mixin),类/抽象类办不到。 Java GUI事件驱动模型/观察者 扯远了,再来看看Java GUI世界里的事件驱动模型吧: 如果写过AWT/Swing程序,应该知道其所有组件都继承自java.awt.Component抽象类,其内部提供了addXXXListener(XXXListener l) 注册监听器的方法,即Component与实际动作之间依赖于XXXListener抽象。 比如获取焦点事件,很多组件都可以有这个事件,是我们知道组件获取到焦点后需要一个处理,虽然每个组件如何处理是特定的(具体的),但我们可以抽象一个FocusListener,让所有具体实现它然后提供具体动作,这样组件只需依赖于FocusListener抽象,而不是具体。 还有如java.awt.Button,提供了一个addActionListener(ActionListener l),用于注册点击后触发的ActionListener实现。 组件是一个抽象类,其好处主要是复用,比如复用这些监听器的触发及管理等。 JavaBean规范的事件驱动模型/观察者 JavaBean规范提供了JavaBean的PropertyEditorSupport及PropertyChangeListener支持。 PropertyEditorSupport就是目标,而PropertyChangeListener就是监听器,大家可以google搜索下,具体网上有很多例子。 Java提供的事件驱动模型/观察者抽象 JDK内部直接提供了观察者模式的抽象: 目标:java.util.Observable,提供了目标需要的关键抽象:addObserver/deleteObserver/notifyObservers()等,具体请参考javadoc。 观察者:java.util.Observer,提供了观察者需要的主要抽象:update(Observable o, Object arg),此处还提供了一种推模型(目标主动把数据通过arg推到观察者)/拉模型(目标需要根据o自己去拉数据,arg为null)。 因为网上介绍的非常多了,请google搜索了解如何使用这个抽象及推/拉模型的优缺点。 接下来是我们的重点:spring提供的事件驱动模型。 Spring提供的事件驱动模型/观察者抽象 首先看一下Spring提供的事件驱动模型体系图: 事件 具体代表者是:ApplicationEvent: 1、其继承自JDK的EventObject,JDK要求所有事件将继承它,并通过source得到事件源,比如我们的AWT事件体系也是继承自它; 2、系统默认提供了如下ApplicationEvent事件实现: 只有一个ApplicationContextEvent,表示ApplicationContext容器事件,且其又有如下实现: ContextStartedEvent:ApplicationContext启动后触发的事件;(目前版本没有任何作用) ContextStoppedEvent:ApplicationContext停止后触发的事件;(目前版本没有任何作用) ContextRefreshedEvent:ApplicationContext初始化或刷新完成后触发的事件;(容器初始化完成后调用) ContextClosedEvent:ApplicationContext关闭后触发的事件;(如web容器关闭时自动会触发spring容器的关闭,如果是普通java应用,需要调用ctx.registerShutdownHook();注册虚拟机关闭时的钩子才行) 注:org.springframework.context.support.AbstractApplicationContext抽象类实现了LifeCycle的start和stop回调并发布ContextStartedEvent和ContextStoppedEvent事件;但是无任何实现调用它,所以目前无任何作用。 目标(发布事件者) 具体代表者是:ApplicationEventPublisher及ApplicationEventMulticaster,系统默认提供了如下实现: 1、ApplicationContext接口继承了ApplicationEventPublisher,并在AbstractApplicationContext实现了具体代码,实际执行是委托给ApplicationEventMulticaster(可以认为是多播): Java代码 收藏代码 public void publishEvent(ApplicationEvent event) { //省略部分代码 } getApplicationEventMulticaster().multicastEvent(event); if (this.parent != null) { this.parent.publishEvent(event); } } 我们常用的ApplicationContext都继承自AbstractApplicationContext,如ClassPathXmlApplicationContext、XmlWebApplicationContext等。所以自动拥有这个功能。 2、ApplicationContext自动到本地容器里找一个名字为”“的ApplicationEventMulticaster实现,如果没有自己new一个SimpleApplicationEventMulticaster。其中SimpleApplicationEventMulticaster发布事件的代码如下: Java代码 收藏代码 public void multicastEvent(final ApplicationEvent event) { for (final ApplicationListener listener : getApplicationListeners(event)) { Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { public void run() { listener.onApplicationEvent(event); } }); } else { listener.onApplicationEvent(event); } } } 大家可以看到如果给它一个executor(java.util.concurrent.Executor),它就可以异步支持发布事件了。佛则就是通过发送。 所以我们发送事件只需要通过ApplicationContext.publishEvent即可,没必要再创建自己的实现了。除非有必要。 监听器 具体代表者是:ApplicationListener 1、其继承自JDK的EventListener,JDK要求所有监听器将继承它,比如我们的AWT事件体系也是继承自它; 2、ApplicationListener接口: Java代码 收藏代码 public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { void onApplicationEvent(E event); } 其只提供了onApplicationEvent方法,我们需要在该方法实现内部判断事件类型来处理,也没有提供按顺序触发监听器的语义,所以Spring提供了另一个接口,SmartApplicationListener: Java代码 收藏代码 public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered { //如果实现支持该事件类型 那么返回true boolean supportsEventType(Class<? extends ApplicationEvent> eventType); //如果实现支持“目标”类型,那么返回true boolean supportsSourceType(Class<?> sourceType); //顺序,即监听器执行的顺序,值越小优先级越高 int getOrder(); } 该接口可方便实现去判断支持的事件类型、目标类型,及执行顺序。 Spring事件机制的简单例子 本例子模拟一个给多个人发送内容(类似于报纸新闻)的例子。 1、定义事件 Java代码 收藏代码 package com.sishuok.hello; import org.springframework.context.ApplicationEvent; public class ContentEvent extends ApplicationEvent { public ContentEvent(final String content) { super(content); } } 非常简单,如果用户发送内容,只需要通过构造器传入内容,然后通过getSource即可获取。 2、定义无序监听器 之所以说无序,类似于AOP机制,顺序是无法确定的。 Java代码 收藏代码 package com.sishuok.hello; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; @Component public class LisiListener implements ApplicationListener<ApplicationEvent> { @Override public void onApplicationEvent(final ApplicationEvent event) { if(event instanceof ContentEvent) { System.out.println("李四收到了新的内容:" + event.getSource()); } } } 1、使用@Compoent注册Bean即可; 2、在实现中需要判断event类型是ContentEvent才可以处理; 更简单的办法是通过泛型指定类型,如下所示 Java代码 收藏代码 package com.sishuok.hello; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; @Component public class ZhangsanListener implements ApplicationListener<ContentEvent> { @Override public void onApplicationEvent(final ContentEvent event) { System.out.println("张三收到了新的内容:" + event.getSource()); } } 3、定义有序监听器 实现SmartApplicationListener接口即可。 Java代码 收藏代码 package com.sishuok.hello; import org.springframework.context.ApplicationEvent; import org.springframework.context.event.SmartApplicationListener; import org.springframework.stereotype.Component; @Component public class WangwuListener implements SmartApplicationListener { @Override public boolean supportsEventType(final Class<? extends ApplicationEvent> eventType) { return eventType == ContentEvent.class; } @Override public boolean supportsSourceType(final Class<?> sourceType) { return sourceType == String.class; } @Override public void onApplicationEvent(final ApplicationEvent event) { System.out.println("王五在孙六之前收到新的内容:" + event.getSource()); } @Override public int getOrder() { return 1; } } Java代码 收藏代码 package com.sishuok.hello; import org.springframework.context.ApplicationEvent; import org.springframework.context.event.SmartApplicationListener; import org.springframework.stereotype.Component; @Component public class SunliuListener implements SmartApplicationListener { @Override public boolean supportsEventType(final Class<? extends ApplicationEvent> eventType) { return eventType == ContentEvent.class; } @Override public boolean supportsSourceType(final Class<?> sourceType) { return sourceType == String.class; } @Override public void onApplicationEvent(final ApplicationEvent event) { System.out.println("孙六在王五之后收到新的内容:" + event.getSource()); } @Override public int getOrder() { return 2; } } supportsEventType:用于指定支持的事件类型,只有支持的才调用onApplicationEvent; supportsSourceType:支持的目标类型,只有支持的才调用onApplicationEvent; getOrder:即顺序,越小优先级越高 4、测试 4.1、配置文件 Java代码 收藏代码 <context:component-scan base-package="com.sishuok"/> 就一句话,自动扫描注解Bean。 4.2、测试类 Java代码 收藏代码 package com.sishuok; import com.sishuok.hello.ContentEvent; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"classpath:spring-config-hello.xml"}) public class HelloIT { @Autowired private ApplicationContext applicationContext; @Test public void testPublishEvent() { applicationContext.publishEvent(new ContentEvent("今年是龙年的博客更新了")); } } 接着会输出: Java代码 收藏代码 王五在孙六之前收到新的内容:今年是龙年的博客更新了 孙六在王五之后收到新的内容:今年是龙年的博客更新了 李四收到了新的内容:今年是龙年的博客更新了 张三收到了新的内容:今年是龙年的博客更新了 一个简单的测试例子就演示完毕,而且我们使用spring的事件机制去写相关代码会非常简单。 Spring事件机制实现之前提到的注册流程 具体请下载源代码参考com.sishuok.register包里的代码。此处贴一下源码结构: 这里讲解一下Spring对异步事件机制的支持,实现方式有两种: 1、全局异步 即只要是触发事件都是以异步执行,具体配置(spring-config-register.xml)如下: Java代码 收藏代码 <task:executor id="executor" pool-size="10" /> <!-- 名字必须是applicationEventMulticaster和messageSource是一样的,默认找这个名字的对象 --> <!-- 名字必须是applicationEventMulticaster,因为AbstractApplicationContext默认找个 --> <!-- 如果找不到就new一个,但不是异步调用而是同步调用 --> <bean id="applicationEventMulticaster" class="org.springframework.context.event.SimpleApplicationEventMulticaster"> <!-- 注入任务执行器 这样就实现了异步调用(缺点是全局的,要么全部异步,要么全部同步(删除这个属性即是同步)) --> <property name="taskExecutor" ref="executor"/> </bean> 通过注入taskExecutor来完成异步调用。具体实现可参考之前的代码介绍。这种方式的缺点很明显:要么大家都是异步,要么大家都不是。所以不推荐使用这种方式。 2、更灵活的异步支持 spring3提供了@Aync注解来完成异步调用。此时我们可以使用这个新特性来完成异步调用。不仅支持异步调用,还支持简单的任务调度,比如我的项目就去掉Quartz依赖,直接使用spring3这个新特性,具体可参考spring-config.xml。 2.1、开启异步调用支持 Java代码 收藏代码 <!-- 开启@AspectJ AOP代理 --> <aop:aspectj-autoproxy proxy-target-class="true"/> <!-- 任务调度器 --> <task:scheduler id="scheduler" pool-size="10"/> <!-- 任务执行器 --> <task:executor id="executor" pool-size="10"/> <!--开启注解调度支持 @Async @Scheduled--> <task:annotation-driven executor="executor" scheduler="scheduler" proxy-target-class="true"/> 2.2、配置监听器让其支持异步调用 Java代码 收藏代码 @Component public class EmailRegisterListener implements ApplicationListener<RegisterEvent> { @Async @Override public void onApplicationEvent(final RegisterEvent event) { System.out.println("注册成功,发送确认邮件给:" + ((User)event.getSource()).getUsername()); } } 使用@Async注解即可,非常简单。 这样不仅可以支持通过调用,也支持异步调用,非常的灵活,实际应用推荐大家使用这种方式。 通过如上,大体了解了Spring的事件机制,可以使用该机制非常简单的完成如注册流程,而且对于比较耗时的调用,可以直接使用Spring自身的异步支持来优化。 spring发布和接收定制的事件(spring事件传播) 2012-12-26 20:05 15785人阅读 评论(1) 收藏 举报 分类: 开源技术(如Struts/spring/Hibernate等)(70) 架构和设计模式(59) 版权声明:本文为博主原创文章,未经博主允许不得转载。 有事件,即有事件监听器. 有人问你spring监听器有哪些你看了下文即也知道了。 事件传播 ApplicationContext基于Observer模式(java.util包中有对应实现),提供了针对Bean的事件传 播功能。通过Application. publishEvent方法,我们可以将事件通知系统内所有的 ApplicationListener。 事件传播的一个典型应用是,当Bean中的操作发生异常(如数据库连接失败),则通过事件传播 机制通知异常监听器进行处理。在笔者的一个项目中,就曾经借助事件机制,较好的实现了当系统 异常时在监视终端上报警,同时发送报警SMS至管理员手机的功能。 ApplicationContext容器提供了容器内部事件发布功能,是继承自JavaSE标准自定义事件类而实现的。 JavaSE标准自定义事件结构不在此详细描述,一张图很直观的描述清楚: EventObject,为JavaSE提供的事件类型基类,任何自定义的事件都继承自该类,例如上图中右侧灰色的各个事件。Spring中提供了该接口的子类ApplicationEvent。 EventListener为JavaSE提供的事件监听者接口,任何自定义的事件监听者都实现了该接口,如上图左侧的各个事件监听者。Spring中提供了该接口的子类ApplicationListener接口。 JavaSE中未提供事件发布者这一角色类,由各个应用程序自行实现事件发布者这一角色。Spring中提供了ApplicationEventPublisher接口作为事件发布者,并且ApplicationContext实现了这个接口,担当起了事件发布者这一角色。但ApplicationContext在具体实现上有所差异,Spring提供了ApplicationEventMulticaster接口,负责管理ApplicationListener和发布ApplicationEvent。ApplicationContext会把相应的事件相关工作委派给ApplicationEventMulticaster接口实现类来做。类图如下所示: 事件发布时序图如下: ------------------------------------------------------------------------------------------------- Spring中提供一些Aware相关的接口,BeanFactoryAware、 ApplicationContextAware、ResourceLoaderAware、ServletContextAware等等,其中最常用到的是ApplicationContextAware。实现ApplicationContextAware的Bean,在Bean被初始后,将会被注入ApplicationContext的实例。ApplicationContextAware提供了publishEvent()方法,实现Observer(观察者)设计模式的事件传播机,提供了针对Bean的事件传播功能。通过Application.publishEvent方法,我们可以将事件通知系统内所有的ApplicationListener。 Spring事件处理一般过程: ◆定义Event类,继承org.springframework.context.ApplicationEvent。 ◆编写发布事件类Publisher,实现org.springframework.context.ApplicationContextAware接口。 ◆覆盖方法setApplicationContext(ApplicationContext applicationContext)和发布方法publish(Object obj)。 ◆定义时间监听类EventListener,实现ApplicationListener接口,实现方法onApplicationEvent(ApplicationEvent event)。 1.发布 1.1事件的发布者需要实现的接口 org.springframework.context.ApplicationEventPublisherAware 1.2 代码示例 import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; /** * * @author zq * */ public class HelloWorld implements ApplicationEventPublisherAware{ private String word; private ApplicationEventPublisher tradeEventPublisher; public void setWord(String w){ this.word = w; } public void say(){ System.out.println("say : "+ this.word); //construct a TradeEvent instance and publish it TradeEvent tradeEvent = new TradeEvent(new String("tradeEvent")); this.tradeEventPublisher.publishEvent(tradeEvent); } @Override public void setApplicationEventPublisher( ApplicationEventPublisher applicationEventPublisher) { // TODO Auto-generated method stub this.tradeEventPublisher = applicationEventPublisher; } } 2.接受事件 2.1需要实现的接口org.springframework.context.ApplicationListener 2.2代码示例 import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextStartedEvent; public class TradeContextListener implements ApplicationListener{ @Override public void onApplicationEvent(ApplicationEvent e) { System.out.println(e.getClass().toString()); // TODO Auto-generated method stub if (e instanceof ContextStartedEvent){ System.out.println("it was contextStartedEvent"); } if (e instanceof TradeEvent){ System.out.println(e.getSource()); } } } 3配置文件 <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean name="helloWorld" class="study.HelloWorld"> <property name="word" value="hello world"/> </bean> <bean id="tradeContextListener" class="study.TradeContextListener"/> </beans> 4.测试代码 import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import study.HelloWorld; public class TestHelloWorld { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub ApplicationContext applicationContext = new ClassPathXmlApplicationContext("study-context.xml"); HelloWorld bean = (HelloWorld)applicationContext.getBean("helloWorld"); bean.say(); } } Spring中ApplicationContext的事件机制--- 内定事件) 在Spring中已经定义了五个标准事件,分别介绍如下: 1) ContextRefreshedEvent:当ApplicationContext初始化或者刷新时触发该事件。 2) ContextClosedEvent:当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。 3) RequestHandleEvent:在Web应用中,当一个http请求(request)结束触发该事件。 ContestStartedEvent:Spring2.5新增的事件,当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。 5) ContestStopedEvent:Spring2.5新增的事件,当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。 下面通过一个例子展示如何处理Spring内定的事件(例程3.8)。创建一个Java工程,添加Spring开发能力后,新建ioc.test包。在包中新建ApplicationEventListener类,实现ApplicationListener接口,在onApplicationEvent()方法中添加事件处理代码,如下: 1 package ioc.test; 2 3 //Import省略 4 publicclass ApplicationEventListenerimplements ApplicationListener { 5 6 publicvoid onApplicationEvent(ApplicationEvent event) { 7 8 //如果是容器刷新事件 9 if(eventinstanceof ContextClosedEvent ){ 10 System.out.println(event.getClass().getSimpleName()+" 事件已发生!"); 11 }elseif(eventinstanceof ContextRefreshedEvent ){//如果是容器关闭事件 12 System.out.println(event.getClass().getSimpleName()+" 事件已发生!"); 13 }elseif(eventinstanceof ContextStartedEvent ){ 14 System.out.println(event.getClass().getSimpleName()+" 事件已发生!"); 15 }elseif(eventinstanceof ContextStoppedEvent){ 16 System.out.println(event.getClass().getSimpleName()+" 事件已发生!"); 17 }else{ 18 System.out.println("有其它事件发生:"+event.getClass().getName()); 19 } 20 21 } 22 23 } 24 在Spring配置文件中定义一个Bean,类为ApplicationEventListener,代码如下: 1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans………… 3 4 <bean id="ApplicationEventListener" class="ioc.test.ApplicationEventListener"/> 5 6 </beans> 7 添加含有主方法的TesMain类,在主方法中,调用容器的相应方法,触发Spring内定事件,代码如下: 1 package ioc.test; 2 3 //import省略 4 publicclass TesMain { 5 6 publicstaticvoid main(String[] args) { 7 AbstractApplicationContext ac=new ClassPathXmlApplicationContext("applicationContext.xml"); 8 9 10 // ac.refresh();//触发ContextRefreshedEvent事件 11 ac.start();//触发ContextStartedEvent事件 12 ac.stop(); //触发ContextStoppedEvent事件 13 ac.close();//关闭容器,触发ContextClosedEvent事件 14 15 } 16 } 17 运行主类,控制台输出如下: 从例子中可以知道,要注册事件监听器,我们只需要把它配置成一个Bean即可,ApplicationContext容器会自动将其注册。 |
|||
radis | sql | Java中使用Jedis操作Redis | |
使用Java操作Redis需要jedis-2.1.0.jar,下载地址:http://files.cnblogs.com/liuling/jedis-2.1.0.jar.zip 如果需要使用Redis连接池的话,还需commons-pool-1.5.4.jar,下载地址:http://files.cnblogs.com/liuling/commons-pool-1.5.4.jar.zip http://www.runoob.com/redis/redis-tutorial.html package com.test; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.junit.Before; import org.junit.Test; import redis.clients.jedis.Jedis; public class TestRedis { private Jedis jedis; @Before public void setup() { //连接redis服务器,192.168.0.100:6379 jedis = new Jedis("192.168.0.100", 6379); //权限认证 jedis.auth("admin"); } /** * redis存储字符串 */ @Test public void testString() { //-----添加数据---------- jedis.set("name","xinxin");//向key-->name中放入了value-->xinxin System.out.println(jedis.get("name"));//执行结果:xinxin jedis.append("name", " is my lover"); //拼接 System.out.println(jedis.get("name")); jedis.del("name"); //删除某个键 System.out.println(jedis.get("name")); //设置多个键值对 jedis.mset("name","liuling","age","23","qq","476777XXX"); jedis.incr("age"); //进行加1操作 System.out.println(jedis.get("name") + "-" + jedis.get("age") + "-" + jedis.get("qq")); } /** * redis操作Map */ @Test public void testMap() { //-----添加数据---------- Map<String, String> map = new HashMap<String, String>(); map.put("name", "xinxin"); map.put("age", "22"); map.put("qq", "123456"); jedis.hmset("user",map); //取出user中的name,执行结果:[minxr]-->注意结果是一个泛型的List //第一个参数是存入redis中map对象的key,后面跟的是放入map中的对象的key,后面的key可以跟多个,是可变参数 List<String> rsmap = jedis.hmget("user", "name", "age", "qq"); System.out.println(rsmap); //删除map中的某个键值 jedis.hdel("user","age"); System.out.println(jedis.hmget("user", "age")); //因为删除了,所以返回的是null System.out.println(jedis.hlen("user")); //返回key为user的键中存放的值的个数2 System.out.println(jedis.exists("user"));//是否存在key为user的记录 返回true System.out.println(jedis.hkeys("user"));//返回map对象中的所有key System.out.println(jedis.hvals("user"));//返回map对象中的所有value Iterator<String> iter=jedis.hkeys("user").iterator(); while (iter.hasNext()){ String key = iter.next(); System.out.println(key+":"+jedis.hmget("user",key)); } } /** * jedis操作List */ @Test public void testList(){ //开始前,先移除所有的内容 jedis.del("java framework"); System.out.println(jedis.lrange("java framework",0,-1)); //先向key java framework中存放三条数据 jedis.lpush("java framework","spring"); jedis.lpush("java framework","struts"); jedis.lpush("java framework","hibernate"); //再取出所有数据jedis.lrange是按范围取出, // 第一个是key,第二个是起始位置,第三个是结束位置,jedis.llen获取长度 -1表示取得所有 System.out.println(jedis.lrange("java framework",0,-1)); jedis.del("java framework"); jedis.rpush("java framework","spring"); jedis.rpush("java framework","struts"); jedis.rpush("java framework","hibernate"); System.out.println(jedis.lrange("java framework",0,-1)); } /** * jedis操作Set */ @Test public void testSet(){ //添加 jedis.sadd("user","liuling"); jedis.sadd("user","xinxin"); jedis.sadd("user","ling"); jedis.sadd("user","zhangxinxin"); jedis.sadd("user","who"); //移除noname jedis.srem("user","who"); System.out.println(jedis.smembers("user"));//获取所有加入的value System.out.println(jedis.sismember("user", "who"));//判断 who 是否是user集合的元素 System.out.println(jedis.srandmember("user")); System.out.println(jedis.scard("user"));//返回集合的元素个数 } @Test public void test() throws InterruptedException { //jedis 排序 //注意,此处的rpush和lpush是List的操作。是一个双向链表(但从表现来看的) jedis.del("a");//先清除数据,再加入数据进行测试 jedis.rpush("a", "1"); jedis.lpush("a","6"); jedis.lpush("a","3"); jedis.lpush("a","9"); System.out.println(jedis.lrange("a",0,-1));// [9, 3, 6, 1] System.out.println(jedis.sort("a")); //[1, 3, 6, 9] //输入排序后结果 System.out.println(jedis.lrange("a",0,-1)); } @Test public void testRedisPool() { RedisUtil.getJedis().set("newname", "中文测试"); System.out.println(RedisUtil.getJedis().get("newname")); } } |
|||
mysql | sql | 【Mysql进阶技巧(1)】 MySQL的多表关联与自连接 | |
MySQL的多表关联与自连接 时间 2015-05-03 16:48:15 博客园-原创精华区 原文 http://www.cnblogs.com/nixi8/p/4474234.html 主题 MySQL 自连接 测试数据准备 CREATE TABLE `t2` ( `id` int(11) NOT NULL, `gid` char(1) DEFAULT NULL, `col1` int(11) DEFAULT NULL, `col2` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; insert into t2 values (1,'A',31,6), (2,'B',25,83), (3,'C',76,21), (4,'D',63,56), (5,'E',3,17), (6,'A',29,97), (7,'B',88,63), (8,'C',16,22), (9,'D',25,43), (10,'E',45,28), (11,'A',2,78), (12,'B',30,79), (13,'C',96,73), (14,'D',37,40), (15,'E',14,86), (16,'A',32,67), (17,'B',84,38), (18,'C',27,9), (19,'D',31,21), (20,'E',80,63), (21,'A',89,9), (22,'B',15,22), (23,'C',46,84), (24,'D',54,79), (25,'E',85,64), (26,'A',87,13), (27,'B',40,45), (28,'C',34,90), (29,'D',63,8), (30,'E',66,40), (31,'A',83,49), (32,'B',4,90), (33,'C',81,7), (34,'D',11,12), (35,'E',85,10), (36,'A',39,75), (37,'B',22,39), (38,'C',76,67), (39,'D',20,11), (40,'E',81,36); 通过自连接查询每组col2最大的值; -- 方法1: select * from t2 as a where not exists (select 1 from t2 where gid=a.gid and col2>a.col2); -- 1. select 1 from t2 where gid=a.gid and col2>a.col2 : select就进入了隐式迭代,同组中比当前col2大的就输出1; -- 2. 然后not exists来判断是否存在比当前col2大的,如果不存在就返回true;返回true就输出当前col2这一列; -- 3. 这里的exists与not exists是判断语句,返回的是true or false; -- 方法2: select * from (select * from t2 order by gid,col2 desc) as t group by gid; -- t2按照gid和col2来降序排列,然后group分组,分组就取的是frist row,而frist row就是最大的值; -- 乍看之下貌似不用自连接也可以搞定,但是group by分组是不能放在order by之后的,否则就会报错; 通过自连接查询每组col2最大的三个值; select * from t2 as a where 3 > (select count(*) from t2 where gid=a.gid and col2>a.col2) order by a.gid,a.col2 desc; -- 比当前col2大的值如果小于三条就输出(注意必须是小于三条,如果等于三条就代表已经有了三条),然后输出后排序; 上面两条自连接sql都比较难理解,但只要换个角度,其实理解起来也很容易,首先在mysql中要把select翻译为输出,并且要满足where以后才输出;输出以后再分组,分组以后才轮到排序,排序之后才轮到取几个 JOIN [inner] join,left join,right join; 通过join,mysql可以做到集合中的求交集,并集,差集等需求,但比起类似redis等集合来说,效率差了不止一个级别了; 数据准备 -- 创建数据表 CREATE TABLE IF NOT EXISTS tdb_goods( goods_id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, goods_name VARCHAR(150) NOT NULL, goods_cate VARCHAR(40) NOT NULL, brand_name VARCHAR(40) NOT NULL, goods_price DECIMAL(15,3) UNSIGNED NOT NULL DEFAULT 0, is_show BOOLEAN NOT NULL DEFAULT 1, is_saleoff BOOLEAN NOT NULL DEFAULT 0 )ENGINE=MyISAM AUTO_INCREMENT=24 DEFAULT CHARSET=utf8 COMMENT='测试商品表'; -- 写入记录 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('R510VC 15.6英寸笔记本','笔记本','华硕','3399',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('Y400N 14.0英寸笔记本电脑','笔记本','联想','4899',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('G150TH 15.6英寸游戏本','游戏本','雷神','8499',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('X550CC 15.6英寸笔记本','笔记本','华硕','2799',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('X240(20ALA0EYCD) 12.5英寸超极本','超级本','联想','4999',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('U330P 13.3英寸超极本','超级本','联想','4299',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('SVP13226SCB 13.3英寸触控超极本','超级本','索尼','7999',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('iPad mini MD531CH/A 7.9英寸平板电脑','平板电脑','苹果','1998',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('iPad Air MD788CH/A 9.7英寸平板电脑 (16G WiFi版)','平板电脑','苹果','3388',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES(' iPad mini ME279CH/A 配备 Retina 显示屏 7.9英寸平板电脑 (16G WiFi版)','平板电脑','苹果','2788',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('IdeaCentre C340 20英寸一体电脑 ','台式机','联想','3499',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('Vostro 3800-R1206 台式电脑','台式机','戴尔','2899',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('iMac ME086CH/A 21.5英寸一体电脑','台式机','苹果','9188',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('AT7-7414LP 台式电脑 (i5-3450四核 4G 500G 2G独显 DVD 键鼠 Linux )','台式机','宏碁','3699',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('Z220SFF F4F06PA工作站','服务器/工作站','惠普','4288',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('PowerEdge T110 II服务器','服务器/工作站','戴尔','5388',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('Mac Pro MD878CH/A 专业级台式电脑','服务器/工作站','苹果','28888',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES(' HMZ-T3W 头戴显示设备','笔记本配件','索尼','6999',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('商务双肩背包','笔记本配件','索尼','99',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('X3250 M4机架式服务器 2583i14','服务器/工作站','IBM','6888',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('玄龙精英版 笔记本散热器','笔记本配件','九州风神','',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES(' HMZ-T3W 头戴显示设备','笔记本配件','索尼','6999',DEFAULT,DEFAULT); INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('商务双肩背包','笔记本配件','索尼','99',DEFAULT,DEFAULT); 语法 table1 {[INNER|CROSS]JOIN|{LEFT|RIGHT}[OUTER]JOIN} table2 ON conditional_expr ... {[INNER|CROSS]JOIN|{LEFT|RIGHT}[OUTER]JOIN} tablen ON conditional_expr JOIN 按照功能大致分为如下三类: INNER JOIN(内连接,或等值连接,):取得两个表中存在连接匹配关系的记录。 LEFT JOIN(左连接):取得左表(table1)完全记录,然后再去匹配(table2),如果匹配不到以NULL的形式返回table2的字段值。 RIGHT JOIN(右连接):与 LEFT JOIN 相反。 关联更新 -- ↓↓把单表更新的table换成了关联在一起的table UPDATE tdb_goods AS g JOIN tdb_goods_brands AS b ON g.brand_name = b.brand_name JOIN tdb_goods_cates AS c ON g.goods_cate = c.cate_name SET g.brand_name = b.brand_id, g.goods_cate = c.cate_id; -- ↓↓由于把原来的品牌名和分类名更换为了id,所以相应的字段名称和类型要有所改变 ALTER TABLE tdb_goods CHANGE brand_name brand_id TINYINT NOT NULL DEFAULT 0, CHANGE goods_cate cate_id TINYINT NOT NULL DEFAULT 0; DESC tdb_goods; 关联查询 -- 内连接 SELECT * FROM tdb_goods AS g JOIN tdb_goods_cates AS c ON g.cate_id = c.cate_id JOIN tdb_goods_brands AS b ON g.brand_id = b.brand_id; -- 左连接 SELECT * FROM tdb_goods AS g LEFT JOIN tdb_goods_cates AS c ON g.cate_id = c.cate_id LEFT JOIN tdb_goods_brands AS b ON g.brand_id = b.brand_id; 关联删除 -- 查找出重复记录; SELECT goods_id,goods_name FROM tdb_goods GROUP BY goods_name HAVING count(goods_name) >= 2; -- 进行删除 DELETE t1 FROM tdb_goods AS t1 JOIN (SELECT goods_id,goods_name FROM tdb_goods GROUP BY goods_name HAVING count(goods_name) >= 2 ) AS t2 ON t1.goods_name = t2.goods_name WHERE t1.goods_id > t2.goods_id; -- 注意,单表的删除在delete后面不用加上表名,但多表一定要加,否则会报语法错误; -- 如何理解这条sql语句? 首先把t1和t2关联一起;然后把t1全删除;也就是说把符合另外一张表关联条件的本表给删掉; Cross join [笛卡尔] 交叉连接,得到的结果是两个表的乘积 select * from tdb_goods,tdb_goods_brands; -- tdb_goods表23条数据,tdb_goods_brands有10条数据,笛卡尔以后就出现23*10条数据; select * from tdb_goods as g join tdb_goods_brands as b; -- join在没有on条件的时候也是笛卡尔乘积; Full join [union] mysql里面没有Full join,只有union;如果要使用union的话,被union的表的结构要一样才能并在一起; -- 先查出1101的评论,再查出1101所关注的人的评论; SELECT * FROM `comment` WHERE user_id = 1101 UNION SELECT * FROM `comment` WHERE user_id IN (select follow_user_id from follow where user_id = 1101); 关于join的外键约束 以往做PHP+MYSQL的web应用时,从未用过外键,但即使如此,外键还是很有必要的,它能是多表之间的关联更严格,能够达到一致性的需求;如果不用外键约束的话,在多表关联的应用场景中,我们插入一条数据,该条数据只要满足语法规范既可插入,但如果使用了外键,该语句还要同时满足当前外键在关联的表中是否存在; 使用外键要满足以下条件: 两张表必须都是InnoDB表,并且它们没有临时表。 外键列和参照列必须具有相似的数据类型. 其中数字的长度及是否有符号位必须相同;而字符的长度则可以不同 外键列和参照列必须创建索引.如果外键列不存在索引的话,mysql将自动创建索引 语法 [CONSTRAINT [symbol]] FOREIGN KEY [index_name] (index_col_name, ...) REFERENCES tbl_name (index_col_name,...) [ON DELETE reference_option] [ON UPDATE reference_option] reference_option: RESTRICT | CASCADE | SET NULL | NO ACTION 如果子表试图创建一个在父表中不存在的外键值,InnoDB会拒绝任何INSERT或UPDATE操作。如果父表试图UPDATE或者DELETE任何子表中存在或匹配的外键值,最终动作取决于外键约束定义中的ON UPDATE和ON DELETE选项。InnoDB支持5种不同的动作,如果没有指定ON DELETE或者ON UPDATE,默认的动作为RESTRICT: CASCADE: 从父表中删除或更新对应的行,同时自动的删除或更新子表中匹配的行。ON DELETE CANSCADE和ON UPDATE CANSCADE都被InnoDB所支持。 SET NULL: 从父表中删除或更新对应的行,同时将子表中的外键列设为空。注意,这些在外键列没有被设为NOT NULL时才有效。ON DELETE SET NULL和ON UPDATE SET NULL都被InnoDB所支持。 NO ACTION: InnoDB拒绝删除或者更新父表。 RESTRICT: 拒绝删除或者更新父表。指定RESTRICT(或者NO ACTION)和忽略ON DELETE或者ON UPDATE选项的效果是一样的。 SET DEFAULT: InnoDB目前不支持。 上文中的父表是指被参照的表; 外键约束使用最多的情况无外乎: 父表更新时子表也更新,父表删除时如果子表有匹配的项,删除失败;(在外键定义中,我们使用ON UPDATE CASCADE ON DELETE RESTRICT) 父表更新时子表也更新,父表删除时子表匹配的项也删除。(使用ON UPDATE CASCADE ON DELETE CASCADE) InnoDB允许你使用ALTER TABLE在一个已经存在的表上增加一个新的外键: ALTER TABLE tbl_name ADD [CONSTRAINT [symbol]] FOREIGN KEY [index_name] (index_col_name, ...) REFERENCES tbl_name (index_col_name,...) [ON DELETE reference_option] [ON UPDATE reference_option] 也支持 ALTER TABLE tbl_name DROP FOREIGN KEY fk_symbol; Example CREATE TABLE `test1` ( `goods_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, `goods_name` varchar(150) NOT NULL, `brand_id` smallint(5) unsigned NOT NULL DEFAULT '0', `goods_price` decimal(15,3) unsigned NOT NULL DEFAULT '0.000', PRIMARY KEY (`goods_id`), KEY `brand_id` (`brand_id`), FOREIGN KEY (`brand_id`) REFERENCES `test2` (`brand_id`) -- test1的brand_id必须和test2一样,包括类型,长度,是否有符号,才能创建外键; -- 创建完之后FOREIGN KEY...这sql就会自动变为:CONSTRAINT `test1_ibfk_1` FOREIGN KEY (`brand_id`) REFERENCES `test2` (`brand_id`) -- 如果不加任何ON DELETE reference_option语句的话,默认就是NO ACTION,也就是说,父表test2更新和删除,只准增加; -- 如果加上ON DELETE CANSCADE和ON UPDATE CANSCADE的话,test2删除和更新都会影响到test1; ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='索引测试test1'; CREATE TABLE `test2` ( `brand_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, `brand_name` varchar(40) NOT NULL, PRIMARY KEY (`brand_id`), ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='索引测试test2'; mysql> insert into test1(goods_name,brand_id) values('i phone 1',6); 1452 - Cannot add or update a child row: a foreign key constraint fails (`test`.`test1`, CONSTRAINT `test1_ibfk_1` FOREIGN KEY (`brand_id`) REFERENCES `test2` (`brand_id`)) -- 没有参照不能插入 mysql> delete from test2 where brand_id=1; 1451 - Cannot delete or update a parent row: a foreign key constraint fails (`test`.`test1`, CONSTRAINT `test1_ibfk_1` FOREIGN KEY (`brand_id`) REFERENCES `test2` (`brand_id`)) -- NO ACTION,凡是test1已经关联上的test2的row都不能被删除;保持数据的一致性;没关联上可以被删除,虽然是no action; 自连接+join 实现一级分类 表的设计是无限极的设计方式,但mysql搞不了递归,只能实现一级; 数据准备 CREATE TABLE tdb_goods_types( type_id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT, type_name VARCHAR(20) NOT NULL, parent_id SMALLINT UNSIGNED NOT NULL DEFAULT 0 )ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='无限极分类表';; INSERT tdb_goods_types(type_name,parent_id) VALUES('家用电器',DEFAULT); INSERT tdb_goods_types(type_name,parent_id) VALUES('电脑、办公',DEFAULT); INSERT tdb_goods_types(type_name,parent_id) VALUES('大家电',1); INSERT tdb_goods_types(type_name,parent_id) VALUES('生活电器',1); INSERT tdb_goods_types(type_name,parent_id) VALUES('平板电视',3); INSERT tdb_goods_types(type_name,parent_id) VALUES('空调',3); INSERT tdb_goods_types(type_name,parent_id) VALUES('电风扇',4); INSERT tdb_goods_types(type_name,parent_id) VALUES('饮水机',4); INSERT tdb_goods_types(type_name,parent_id) VALUES('电脑整机',2); INSERT tdb_goods_types(type_name,parent_id) VALUES('电脑配件',2); INSERT tdb_goods_types(type_name,parent_id) VALUES('笔记本',9); INSERT tdb_goods_types(type_name,parent_id) VALUES('超级本',9); INSERT tdb_goods_types(type_name,parent_id) VALUES('游戏本',9); INSERT tdb_goods_types(type_name,parent_id) VALUES('CPU',10); INSERT tdb_goods_types(type_name,parent_id) VALUES('主机',10); 实现分类 SELECT t1.type_id, t1.type_name AS parent_name, t2.type_name, t2.parent_id FROM `tdb_goods_types` AS t1 JOIN tdb_goods_types AS t2 ON t1.type_id = t2.parent_id; |
|||
java多线程传参数 | 多线程 | ||
向线程中传递数据的三种方法: 一、通过构造函数传递参数 public class MyThread1 extends Thread { private String name; public MyThread1(String name) { this.name = name; } public void run() { System.out.println("hello " + name); } public static void main(String[] args) { Thread thread = new MyThread1("world"); thread.start(); } } 二、通过变量和方法传递数据 public class MyThread2 implements Runnable { private String name; public void setName(String name) { this.name = name; } public void run() { System.out.println("hello " + name); } public static void main(String[] args) { MyThread2 myThread = new MyThread2(); myThread.setName("world"); Thread thread = new Thread(myThread); thread.start(); } } 三、通过回调函数传递数据 class Data { public int value = 0; } class Work { public void process(Data data, Integer numbers) { for (int n : numbers) { data.value += n; } } } public class MyThread3 extends Thread { private Work work; public MyThread3(Work work) { this.work = work; } public void run() { java.util.Random random = new java.util.Random(); Data data = new Data(); int n1 = random.nextInt(1000); int n2 = random.nextInt(2000); int n3 = random.nextInt(3000); work.process(data, n1, n2, n3); // 使用回调函数 System.out.println(String.valueOf(n1) + "+" + String.valueOf(n2) + "+" + String.valueOf(n3) + "=" + data.value); } public static void main(String[] args) { Thread thread = new MyThread3(new Work()); thread.start(); } } |
|||
tomcat内存配置 | tomcat内存配置 | ||
-Xms2014m -Xmx2014m -XX:PermSize=1024m -XX:MaxPermSize=1024m set JAVA_OPTS=-server -XX:PermSize=128M -XX:MaxPermSize=256m -Xms256m -Xmx1024m来解决。 遇到PermGen内存溢出问题(转) 开发的应用程序平时运行时没有问题,当同时使用人数达到10人左右时,过不了多久就报告PermGen内存溢出,狂晕了一段时间,通过在百度上搜索,发现产生此问题的原因是应为装载的class太多造成的。当服务器收到大量http请求时,tomcat需要首先编译jsp文件,这个时候会装载需要的class,又因为PermGen不会自动回收内存就会造成内存溢出。解决方案:一是将需要用到的class文件放置到tomcat下的share/lib和share/classes目录下;二是通过在catalina.bat文件中指定以下代码set JAVA_OPTS=-server -XX:PermSize=128M -XX:MaxPermSize=256m -Xms256m -Xmx1024m来解决。 这里要分配的是允许java使用的最大内存大小,要根据MAS服务器实际配置而定。建议配置如下: 1G内存:JAVA_OPTS='-Xms512m -Xmx512m' 2G内存:JAVA_OPTS='-Xms512m -Xmx1024m' 4G内存:JAVA_OPTS='-Xms512m -Xmx2048m' 用vi打开/opt/tomcat/bin/catalina.sh,在开头加入: JAVA_OPTS='-Xms512m -Xmx512m' 保存退出。 Tomcat默认可以使用的内存为128MB,在较大型的应用项目中,这点内存是不够的,轻微时,会使系统性能急剧下降,严重时,将导致系统无法运行,影响系统的稳定性。当内存不够用时,常见的问题就是报tomcat内存益处错误,从儿导致客户端包500错误的,如下:解决方法主要是加大TOMCAT可利用内存,并在程序当中加大内存使用。因此根据应用的需求,有必要调整JVM使用内存的大小。现在将手工修改tomcat内存的方法及注意事项列出,希望能对新人有所帮助。 tomcat提供了两种安装模式,即免安装(*.zip)和安装(*.exe)方式。针对不同的安装方式下修改tomcat内存大小的方法几注意问题(windows环境): 方式1:当选择安装方式时,可以在安装tomcat的过程进行设置tomcat初始化内存的大小。但是假如说在安装时没有选择,或者应用改变了,需要增加tomcat内存时怎么半呢?此时,我们就要手工修改tomcat的一些文件了: 看了很多网上的资料,都是说修改<CATALINA_HOME>\bin\catalina.bat文件的内容,即在里面增加一行代码: set JAVA_OPTS=-Xms512m -Xmx512m //表示初始化最小可用内存和最大可用内存都是512MB(修改相应值即可) 如在catalina.bat的 rem ----- Execute The Requested Command echo Using CATALINA_BASE: %CATALINA_BASE% echo Using CATALINA_HOME: %CATALINA_HOME% echo Using CATALINA_TMPDIR: %CATALINA_TMPDIR% echo Using JAVA_HOME: %JAVA_HOME% 这一栏改为 rem ----- Execute The Requested Command set JAVA_OPTS=-Xms512m -Xmx512m echo Using CATALINA_BASE: %CATALINA_BASE% echo Using CATALINA_HOME: %CATALINA_HOME% echo Using CATALINA_TMPDIR: %CATALINA_TMPDIR% echo Using JAVA_HOME: %JAVA_HOME% 就可以将JAVA虚拟机分配内存 508.0625MB的! 但是很多人修改后,发现修改并没有起作用,即通过windows的服务启动tomcat时,实际的内存还是默认的,修改的设置并没有起作用;而通过<CATALINA_HOME>\bin\startup.bat 启动却是生效的。这是为什么呢?因为在安装过程中,JVM的初始化参数已经写在注册表中了,由于没有修改注册表中相关参数,所以以windows服务方式启动时,修改的并没有生效。而通过<CATALINA_HOME>\bin\startup.bat 启动直接是通过<CATALINA_HOME>\bin\catalina.bat文件中的配置的。你需要重新加载到系统服务中才生效,或者你手工在注册表中查找修改启动值,加载到服务中的时候参数已经配置好了,自己修改artup.bat不会改变注册表中的参数设置。 解决方法:修改注册表中的参数,加入JVM初始化内存的参数: HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Tomcat Service Manager\Tomcat5\Parameters\JavaOptions 值为 -Dcatalina.home="C:\ApacheGroup\Tomcat 5.0" -Djava.endorsed.dirs="C:\ApacheGroup\Tomcat 5.0\common\endorsed" -Xrs 如加入 -Xms512m -Xmx800m 方式2:针对免安装的用户,也可以通过将tomcat注册为windows的一个服务的方式来实现:‘ 我们可以对service.bat文件做一些其他修改,使tomcat更加能满足我们各种不同需求时的要求 1. 如果让tomcat编译jsp文件,就在PR_CLASSPATH中加入J2SDK的tools.jar 修改前: set PR_CLASSPATH=%CATALINA_HOME%\bin\bootstrap.jar 修改后: set PR_CLASSPATH=%JAVA_HOME%\lib\tools.jar;%CATALINA_HOME%\bin\bootstrap.jar 2.要使用一个特定的JVM,就要修改jvm的参数;要使注册的windows服务的启动方式为自动,增加--Startup Automatic,这个是比较常用的;要用定制的server.xml配置文件并且传递多个参数给StartClass,要修改StartParams的值,各个值之间用分号分隔: 修改前: "%EXECUTABLE%" //IS//%SERVICE_NAME% --Jvm auto --StartClass org.apache.catalina.startup.Bootstrap --StopClass org.apache.catalina.startup.Bootstrap --StartParams start --StopParams stop 修改后: "%EXECUTABLE%" //IS//%SERVICE_NAME% --Jvm "%JAVA_HOME%\jre\bin\server\jvm.dll" --StartClass org.apache.catalina.startup.Bootstrap --StopClass org.apache.catalina.startup.Bootstrap --StartParams "-config;%CUSTOM_SERVERXML_FILE%;-nonaming;start" --StopParams stop --Startup Automatic 3. 指定最大和最小的内存限制,要增加jvm的初始参数 修改前: "%EXECUTABLE%" //US//%SERVICE_NAME% --JvmOptions "-Dcatalina.base=%CATALINA_BASE%;-Dcatalina.home=%CATALINA_HOME%;-Djava.endorsed.dirs=%CATALINA_HOME%\common\endorsed" --StartMode jvm --StopMode jvm 修改后: "%EXECUTABLE%" //US//%SERVICE_NAME% --JvmOptions "-Xms128M;-Xmx256M;-Dcatalina.base=%CATALINA_BASE%;-Dcatalina.home=%CATALINA_HOME%;-Djava.endorsed.dirs=%CATALINA_HOME%\common\endorsed" --StartMode jvm --StopMode jvm 4.有时注册windows服务成功后,但是启动服务时显示“发生服务特定错误: 0.” 就是因为jvm没有指定,修改Jvm auto为Jvm "%JAVA_HOME%\jre\bin\server\jvm.dll"后重新注册windows服务就可以启动了。 |
|||
图片压缩代码 | 图片压缩代码 | ||
package com.yipai.util; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import javax.imageio.ImageIO; import com.sun.image.codec.jpeg.JPEGCodec; import com.sun.image.codec.jpeg.JPEGEncodeParam; import com.sun.image.codec.jpeg.JPEGImageEncoder; public class ImageCompressUtil { /** * 直接指定压缩后的宽高: * (先保存原文件,再压缩、上传) * 壹拍项目中用于二维码压缩 * @param oldFile 要进行压缩的文件全路径 * @param width 压缩后的宽度 * @param height 压缩后的高度 * @param quality 压缩质量 * @param smallIcon 文件名的小小后缀(注意,非文件后缀名称),入压缩文件名是yasuo.jpg,则压缩后文件名是yasuo(+smallIcon).jpg * @return 返回压缩后的文件的全路径 */ public static String zipImageFile(String oldFile, int width, int height, float quality, String smallIcon) { if (oldFile == null) { return null; } String newImage = null; try { /**对服务器上的临时文件进行处理 */ Image srcFile = ImageIO.read(new File(oldFile)); /** 宽,高设定 */ BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); tag.getGraphics().drawImage(srcFile, 0, 0, width, height, null); String filePrex = oldFile.substring(0, oldFile.indexOf('.')); /** 压缩后的文件名 */ newImage = filePrex + smallIcon + oldFile.substring(filePrex.length()); /** 压缩之后临时存放位置 */ FileOutputStream out = new FileOutputStream(newImage); JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(tag); /** 压缩质量 */ jep.setQuality(quality, true); encoder.encode(tag, jep); out.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return newImage; } /** * 保存文件到服务器临时路径(用于文件上传) * @param fileName * @param is * @return 文件全路径 */ public static String writeFile(String fileName, InputStream is) { if (fileName == null || fileName.trim().length() == 0) { return null; } try { /** 首先保存到临时文件 */ FileOutputStream fos = new FileOutputStream(fileName); byte[] readBytes = new byte[512];// 缓冲大小 int readed = 0; while ((readed = is.read(readBytes)) > 0) { fos.write(readBytes, 0, readed); } fos.close(); is.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return fileName; } /** * 等比例压缩算法: * 算法思想:根据压缩基数和压缩比来压缩原图,生产一张图片效果最接近原图的缩略图 * @param srcURL 原图地址 * @param deskURL 缩略图地址 * @param comBase 压缩基数 * @param scale 压缩限制(宽/高)比例 一般用1: * 当scale>=1,缩略图height=comBase,width按原图宽高比例;若scale<1,缩略图width=comBase,height按原图宽高比例 * @throws Exception * @author shenbin * @createTime 2014-12-16 * @lastModifyTime 2014-12-16 */ public static void saveMinPhoto(String srcURL, String deskURL, double comBase, double scale) throws Exception { File srcFile = new java.io.File(srcURL); Image src = ImageIO.read(srcFile); int srcHeight = src.getHeight(null); int srcWidth = src.getWidth(null); int deskHeight = 0;// 缩略图高 int deskWidth = 0;// 缩略图宽 double srcScale = (double) srcHeight / srcWidth; /**缩略图宽高算法*/ if ((double) srcHeight > comBase || (double) srcWidth > comBase) { if (srcScale >= scale || 1 / srcScale > scale) { if (srcScale >= scale) { deskHeight = (int) comBase; deskWidth = srcWidth * deskHeight / srcHeight; } else { deskWidth = (int) comBase; deskHeight = srcHeight * deskWidth / srcWidth; } } else { if ((double) srcHeight > comBase) { deskHeight = (int) comBase; deskWidth = srcWidth * deskHeight / srcHeight; } else { deskWidth = (int) comBase; deskHeight = srcHeight * deskWidth / srcWidth; } } } else { deskHeight = srcHeight; deskWidth = srcWidth; } BufferedImage tag = new BufferedImage(deskWidth, deskHeight, BufferedImage.TYPE_3BYTE_BGR); tag.getGraphics().drawImage(src, 0, 0, deskWidth, deskHeight, null); //绘制缩小后的图 FileOutputStream deskImage = new FileOutputStream(deskURL); //输出到文件流 JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(deskImage); encoder.encode(tag); //近JPEG编码 deskImage.close(); } public static void main(String args[]) throws Exception { ImageCompressUtil.zipImageFile("f:/食尸鬼 - 藿香.jpg", 1280, 1280, 1f, "x2"); ImageCompressUtil.saveMinPhoto("f:/食尸鬼 - 藿香.jpg", "f:/11.jpg", 139, 0.9d); } } |
|||
java 下拉数据异步请求(例子) | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title></title> <#include "/jeecms_sys/head.html"/> <script type="text/javascript"> $(function() { $("#jvForm").validate(); }); </script> </head> <body> <div class="box-positon"> <div class="rpos"><@s.m "global.position"/>: <@s.m "cmsMember.function"/> - <@s.m "global.add"/></div> <form class="ropt"> <input type="submit" value="<@s.m "global.backToList"/>" onclick="this.form.action='v_list.do';" class="return-button"/> </form> <div class="clear"></div> </div> <div class="body-box"> <#assign usernameExist><@s.m "error.usernameExist"/></#assign> <@p.form id="jvForm" action="o_save.do" labelWidth="12"> <#if regionlist?exists> <@p.td colspan="1" width="50" label="业主所在房子" required="true"> <#if is_super?exists&&is_super==1> <select name="community_id" id="community_id" onchange="building()" > <option value=''>选择小区</option> <#if communityList?exists> <#list communityList as community> <option value='${(community.id)!}'>${community.community_name!'选择小区'}</option> </#list> <#else> <option value=''>暂无小区</option> </#if> <select> <#else> <select name="city_id" id="city_id" onchange="community()" > <option value=''>选择城市</option> <#list regionlist as regions> <option value='${(regions.id)!}'>${(regions.region_name)!}</option> </#list> <select> <select name="community_id" id="community_id" onchange="building()" > <option value=''>选择小区</option> <select> </#if> <select name="building_id" id="building_id" onchange="room()" > <option value=''>选择楼号</option> <select> <select name="room_id" id="room_id" required="true" onchange="checkYezhu()" > <option value=''>选择房号</option> <select> </@p.td> </#if> <@p.td width="50" colspan="1" label="用户身份">业主</@p.td> <@p.tr/> <@p.text width="50" colspan="1" label="cmsUser.username" name="username" required="true" maxlength="100" vld="{required:true,username:true,remote:'v_check_username.do',messages:{remote:'${usernameExist}'}}"/> <@p.text width="50" colspan="1" label="cmsUser.email" name="email" size="30" class="email" vld="{email:true,remote:'v_check_email.do',messages:{remote:'该邮箱已注册过'}}"/><@p.tr/> <@p.text width="50" colspan="1" label="手机" name="user_mobile" required="true" maxlength="50" onblur="checkmobile(this)"/> <@p.password width="50" colspan="1" label="cmsUser.password" id="password" name="password" maxlength="100" required="true" class="required"/><@p.tr/> <@p.password width="50" colspan="1" label="cmsUser.pwdAgain" required="true" equalTo="#password"/> <@p.select colspan="2" label="cmsUser.group" name="groupId" list=groupList listKey="id" listValue="name" required="true"/><@p.tr/> <@p.text width="50" colspan="1" label="cmsUser.realname" name="realname" maxlength="100"/> <@p.text width="50" colspan="1" label="身份证" name="id_number" maxlength="100"/><@p.tr/> <@p.radio width="50" colspan="1" label="cmsUser.gender" name="gender" list={"true":"cmsUser.male","false":"cmsUser.female","":"cmsUser.secrecy"}/> <@p.text width="50" colspan="1" label="cmsUser.birthday" name="birthday" onclick="WdatePicker({dateFmt:'yyyy-MM-dd'})" class="Wdate"/><@p.tr/> <!-- <@p.text width="50" colspan="1" label="cmsUser.comefrom" name="comefrom" maxlength="150"/><@p.tr/> --> <@p.text width="50" colspan="1" label="cmsUser.qq" name="qq" maxlength="100"/> <!-- <@p.text width="50" colspan="1" label="cmsUser.msn" name="msn" maxlength="100"/><@p.tr/> --> <@p.text width="50" colspan="1" label="cmsUser.phone" name="phone" maxlength="50"/><@p.tr/> <!-- <@p.textarea colspan="2" label="cmsUser.intro" name="intro" maxlength="255" cols="70" rows="5"/><@p.tr/> --> <@p.td colspan="2"><@p.submit code="global.submit"/> <@p.reset code="global.reset"/></@p.td> </@p.form> </div> <script> //获取某城市下的小区列表 function community(){ var city_id = $('#city_id option:selected').val(); //alert(city_id); $.ajax({ url:"../community/listByCity.do", data:{city_id:city_id}, type:"POST", dataType:"json", timeout:5000, success:function(json){ var select_option; //console.log(json); // console.log(json.Data.cityList); var options_str = ""; for ( var int = 0; int < json.communityList.length; int++) { options_str += "<option value=\"" + json.communityList[int].community_id + "\" >" + json.communityList[int].community_name + "</option>"; } $("#community_id").empty(); $("#community_id").append("<option value=''>选择小区</option>"); $("#building_id").empty(); $("#building_id").append("<option value=''>选择楼号</option>"); $("#room_id").empty(); $("#room_id").append("<option value=''>选择房号</option>"); $("#community_id").append(options_str); return; }, }) } //获取小区下的楼号列表 function building(){ var community_id = $('#community_id option:selected').val(); //alert(community_id); $.ajax({ url:"../building/buildingList.do", data:{community_id:community_id}, type:"POST", dataType:"json", timeout:5000, success:function(json){ var select_option; var options_str = "";//alert(json.buildingList); for ( var int = 0; int < json.buildingList.length; int++) { options_str += "<option value=\"" + json.buildingList[int].building_id + "\" >" + json.buildingList[int].building_name + "</option>"; } $("#building_id").empty(); $("#building_id").append("<option value=''>选择楼号</option>"); $("#room_id").empty(); $("#room_id").append("<option value=''>选择房号</option>"); $("#building_id").append(options_str); return; }, }) } //获取楼号下的房子列表 function room(){ var building_id = $('#building_id option:selected').val(); //alert(building_id); $.ajax({ url:"../room/roomList.do", data:{building_id:building_id}, type:"POST", dataType:"json", timeout:5000, success:function(json){ var select_option; var options_str = ""; for ( var int = 0; int < json.roomList.length; int++) { options_str += "<option value=\"" + json.roomList[int].room_id + "\" >" + json.roomList[int].room_name + "</option>"; } $("#room_id").empty();//清空原有数据 $("#room_id").append("<option value=''>选择房号</option>");//恢复第一条描述 $("#room_id").append(options_str); return; }, }) } //检查所选择的房子是否已经有业主 function checkYezhu(){ var community_id = $("#community_id").val(); var building_id = $("#building_id").val(); var room_id = $('#room_id option:selected').val(); $.ajax({ url:"../member/v_checkYezhu.do?room_id="+room_id+"&building_id="+building_id+"&community_id="+community_id+"&ctype=1", //data:{room_id:room_id}, type:"POST", dataType:"json", timeout:5000, success:function(json){ if(json.message=='true') alert("该房子已有业主!"); else if(json.message=='cuowu') alert("抱歉,异步检查所选房子是否已有业主出错"); else return; }, }) } </script> <script type="text/javascript"> function checkmobile(This){ var mobile = $(This).val(); //var member_id = $(This).siblings("input[name=xiaxian_id]").val(); //alert(mobile); $.ajax({ url:"../member/v_check_user_mobile.do?ctype=1&user_mobile="+mobile, type:"POST", dataType:"json", success:function(result){ if(result.message=="0"){ } if(result.message=="1"){ alert("该手机已注册"); } if(result.message=="2"){ alert("检查手机号出错"); } }, error:function(){ alert("抱歉,检查手机号出错!"); } }); } </script> </body> </html> |
|||
采用HttpClient发送HTTP请求 | |||
采用HttpClient发送HTTP请求 2015/9/10 14:09:11 HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在JDK的URLConnection包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK库本身提供的功能还不够丰富和灵活。HttpClient 是 Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。 项目地址:http://hc.apache.org/index.html 一、功能介绍 实现了所有 HTTP 的方法(GET,POST,PUT,HEAD 等) 支持HTTPS协议 支持自动转向 插件式的自定义认证方案 支持代理服务器 自定义Cookie 直接获取服务器发送的response code和 headers 在http1.0和http1.1中利用KeepAlive保持持久连接 设置连接超时的能力 二、使用方法 创建HttpClient对象。 创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。 如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HetpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。 调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。 释放连接。无论执行方法是否成功,都必须释放连接。 三、代码实现 发送 get请求代码 /** * 发送 get请求 */ public void get() { CloseableHttpClient httpclient = HttpClients.createDefault(); try { // 创建httpget. HttpGet httpget = new HttpGet("http://www.baidu.com/"); System.out.println("executing request " + httpget.getURI()); // 执行get请求. CloseableHttpResponse response = httpclient.execute(httpget); try { // 获取响应实体 HttpEntity entity = response.getEntity(); System.out.println("--------------------------------------"); // 打印响应状态 System.out.println(response.getStatusLine()); if (entity != null) { // 打印响应内容长度 System.out.println("Response content length: " + entity.getContentLength()); // 打印响应内容 System.out.println("Response content: " + EntityUtils.toString(entity)); } System.out.println("------------------------------------"); } finally { response.close(); } } catch (Exception e) { e.printStackTrace(); } finally { // 关闭连接,释放资源 try { httpclient.close(); } catch (IOException e) { e.printStackTrace(); } } } Post方式代码 /** * post方式 */ public void postForm() { // 创建默认的httpClient实例. CloseableHttpClient httpclient = HttpClients.createDefault(); // 创建httppost HttpPost httppost = new HttpPost("http://localhost:8080/Demo/test.action"); // 创建参数队列 List<NameValuePair> formparams = new ArrayList<NameValuePair>(); formparams.add(new BasicNameValuePair("username", "tt")); formparams.add(new BasicNameValuePair("password", "123456")); UrlEncodedFormEntity uefEntity; try { uefEntity = new UrlEncodedFormEntity(formparams, "UTF-8"); httppost.setEntity(uefEntity); System.out.println("executing request " + httppost.getURI()); CloseableHttpResponse response = httpclient.execute(httppost); try { HttpEntity entity = response.getEntity(); if (entity != null) { System.out.println("--------------------------------------"); System.out.println("Response content: " + EntityUtils.toString(entity, "UTF-8")); System.out.println("--------------------------------------"); } } finally { response.close(); } } catch (Exception e) { e.printStackTrace(); } finally { // 关闭连接,释放资源 try { httpclient.close(); } catch (IOException e) { e.printStackTrace(); } } } 上传文件代码 /** * 上传文件 */ public void upload() { CloseableHttpClient httpclient = HttpClients.createDefault(); try { HttpPost httppost = new HttpPost("http://localhost:8080/Demo/upFile.action"); FileBody bin = new FileBody(new File("F:\\image\\text.jpg")); StringBody comment = new StringBody("A binary file of some kind", ContentType.TEXT_PLAIN); HttpEntity reqEntity = MultipartEntityBuilder.create().addPart("bin", bin).addPart("comment", comment).build(); httppost.setEntity(reqEntity); System.out.println("executing request " + httppost.getRequestLine()); CloseableHttpResponse response = httpclient.execute(httppost); try { System.out.println("----------------------------------------"); System.out.println(response.getStatusLine()); HttpEntity resEntity = response.getEntity(); if (resEntity != null) { System.out.println("Response content length: " + resEntity.getContentLength()); } EntityUtils.consume(resEntity); } finally { response.close(); } } catch (Exception e) { e.printStackTrace(); } finally { try { httpclient.close(); } catch (IOException e) { e.printStackTrace(); } } } |
|||
springMVC定时器配置 | springmvc定时器配置 | ||
<bean id="headController" class="com.fh.controller.system.head.HeadController"></bean> <!-- 每隔12小时 执行一次 --> <bean id="ZntaskTopSaleJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="headController"></property> <property name="targetMethod" value="zntask"></property> </bean> <bean id="zntaskTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail"> <ref bean="ZntaskTopSaleJobDetail"/> </property> <property name="cronExpression"> <value>0 43 14 * * ?</value> </property> </bean> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="zntaskTrigger"/> </list> </property> </bean> 时间的配置如下: <value>0 26 16 * * ?value> 时间大小由小到大排列,从秒开始,顺序为 秒,分,时,天,月,年 *为任意 ?为无限制。由此上面所配置的内容就是,在每天的16点26分启动znrwdb方法 具体时间设定可参考 "0/10 * * * * ?" 每10秒触发 "0 0 12 * * ?" 每天中午12点触发 "0 15 10 ? * *" 每天上午10:15触发 "0 15 10 * * ?" 每天上午10:15触发 "0 15 10 * * ? *" 每天上午10:15触发 "0 15 10 * * ? 2005" 2005年的每天上午10:15触发 "0 * 14 * * ?" 在每天下午2点到下午2:59期间的每1分钟触发 "0 0/5 14 * * ?" 在每天下午2点到下午2:55期间的每5分钟触发 "0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发 "0 0-5 14 * * ?" 在每天下午2点到下午2:05期间的每1分钟触发 "0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发 "0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发 "0 15 10 15 * ?" 每月15日上午10:15触发 "0 15 10 L * ?" 每月最后一日的上午10:15触发 "0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发 "0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发 "0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发 每隔5秒执行一次:*/5 * * * * ? 每隔1分钟执行一次:0 */1 * * * ? 每天23点执行一次:0 0 23 * * ? 每天凌晨1点执行一次:0 0 1 * * ? 每月1号凌晨1点执行一次:0 0 1 1 * ? 每月最后一天23点执行一次:0 0 23 L * ? 每周星期天凌晨1点实行一次:0 0 1 ? * L 在26分、29分、33分执行一次:0 26,29,33 * * * ? 每天的0点、13点、18点、21点都执行一次:0 0 0,13,18,21 * * ? 引入两个包: jta.jar (8.6 KB) quartz-all-1.6.0.jar (426.4 KB) |
|||
Ajax Jquery请求方式 | ajaxjquery请求方式 | ||
function listSearchSource(){ var url="/jfysc/listfindcar.jspx"; var formData = $("#fmNames").serialize(); $.ajax({ type : "POST", url : url, processData : true, data : formData, success : function(responseData) { if(responseData=="false"){ alert("抱歉,哦!") // window.location.href="/jfysc/jfsell/asksell.jspx"; }else{ // responseData=encodeURI(encodeURI(responseData)); window.location.href="/jfysc/show/toshowlist.jspx?name="+responseData+"&flag=search"; } } }); } $.ajax({ url:URL, type:'get', dataType:'html', data:josn, success:function(result){ $("#J_Jpls").html(result); }, error:function(){ } }); var loginname = $("#loginname").val(); var password = $("#password").val(); var code = "qq313596790fh"+loginname+",fh,"+password+"QQ978336446fh"+",fh,"+$("#code").val(); $.ajax({ type: "POST", url: 'login_login', data: {KEYDATA:code,tm:new Date().getTime()}, dataType:'json', cache: false, success: function(data){ if("success" == data.result){ saveCookie(); window.location.href="main/index"; }else if("usererror" == data.result){ $("#loginname").tips({ side : 1, msg : "用户名或密码有误", bg : '#FF5080', time : 15 }); $("#loginname").focus(); }else if("codeerror" == data.result){ $("#code").tips({ side : 1, msg : "验证码输入有误", bg : '#FF5080', time : 15 }); $("#code").focus(); }else{ $("#loginname").tips({ side : 1, msg : "缺少参数", bg : '#FF5080', time : 15 }); $("#loginname").focus(); } } }); } } |
|||
服务器内存配置 | tomcat | ||
-Xms512m -Xmx512m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=512m Myeclipse->preferences->myeclipse->servers->tomcat->tomcat×.×->JDK面板中的 Optional Java VM arguments中添加:-Xmx1024M -Xms512M -XX:MaxPermSize=256m |
|||
处理同步登录问题 | mvc | ||
1楼的方法是对的但实现起来会有很多问题,踢掉前一次登录反而最简单,如下代码: 1、添加两个监听器类: public class MySessionAttributeListener implements HttpSessionAttributeListener { public static Map<String, HttpSession> sessionMap=new ConcurrentHashMap<String, HttpSession>(); @Override public void attributeAdded(HttpSessionBindingEvent arg0) { String name=(String)arg0.getValue(); if("name".equals(name)){//name属性保存用户登录信息,name=为唯一信息如用户名 if(sessionMap.containsKey(name)){//踢掉前一次登录 HttpSession session=sessionMap.remove(name); session.invalidate(); } sessionMap.put(name, arg0.getSession()); } } @Override public void attributeRemoved(HttpSessionBindingEvent arg0) {} @Override public void attributeReplaced(HttpSessionBindingEvent arg0) {} } public class MySessionListener implements HttpSessionListener { @Override public void sessionCreated(HttpSessionEvent arg0) {} @Override public void sessionDestroyed(HttpSessionEvent arg0) { String name=(String)arg0.getSession().getAttribute("name"); if(name!=null && name.length()>0){//session失效时候移除记录 if(MySessionAttributeListener.sessionMap.containsKey(name)) MySessionAttributeListener.sessionMap.remove(name); } //else System.out.println("注销用户:未获取到登录用户属性"); } } 2、web.xml加入监听 <listener> <listener-class>你的包名.MySessionListener</listener-class> </listener> <listener> <listener-class>你的包名.MySessionAttributeListener</listener-class> </listener> 3、jsp或servlet中保存登录信息如: request.getSession().setAttribute("name", "登录信息"); 对于用户登录不能同时登录的做法,我的想法是: 一、策略 a、后面的登录踢掉前面的登录 b、给前面的登录提示或者将前面的登录重定向到登出页面 二、做法 a、在ServletContext中增加一个HashMap对象,记录登录的用户名及其对应的session对象,其中key为用户名,value为session对象,这样可以利用HashMap的特性快速找到key,尤其是用户量很大的情况下。 b、当一个用户输入正确的用户名和密码后,到a中生成的HashMap中查找该用户名,如果没有,则说明这个用户名还没有登录,将用户名及对应的session添加到HashMap对象中;如果有,则到c。 c、取得HashMap中key中对应的session对象,如果session对象不为空,则使用invalidate()方法清理该session对象,同时将key的value置为现在session对象。 d、增加一个session监听器,监听session摧毁时要执行方法,取得当前session对应的用户名在HashMap中session,比较两个session是否相同,如果是,则清除HashMap中的key。(如果不需要统计在线人数,d步可以没有)。 |
|||
支付相关接口 | |||
package com.jeecms.cms.action.front; import static com.jeecms.core.manager.AuthenticationMng.AUTH_KEY; import java.io.IOException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.text.DecimalFormat; import java.text.ParseException; import java.text.SimpleDateFormat; 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.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.lang.StringUtils; import org.dom4j.DocumentException; import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import sun.misc.BASE64Decoder; import beartool.MD5; import com.alipay.config.AlipayConfig; import com.alipay.util.AlipayCore; import com.alipay.util.AlipayNotify; import com.alipay.util.AlipaySubmit; import com.jeecms.cms.entity.main.AgentSet; import com.jeecms.cms.entity.main.CmsSite; import com.jeecms.cms.entity.main.CmsUser; import com.jeecms.cms.entity.main.JcOrg; import com.jeecms.cms.entity.main.Order; import com.jeecms.cms.entity.main.OrderExt; import com.jeecms.cms.entity.main.Product; import com.jeecms.cms.entity.main.ProductCategory; import com.jeecms.cms.manager.main.AgentSetMng; import com.jeecms.cms.manager.main.CmsLogMng; import com.jeecms.cms.manager.main.CmsUserMng; import com.jeecms.cms.manager.main.JcOrgMng; import com.jeecms.cms.manager.main.OrderExtMng; import com.jeecms.cms.manager.main.OrderMng; import com.jeecms.cms.manager.main.ProductCategoryMng; import com.jeecms.cms.manager.main.ProductMng; import com.jeecms.cms.web.CmsUtils; import com.jeecms.cms.web.FrontUtils; import com.jeecms.cms.web.WebErrors; import com.jeecms.common.util.AplipayInfoRW; import com.jeecms.common.util.MD5Utils; import com.jeecms.common.util.RandomUtil; import com.jeecms.common.util.ReadMessagerUtils; import com.jeecms.common.util.RequestUtil; import com.jeecms.common.util.SetMailInfoUtils; import com.jeecms.common.util.ipspay.IpsSubmit; import com.jeecms.common.web.RequestUtils; import com.jeecms.common.web.ResponseUtils; import com.jeecms.common.web.session.SessionProvider; import com.jeecms.core.entity.Authentication; import com.jeecms.core.entity.UnifiedUser; import com.jeecms.core.manager.AuthenticationMng; import com.jeecms.core.manager.UnifiedUserMng; import com.jeecms.mail.MailSenderInfo; import com.jeecms.mail.SimpleMailSender; import com.octo.captcha.service.CaptchaServiceException; import com.octo.captcha.service.image.ImageCaptchaService; import com.yeepay.Configuration; import com.yeepay.PaymentForOnlineService; @Controller public class OrderAct { private static final Logger log = LoggerFactory.getLogger(OrderAct.class); public static final String PLACE_ORDER = "tpl.placeOrder"; public static final String ORDER_INFO = "tpl.orderInfo"; public static final String SEARCH_ORDER = "tpl.searchOrder"; public static final String CONFIRM_ORDER = "tpl.confirmOrder"; public static final String DOSELF_ORDER = "tpl.doself"; public static final String DOSELF_RESULT = "tpl.doselfResult"; public static final String ALIPAY_SUBMIT = "tpl.alipaySubmit"; public static final String YEEPAY_SUBMIT = "tpl.yeepaySubmit"; public static final String CHINA_SUBMIT = "tpl.chinaBankSubmit"; public static final String TRANSACTION_RESULT = "tpl.paySucessReturn"; public static final String SAVECLOUD_SUBMIT = "tpl.alipaySaveCloudSubmit"; //edit by bin 2015.2.27 public static String orderCodeTemp="5fd"; /** * 下单(进入产品详情) * * @param id * @param request * @param model * @return */ @RequestMapping("/order/v_place.jspx") public String getProduct(Integer id, HttpServletRequest request, ModelMap model) { StringBuffer p = request.getRequestURL(); int endp = p.length() - "order/v_place.jspx".length(); String path = p.toString().substring(0, endp); // System.out.println(new Date() + "--当前请求域名为:" + path); List<JcOrg> jcOrgs = orgMng.getJcOrgList(); if (null != jcOrgs && jcOrgs.size() > 0) { for (int i = 0; i < jcOrgs.size(); i++) { if (path.equals(jcOrgs.get(i).getOrg())) { if (null != jcOrgs.get(i).getIsDisplay() && jcOrgs.get(i).getIsDisplay() == 1) { String msg = "爱卡商城提醒您:我们不刷信誉不招兼职 请勿将卡密交给其他人 谨防被骗"; model.addAttribute("msg", msg); } } } } Product product = productMng.findById(id); if (null != product && null != product.getCategoryCode()) { ProductCategory category = categoryMng .getProductCategoryBycategoryCode(product.getCategoryCode()); model.addAttribute("category", category); } model.addAttribute("product", product); CmsSite site = CmsUtils.getSite(request); FrontUtils.frontData(request, model, site); FrontUtils.frontPageData(request, model); return FrontUtils.getTplPath(request, site.getSolutionPath(), "order", PLACE_ORDER); } /** * 订单查询 * * @param captcha * @param orderCode * @param state * @param request * @param model * @return */ @RequestMapping("/order/v_search.jspx") public String getOrder(String captcha, String orderCode, String state, HttpServletRequest request, ModelMap model) { CmsSite site = CmsUtils.getSite(request); FrontUtils.frontData(request, model, site); FrontUtils.frontPageData(request, model); return FrontUtils.getTplPath(request, site.getSolutionPath(), "order", PLACE_ORDER); } /** * 订单查询输入 * * @param id * @param request * @param model * @return */ @RequestMapping("/order/v_searchinput.jspx") public String getOrderInput(Integer id, HttpServletRequest request, ModelMap model) { CmsSite site = CmsUtils.getSite(request); FrontUtils.frontData(request, model, site); FrontUtils.frontPageData(request, model); // // StringBuffer p = request.getRequestURL(); // int endp = p.length()-"order/v_searchinput.jspx".length(); // String p2 = p.toString().substring(1, endp); // System.out.println(p2); // System.out.println(p); return FrontUtils.getTplPath(request, site.getSolutionPath(), "order", SEARCH_ORDER); } /** * 自助服务输入 * * @param id * @param request * @param model * @return */ @RequestMapping("/order/v_doselfinput.jspx") public String doSelfInput(Integer id, HttpServletRequest request, ModelMap model) { CmsSite site = CmsUtils.getSite(request); FrontUtils.frontData(request, model, site); FrontUtils.frontPageData(request, model); return FrontUtils.getTplPath(request, site.getSolutionPath(), "order", DOSELF_ORDER); } /** * 自助服务结果 * * @param id * @param request * @param model * @return */ @RequestMapping("/order/v_doselfresult.jspx") public String doSelfResult(Integer id, HttpServletRequest request, ModelMap model) { CmsSite site = CmsUtils.getSite(request); FrontUtils.frontData(request, model, site); FrontUtils.frontPageData(request, model); return FrontUtils.getTplPath(request, site.getSolutionPath(), "order", DOSELF_RESULT); } /** * 下单 * * @param productId * @param orderCodeOld * @param productCode * @param productCount * @param flag * @param captcha * @param response * @param request * @param model * @return */ @SuppressWarnings("unused") @RequestMapping(value = "/order/v_order.jspx", method = RequestMethod.POST) public String addOrder(Integer productId, String orderCodeOld, String productCode, Integer productCount, String flag, String captcha, HttpServletResponse response, HttpServletRequest request, ModelMap model) { if (null != flag) { WebErrors errors1 = validateCaptcha1(captcha, request, response); if (errors1.hasErrors()) { return FrontUtils.showError(request, response, model, errors1); } } StringBuffer p = request.getRequestURL(); int endp = p.length() - "order/v_order.jspx".length(); String path = p.toString().substring(0, endp); // System.out.println(new Date() + "--当前请求域名为:" + path); List<JcOrg> jcOrgs = orgMng.getJcOrgList(); if (null != jcOrgs && jcOrgs.size() > 0) { for (int i = 0; i < jcOrgs.size(); i++) { if (path.equals(jcOrgs.get(i).getOrg())) { if (null != jcOrgs.get(i).getIsDisplay() && jcOrgs.get(i).getIsDisplay() == 1) { String msg = "爱卡商城提醒您:我们不刷信誉不招兼职 请勿将卡密交给其他人 谨防被骗"; model.addAttribute("msg", msg); } } } } String receiverEmail = RequestUtils.getQueryParam(request, "receiverEmail"); // if(null!=receiverEmail&&!"".equals(receiverEmail)) String receiverNickName = RequestUtils.getQueryParam(request, "receiverNickName"); String ip = RequestUtils.getIpAddr(request); Product product = null; if (null == orderCodeOld) {// 是否下过单(用于继续交易和重新下单的区别) product = productMng.findById(productId); String searchKey = RequestUtils.getQueryParam(request, "searchKey"); String authId = (String) session.getAttribute(request, AUTH_KEY); WebErrors errors = validateSubmit(receiverEmail, searchKey, request, response); if (errors.hasErrors()) { return FrontUtils.showError(request, response, model, errors); } // SimpleDateFormat dateFormat = new // SimpleDateFormat("yyyyMMddhhmmss"); // dateFormat.format(new java.util.Date()); // 下单日期 // java.sql.Timestamp date=new java.sql.Timestamp(new // java.util.Date().getTime()); java.sql.Date date = new java.sql.Date( new java.util.Date().getTime()); // 订单号生成 // int r1 = (int) (Math.random() * (10));// 产生3个0-9的随机数 // int r2 = (int) (Math.random() * (10)); // int r3 = (int) (Math.random() * (10)); String r1 = RandomUtil.getCharAndNumr(4);// 随机产生四个数 // long now = System.currentTimeMillis();// 一个13位的时间戳 String r2 = RandomUtil.getCharAndNumr(4); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");// 十四位时间 String now = dateFormat.format(new java.util.Date()); String orderCode = String.valueOf(r1) + String.valueOf(now) + String.valueOf(r2);// 订单号 Order order = new Order(); OrderExt ext = new OrderExt(); // 支付方式的值 String bank = request.getParameter("bank"); order.setChargeKey(bank); if (authId != null) {// 是否是注册用户 // 存在认证ID Authentication auth = authMng.retrieve(authId); CmsUser user = cmsUserMng.findById(auth.getUid()); // 存在认证信息,且未过期 if (auth != null) { order.setUserId(user.getId()); order.setUserName(user.getUsername()); ext.setPrice(product.getVipPrice()); } else { order.setUserId(-1); order.setUserName("普通客户"); ext.setPrice(product.getSalePrice()); } } else { order.setUserId(-1); order.setUserName("普通客户"); ext.setPrice(product.getSalePrice()); } order.setSum(ext.getPrice() * productCount); if (ext.getPrice() < product.getPurchasePrice()) {// 保证不亏损 ext.setPrice(product.getPurchasePrice()); order.setSum(product.getPurchasePrice() * productCount); log.info("提交订单时的单价大于进价,以进价为主", 0); } else if (order.getSum() < product.getPurchasePrice() * productCount) { order.setSum(product.getPurchasePrice() * productCount); } order.setIp(ip); order.setOrderCode(orderCode); order.setOrdeDate(date); order.setReceiverEmail(receiverEmail); order.setReceiverNickName(receiverNickName); if (null == order.getReceiverNickName()) { order.setReceiverNickName(order.getOrderCode()); } order.setSearchKey(searchKey); order.setSendState(0); order.setChargeType(0); order.setStatus(0); Order temp = orderMng.save(order); ext.setOrderCode(orderCode); ext.setCategoryCode(product.getCategoryCode()); ext.setProductCount(productCount); ext.setProductName(product.getProductName()); ext.setOrderId(order.getOrderId()); ext.setProductCode(product.getProductCode()); if (null != temp) {// 是否下单成功并保存日志 ext.setOrderId(temp.getOrderId()); OrderExt ext2 = extMng.save(ext); temp.setExt(ext2); log.info("save Order id={}", temp.getOrderId()); if (null != ext2) { log.info("save OrderExt id={}", ext2.getId()); } else { Order temp2 = orderMng.deleteById(temp.getOrderId()); log.info("delete Order id={}", temp2.getOrderId()); } cmsLogMng.orderLogSave(request, temp.getOrderCode(), "order.log", "下订单成功:orderCode=" + temp.getOrderCode()); } else { cmsLogMng.orderLogSave(request, null, "order.log", "下订单失败,产品编号=" + productCode); } model.addAttribute("order", temp); // if(isDelegate){ // String result = "orderCodeOld="+temp.getOrderCode(); // JSONObject json=new JSONObject(); // json.put("result", result); // ResponseUtils.renderJson(response, json.toString()); // } } else { product = productMng.findByProductCode(productCode); Order orderExit = orderMng.getOrderByCode(orderCodeOld); if (null != orderExit) { OrderExt ext = extMng.getOrderExtListByOrderId( orderExit.getOrderId()).get(0); orderExit.setExt(ext); model.addAttribute("order", orderExit); // if(isDelegate){ // String result = "orderCodeOld="+orderCodeOld; // JSONObject json=new JSONObject(); // json.put("result", result); // ResponseUtils.renderJson(response, json.toString()); // } } } String dPay = request.getParameter("dPay"); model.addAttribute("dPay", dPay); // List<CmsDictionary> banks = dictionaryMng.getList(); model.addAttribute("product", product); // model.addAttribute("banks", banks); CmsSite site = CmsUtils.getSite(request); FrontUtils.frontData(request, model, site); FrontUtils.frontPageData(request, model); return FrontUtils.getTplPath(request, site.getSolutionPath(), "order", CONFIRM_ORDER); } /** * 邮箱和密码验证 * * @param email * @param password * @param request * @param response * @return */ private WebErrors validateSubmit(String email, String password, HttpServletRequest request, HttpServletResponse response) { WebErrors errors = WebErrors.create(request); if (errors.ifOutOfLength(password, "password", 4, 16)) { return errors; } if (errors.ifNotEmail(email, "email", 100)) { return errors; } return errors; } /** * 代付(下单) * * @param productId * @param orderCodeOld * @param productCode * @param productCount * @param flag * @param captcha * @param response * @param request * @param model * @return */ @SuppressWarnings("unused") @RequestMapping(value = "/order/v_order_d_p.jspx", method = RequestMethod.GET) public String addOrderDPay(Integer productId, String orderCodeOld, String productCode, Integer productCount, String flag, String captcha, HttpServletResponse response, HttpServletRequest request, ModelMap model) { StringBuffer p = request.getRequestURL(); int endp = p.length() - "order/v_order_d_p.jspx".length(); String path = p.toString().substring(0, endp); // System.out.println(new Date() + "--当前请求域名为:" + path); String dPay = request.getParameter("dPay"); model.addAttribute("dPay", dPay); // 支付方式的值 String bank = request.getParameter("bank"); List<JcOrg> jcOrgs = orgMng.getJcOrgList(); if (null != jcOrgs && jcOrgs.size() > 0) { for (int i = 0; i < jcOrgs.size(); i++) { if (path.equals(jcOrgs.get(i).getOrg())) { if (null != jcOrgs.get(i).getIsDisplay() && jcOrgs.get(i).getIsDisplay() == 1) { String msg = "爱卡商城提醒您:我们不刷信誉不招兼职 请勿将卡密交给其他人 谨防被骗"; model.addAttribute("msg", msg); } } } } String receiverEmail = RequestUtils.getQueryParam(request, "receiverEmail"); String receiverNickName = RequestUtils.getQueryParam(request, "receiverNickName"); // if (null == flag) { // WebErrors errors = validateCaptcha(captcha, receiverEmail, request, // response); // if (errors.hasErrors()) { // return FrontUtils.showError(request, response, model, errors); // } // } String ip = RequestUtils.getIpAddr(request); Product product = null; if (null == orderCodeOld) { product = productMng.findById(productId); String searchKey = RequestUtils.getQueryParam(request, "searchKey"); String authId = (String) session.getAttribute(request, AUTH_KEY); WebErrors errors = validateSubmit(receiverEmail, searchKey, request, response); if (errors.hasErrors()) { return FrontUtils.showError(request, response, model, errors); } // SimpleDateFormat dateFormat = new // SimpleDateFormat("yyyyMMddhhmmss"); // dateFormat.format(new java.util.Date()); // 下单日期 // java.sql.Timestamp date=new java.sql.Timestamp(new // java.util.Date().getTime()); java.sql.Date date = new java.sql.Date( new java.util.Date().getTime()); // 订单号生成 // int r1 = (int) (Math.random() * (10));// 产生3个0-9的随机数 // int r2 = (int) (Math.random() * (10)); // int r3 = (int) (Math.random() * (10)); String r1 = RandomUtil.getCharAndNumr(4);// 产生一个四位数 // long now = System.currentTimeMillis();// 一个13位的时间戳 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddhhmmss");// 一个14位时间 String now = dateFormat.format(new java.util.Date()); String orderCode = "w" + String.valueOf(r1) + String.valueOf(now);// 订单号 Order order = new Order(); OrderExt ext = new OrderExt(); order.setChargeKey(bank); if (authId != null) { // 存在认证ID Authentication auth = authMng.retrieve(authId); CmsUser user = cmsUserMng.findById(auth.getUid()); // 存在认证信息,且未过期 if (auth != null) { order.setUserId(user.getId()); order.setUserName(user.getUsername()); ext.setPrice(product.getVipPrice()); } else { order.setUserId(-1); order.setUserName("普通客户"); ext.setPrice(product.getSalePrice()); } } else { order.setUserId(-1); order.setUserName("普通客户"); ext.setPrice(product.getSalePrice()); } order.setSum(ext.getPrice() * productCount); if (ext.getPrice() < product.getPurchasePrice()) { ext.setPrice(product.getPurchasePrice()); order.setSum(product.getPurchasePrice() * productCount); log.info("提交订单时的单价大于进价,以进价为主", 0); } else if (order.getSum() < product.getPurchasePrice() * productCount) { order.setSum(product.getPurchasePrice() * productCount); } order.setIp(ip); order.setOrderCode(orderCode); order.setOrdeDate(date); order.setReceiverEmail(receiverEmail); order.setReceiverNickName(receiverNickName); if (null == order.getReceiverNickName()) { order.setReceiverNickName(order.getOrderCode()); } order.setSearchKey(searchKey); order.setSendState(0); order.setChargeType(0); order.setStatus(0); Order temp = orderMng.save(order); ext.setOrderCode(orderCode); ext.setCategoryCode(product.getCategoryCode()); ext.setProductCount(productCount); ext.setProductName(product.getProductName()); ext.setOrderId(order.getOrderId()); ext.setProductCode(product.getProductCode()); if (null != temp) { ext.setOrderId(temp.getOrderId()); OrderExt ext2 = extMng.save(ext); temp.setExt(ext2); log.info("save Order id={}", temp.getOrderId()); if (null != ext2) { log.info("save OrderExt id={}", ext2.getId()); } else { Order temp2 = orderMng.deleteById(temp.getOrderId()); log.info("delete Order id={}", temp2.getOrderId()); } cmsLogMng.orderLogSave(request, temp.getOrderCode(), "order.log", "下订单成功:orderCode=" + temp.getOrderCode()); } else { cmsLogMng.orderLogSave(request, null, "order.log", "下订单失败,产品编号=" + productCode); } model.addAttribute("order", temp); // if(isDelegate){ // String result = "orderCodeOld="+temp.getOrderCode(); // JSONObject json=new JSONObject(); // json.put("result", result); // ResponseUtils.renderJson(response, json.toString()); // } } else { // product = productMng.findByProductCode(productCode); Order orderExit = orderMng.getOrderByCode(orderCodeOld); if (null != orderExit) { OrderExt ext = extMng.getOrderExtListByOrderId( orderExit.getOrderId()).get(0); orderExit.setExt(ext); model.addAttribute("order", orderExit); product = productMng.findByProductCode(ext.getProductCode()); // if(isDelegate){ // String result = "orderCodeOld="+orderCodeOld; // JSONObject json=new JSONObject(); // json.put("result", result); // ResponseUtils.renderJson(response, json.toString()); // } } } // List<CmsDictionary> banks = dictionaryMng.getList(); model.addAttribute("product", product); // model.addAttribute("banks", banks); CmsSite site = CmsUtils.getSite(request); FrontUtils.frontData(request, model, site); FrontUtils.frontPageData(request, model); return FrontUtils.getTplPath(request, site.getSolutionPath(), "order", CONFIRM_ORDER); } /** * 代付下单(获取产品详情) * * @param productId * @param orderCodeOld * @param productCode * @param productCount * @param flag * @param captcha * @param response * @param isDelegate * @param request * @param model * @throws JSONException */ @SuppressWarnings("unused") @RequestMapping(value = "/order/v_order_d.jspx", method = RequestMethod.POST) public void addOrderD(Integer productId, String orderCodeOld, String productCode, Integer productCount, String flag, String captcha, HttpServletResponse response, boolean isDelegate, HttpServletRequest request, ModelMap model) throws JSONException { StringBuffer p = request.getRequestURL(); int endp = p.length() - "v_order_d.jspx".length(); String path = p.toString().substring(0, endp); // System.out.println(path); List<JcOrg> jcOrgs = orgMng.getJcOrgList(); captcha = request.getParameter("captcha"); if (null != jcOrgs && jcOrgs.size() > 0) { for (int i = 0; i < jcOrgs.size(); i++) { if (path.equals(jcOrgs.get(i).getOrg())) { if (null != jcOrgs.get(i).getIsDisplay() && jcOrgs.get(i).getIsDisplay() == 1) { String msg = "爱卡商城提醒您:我们不刷信誉不招兼职 请勿将卡密交给其他人 谨防被骗"; model.addAttribute("msg", msg); } } } } String receiverEmail = RequestUtils.getQueryParam(request, "receiverEmail"); String receiverNickName = RequestUtils.getQueryParam(request, "receiverNickName"); String ip = RequestUtils.getIpAddr(request); // WebErrors errors = validateCaptcha(captcha, receiverEmail, request, // response); // if (errors.hasErrors()) { // // String result = FrontUtils.showError(request, response, model, // // errors); // String result = errors.getErrors().get(0); // JSONObject json = new JSONObject(); // json.put("status", 0); // json.put("result", result); // ResponseUtils.renderJson(response, json.toString()); // } else { Product product = null; if (null == orderCodeOld) { product = productMng.findById(productId); String searchKey = RequestUtils.getQueryParam(request, "searchKey"); WebErrors errors1 = validateSubmit(receiverEmail, searchKey, request, response); if (errors1.hasErrors()) { // String result = FrontUtils.showError(request, response, // model, errors1); String result = errors1.getErrors().get(0); JSONObject json = new JSONObject(); json.put("status", 0); json.put("result", result); ResponseUtils.renderJson(response, json.toString()); } else { String authId = (String) session .getAttribute(request, AUTH_KEY); java.sql.Date date = new java.sql.Date( new java.util.Date().getTime()); // 订单号生成 // int r1 = (int) (Math.random() * (10));// 产生3个0-9的随机数 // int r2 = (int) (Math.random() * (10)); // int r3 = (int) (Math.random() * (10)); String r1 = RandomUtil.getCharAndNumr(4);// 产生一个四位数 // long now = System.currentTimeMillis();// 一个13位的时间戳 SimpleDateFormat dateFormat = new SimpleDateFormat( "yyyyMMddhhmmss");// 一个14位时间 String now = dateFormat.format(new java.util.Date()); String orderCode = "w" + String.valueOf(r1) + String.valueOf(now);// 订单号 Order order = new Order(); OrderExt ext = new OrderExt(); // 支付方式的值 String bank = request.getParameter("bank"); order.setChargeKey(bank); if (authId != null) { // 存在认证ID Authentication auth = authMng.retrieve(authId); CmsUser user = cmsUserMng.findById(auth.getUid()); // 存在认证信息,且未过期 if (auth != null) { order.setUserId(user.getId()); order.setUserName(user.getUsername()); ext.setPrice(product.getVipPrice()); } else { order.setUserId(-1); order.setUserName("普通客户"); ext.setPrice(product.getSalePrice()); } } else { order.setUserId(-1); order.setUserName("普通客户"); ext.setPrice(product.getSalePrice()); } order.setSum(ext.getPrice() * productCount); if (ext.getPrice() < product.getPurchasePrice()) { ext.setPrice(product.getPurchasePrice()); order.setSum(product.getPurchasePrice() * productCount); log.info("提交订单时的单价大于进价,以进价为主", 0); } else if (order.getSum() < product.getPurchasePrice() * productCount) { order.setSum(product.getPurchasePrice() * productCount); } order.setIp(ip); order.setOrderCode(orderCode); order.setOrdeDate(date); order.setReceiverEmail(receiverEmail); order.setReceiverNickName(receiverNickName); if (null == order.getReceiverNickName()) { order.setReceiverNickName(order.getOrderCode()); } order.setSearchKey(searchKey); order.setSendState(0); order.setChargeType(0); order.setStatus(0); Order temp = orderMng.save(order); ext.setOrderCode(orderCode); ext.setCategoryCode(product.getCategoryCode()); ext.setProductCount(productCount); ext.setProductName(product.getProductName()); ext.setOrderId(order.getOrderId()); ext.setProductCode(product.getProductCode()); if (null != temp) { ext.setOrderId(temp.getOrderId()); OrderExt ext2 = extMng.save(ext); temp.setExt(ext2); log.info("save Order id={}", temp.getOrderId()); if (null != ext2) { log.info("save OrderExt id={}", ext2.getId()); } else { Order temp2 = orderMng.deleteById(temp.getOrderId()); log.info("delete Order id={}", temp2.getOrderId()); } cmsLogMng.orderLogSave(request, temp.getOrderCode(), "order.log", "下订单成功:orderCode=" + temp.getOrderCode()); } else { cmsLogMng.orderLogSave(request, null, "order.log", "下订单失败,产品编号=" + productCode); } model.addAttribute("order", temp); if (isDelegate) { String result = "orderCodeOld=" + temp.getOrderCode(); JSONObject json = new JSONObject(); json.put("status", 1); json.put("result", result); ResponseUtils.renderJson(response, json.toString()); } } } else { product = productMng.findByProductCode(productCode); Order orderExit = orderMng.getOrderByCode(orderCodeOld); if (null != orderExit) { OrderExt ext = extMng.getOrderExtListByOrderId( orderExit.getOrderId()).get(0); orderExit.setExt(ext); model.addAttribute("order", orderExit); if (isDelegate) { String result = "orderCodeOld=" + orderCodeOld; JSONObject json = new JSONObject(); json.put("status", 1); json.put("result", result); ResponseUtils.renderJson(response, json.toString()); } } } // } // List<CmsDictionary> banks = dictionaryMng.getList(); // model.addAttribute("product", product); } // 订单信息查询 @RequestMapping(value = "/order/v_orderInfo.jspx", method = RequestMethod.POST) public String searchOrder(String orderCode, String search_key, HttpServletRequest request, String captcha, HttpServletResponse response, ModelMap model) { if (!(orderCode == null || "".equals(orderCode)) && !(search_key == null || "".equals(search_key))) { WebErrors errors = validateCaptcha1(captcha, request, response); if (errors.hasErrors()) { return FrontUtils.showError(request, response, model, errors); } // add by chenyan 20140512 去除前后空格 orderCode = StringUtils.strip(orderCode); Order order = orderMng.getOrderByCode(orderCode); if (order == null) { model.addAttribute("msg", "您输入的订单号和查询密码不正确或不匹配!请重新输入!"); } else { // 判断密码是否正确, add by chenyan 20140512 if (null != order.getSearchKey() && order.getSearchKey().equals(search_key)) { if (null != order.getCardkey()) { String carKey = order.getCardkey(); List<Map<Integer, String>> keyList = new ArrayList<Map<Integer, String>>(); if (null != carKey) { String contentStart = " <table style='width: 470px;' align='left'> <tr >" + " <td style='background-color:#CCC'>卡号</td>" + " <td style='background-color:#CCC'>密码</td>" + " <td style='background-color:#CCC'>过期时间</td>" + " </tr> "; keyList = ReadMessagerUtils.ReadCarKey(carKey); BASE64Decoder decoder = new BASE64Decoder(); try { if (null != keyList && keyList.size() > 0) { for (Map<Integer, String> map2 : keyList) { String cardno = ""; String cardpsw = ""; if (null != map2.get(0) && !"".equals(map2.get(0))) { cardno = new String( decoder.decodeBuffer(map2 .get(0))); } if (null != map2.get(1) && !"".equals(map2.get(1))) { cardpsw = new String( decoder.decodeBuffer(map2 .get(1))); } String contentKey = " <tr>" + " <td style='background-color:#eee'>" + cardno + "</td>" + " <td style='background-color:#eee'>" + cardpsw + "</td>" + " <td style='background-color:#eee'>" + map2.get(2) + "</td> " + " </tr>"; contentStart = contentStart + contentKey; } String contentEnd = " </table></br></br>"; contentStart = contentStart + contentEnd; model.addAttribute("carKey", contentStart); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } OrderExt orderExt = extMng.getOrderExtById(orderCode); model.addAttribute("order", order); model.addAttribute("orderExt", orderExt); } else { model.addAttribute("msg", "您输入的查询密码不正确!请重新输入!"); } } } else { model.addAttribute("msg", "您输入的订单号和查询密码不能为空!请输入!"); } CmsSite site = CmsUtils.getSite(request); FrontUtils.frontData(request, model, site); FrontUtils.frontPageData(request, model); return FrontUtils.getTplPath(request, site.getSolutionPath(), "order", SEARCH_ORDER); } // 自助服务订单状态查询 @RequestMapping(value = "/order/v_orderState.jspx", method = RequestMethod.POST) public String stateOrder(String orderCode, String querytype, String searchKey, HttpServletRequest request, String captcha, HttpServletResponse response, ModelMap model) { WebErrors errors = validateCaptcha1(captcha, request, response); if (errors.hasErrors()) { return FrontUtils.showError(request, response, model, errors); } // add by chenyan 20140512 去除前后空格 orderCode = StringUtils.strip(orderCode); Order order = orderMng.getOrderByCode(orderCode); if (order == null) { model.addAttribute("msg", "您输入的订单号不存在!请重新输入!"); } else { if (null != order.getSearchKey() && order.getSearchKey().equals(searchKey)) { // 排列卡密 (自助服务不要显示卡密) /* * if(null!=order.getCardkey()){ String carKey = * order.getCardkey(); List<Map<Integer,String>> keyList = new * ArrayList<Map<Integer,String>>(); if(null!=carKey){ String * contentStart = * " <table style='width: 470px;' align='left'> <tr >" + * " <td style='background-color:#CCC'>卡号</td>" + * " <td style='background-color:#CCC'>密码</td>" + * " <td style='background-color:#CCC'>过期时间</td>" + " </tr> " * ; keyList = ReadMessagerUtils.ReadCarKey(carKey); * if(null!=keyList&&keyList.size()>0){ for (Map<Integer, * String> map2 : keyList) { String contentKey =" <tr>" + * " <td style='background-color:#eee'>"+map2.get(0)+"</td>" + * " <td style='background-color:#eee'>"+map2.get(1)+"</td>" + * " <td style='background-color:#eee'>"+map2.get(2)+"</td> " + * " </tr>"; contentStart = contentStart + contentKey; } String * contentEnd = " </table></br></br>"; contentStart = * contentStart+contentEnd; model.addAttribute("carKey", * contentStart); } * * } } */ orderCode = order.getOrderCode(); OrderExt ext = extMng.getOrderExtById(orderCode); order.setExt(ext); Integer status = order.getStatus(); if (null != querytype && "2".equals(querytype)) { if (null != status && (status == 1 || status == 2)) return againSendEmail(order, null, request, null, response, model); else { if (null == status || status == 0) { model.addAttribute("msg", "邮件补发失败!返回信息:未支付!"); // OrderExt ext = extMng.getOrderExtById(orderCode); // order.setExt(ext); model.addAttribute("ext", ext); model.addAttribute("order", order); } else { model.addAttribute("msg", "邮件补发失败!返回信息:订单已失效!请重新下单!"); } } } else if (null != querytype && "1".equals(querytype)) { if (null != status && status == 3) { model.addAttribute("msg", "订单状态更换失败!返回信息:订单已失效!请重新下单!"); } else { // OrderExt ext = extMng.getOrderExtById(orderCode); // order.setExt(ext); model.addAttribute("ext", ext); model.addAttribute("order", order); } } } else { model.addAttribute("msg", "查询密码错误!!!"); } } CmsSite site = CmsUtils.getSite(request); FrontUtils.frontData(request, model, site); FrontUtils.frontPageData(request, model); return FrontUtils.getTplPath(request, site.getSolutionPath(), "order", DOSELF_RESULT); } /** * 发送邮件 * * @param order * @param state * @param request * @param captcha * @param response * @param model * @return */ private String againSendEmail(Order order, String state, HttpServletRequest request, String captcha, HttpServletResponse response, ModelMap model) { if (null != order.getSendState() && order.getSendState() == 2) { String msg = fetchCard(request, response, model, order); if ("提卡失败".equals(msg)) { model.addAttribute("msg", "发送失败!请先检查网络或联系客服!"); Order orderNew = orderMng.getOrderByCode(order.getOrderCode()); OrderExt ext = extMng.getOrderExtById(order.getOrderCode()); model.addAttribute("ext", ext); model.addAttribute("order", orderNew); CmsSite site = CmsUtils.getSite(request); FrontUtils.frontData(request, model, site); FrontUtils.frontPageData(request, model); log.info("提卡失败", 0); return FrontUtils.getTplPath(request, site.getSolutionPath(), "order", DOSELF_RESULT); } } MailSenderInfo mailInfo = new MailSenderInfo(); List<AgentSet> list = agentSetMng.getAgentSetList(); SetMailInfoUtils.setMailMss(mailInfo, list); mailInfo.setToAddress(order.getReceiverEmail()); // 要发送的邮箱地址 // 邮件内容 // mailInfo.setContent("你好!"); //文本格式的邮件内容 // html页面格式的邮件内容 // mailInfo.setContent("<div style='width:900px;height:900px;text-align:center;color:blue;font-size:20px;border:solid red;'><b>亲爱的"+order.getReceiverNickName()+"!</br>您在<a href='http://www.003511.com/'>爱卡点卡商城</a>有如下订单:您的订单号为:<a href='http://www.003511.com/order/v_searchinput.jspx'>"+order.getOrderCode()+"</a></br>您购买的点卡信息如下 (格式为:卡号1,卡密1,有效日期|卡号2,卡密2,有效期2):</b></br>" // + order.getCardkey() + "</div>"); String contentStart = getMailContents(order); mailInfo.setContent(contentStart); // 这个类主要来发送邮件 SimpleMailSender sms = new SimpleMailSender(); // boolean flag = sms.sendTextMail(mailInfo);// 发送文体格式 boolean flag = sms.sendHtmlMail(mailInfo);// 发送html格式 if (flag) { // true则发送成功 if (null == order.getSendTime() || "".equals(order.getSendTime())) { order.setSendTime(new java.sql.Date(new java.util.Date() .getTime())); } order.setStatus(1); //订单状态变成已发货 order.setSendState(1); //发货状态变成已发货 add by bin 2015-2-27 orderMng.updateByUpdater(order); String msg = "发送成功!请注意查收!"; model.addAttribute("msg", msg); cmsLogMng.sendLogSave(request, order.getOrderCode(), "order.log.sendSuccess", "orderCode=" + order.getOrderCode() + ";receiverEmail=" + order.getReceiverEmail() + ";信息:" + msg); } else { String msg = "发送失败!请先检查网络或联系客服!"; model.addAttribute("msg", msg); cmsLogMng.sendLogSave(request, order.getOrderCode(), "order.log.sendSuccess", "orderCode=" + order.getOrderCode() + ";receiverEmail=" + order.getReceiverEmail() + ";信息:" + msg); } Order orderNew = orderMng.getOrderByCode(order.getOrderCode()); OrderExt ext = extMng.getOrderExtById(order.getOrderCode()); model.addAttribute("ext", ext); model.addAttribute("order", orderNew); CmsSite site = CmsUtils.getSite(request); FrontUtils.frontData(request, model, site); FrontUtils.frontPageData(request, model); return FrontUtils.getTplPath(request, site.getSolutionPath(), "order", DOSELF_RESULT); } /** * 邮件内容 * * @param order * @return */ private String getMailContents(Order order) { String contentStart = "<div>" + " <h1 style='font:13px Verdana, Geneva, sans-serif; color:#000'>尊敬的" + order.getReceiverNickName() + "用户,您好!</h1>" + " <h1 style='font:13px Verdana, Geneva, sans-serif; color:#000'>感谢您对Q-Q点卡商城的支持,现将您从此次购买的产品信息发送到您的邮件给您!</h1>" + " </br>" + " <h1 style='font:13px Verdana, Geneva, sans-serif; color:#000'>订单号:" + order.getOrderCode() + "</h1>" + " <h1 style='font:13px Verdana, Geneva, sans-serif; color:#000'>产品名称:" + order.getExt().getProductName() + "</h1>" + " <h1 style='font:13px Verdana, Geneva, sans-serif; color:#000'>产品数量:" + order.getExt().getProductCount() + "</h1>" + " <h1 style='font:13px Verdana, Geneva, sans-serif; color:#000'>订单总额:<span style='color:#F00;'>¥" + order.getSum() + "</span></h1>" + " <h1 style='font:13px Verdana, Geneva, sans-serif; color:#000'>产品信息:</h1>" + " <table width='600'> <tr >" + " <td style='background-color:#CCC'>卡号</td>" + " <td style='background-color:#CCC'>密码</td>" + " <td style='background-color:#CCC'>过期时间</td>" + " </tr> "; BASE64Decoder decoder = new BASE64Decoder(); try { String carKey = order.getCardkey(); List<Map<Integer, String>> keyList = new ArrayList<Map<Integer, String>>(); if (null != carKey) { keyList = ReadMessagerUtils.ReadCarKey(carKey); if (null != keyList && keyList.size() > 0) { for (Map<Integer, String> map2 : keyList) { String cardno = ""; String cardpsw = ""; if (null != map2.get(0) && !"".equals(map2.get(0))) { cardno = new String(decoder.decodeBuffer(map2 .get(0))); } if (null != map2.get(1) && !"".equals(map2.get(1))) { cardpsw = new String(decoder.decodeBuffer(map2 .get(1))); } String contentKey = " <tr>" + " <td style='background-color:#eee'>" + cardno + "</td>" + " <td style='background-color:#eee'>" + cardpsw + "</td>" + " <td style='background-color:#eee'>" + map2.get(2) + "</td> " + " </tr>"; contentStart = contentStart + contentKey; } } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } String contentEnd = " </table></br></br>" + " <h1 style='font:13px Verdana, Geneva, sans-serif; color:#000'><strong>温馨提示:</strong>千万注意!不要将邮件信息购买的订单号等信息随便透露给任何人!!</h1>" + " <h1 style='font:13px Verdana, Geneva, sans-serif; color:#000'>本邮件由系统邮箱发送,请不要回复!!系统邮箱无人职守故对任何邮件都不作回复!!</h1>" + " </div>"; contentStart = contentStart + contentEnd; return contentStart; } /** * 页面显示卡密详情 * * @param order * @param request * @return */ private String getMailContents1(Order order, HttpServletRequest request) { String contentStart = "<div>" + " <h1 style='font:13px Verdana, Geneva, sans-serif; color:#000'>尊敬的" + order.getReceiverNickName() + "用户,您好!</h1>" + " <h1 style='font:13px Verdana, Geneva, sans-serif; color:#000'>感谢您对Q-Q点卡商城的支持,现将您从此次购买的产品信息发送到您的邮件给您!</h1>" + " </br>" + " <h1 style='font:13px Verdana, Geneva, sans-serif; color:#000'>订单号:" + order.getOrderCode() + "</h1>" + " <h1 style='font:13px Verdana, Geneva, sans-serif; color:#000'>产品名称:" + order.getExt().getProductName() + "</h1>" + " <h1 style='font:13px Verdana, Geneva, sans-serif; color:#000'>产品数量:" + order.getExt().getProductCount() + "</h1>" + " <h1 style='font:13px Verdana, Geneva, sans-serif; color:#000'>订单总额:<span style='color:#F00;'>¥" + order.getSum() + "</span></h1>" + " <h1 style='font:13px Verdana, Geneva, sans-serif; color:#000'>产品信息:</h1>" + " <table width='600'> <tr >" + " <td style='background-color:#CCC'>卡号</td>" + " <td style='background-color:#CCC'>密码</td>" + " <td style='background-color:#CCC'>过期时间</td>" + " </tr> "; BASE64Decoder decoder = new BASE64Decoder(); try { String carKey = order.getCardkey(); List<Map<Integer, String>> keyList = new ArrayList<Map<Integer, String>>(); if (null != carKey) { keyList = ReadMessagerUtils.ReadCarKey(carKey); if (null != keyList && keyList.size() > 0) { for (Map<Integer, String> map2 : keyList) { String cardno = ""; String cardpsw = ""; if (null != map2.get(0) && !"".equals(map2.get(0))) { cardno = new String(decoder.decodeBuffer(map2 .get(0))); } if (null != map2.get(1) && !"".equals(map2.get(1))) { cardpsw = new String(decoder.decodeBuffer(map2 .get(1))); } String contentKey = " <tr>" + " <td style='background-color:#eee'>" + cardno + "</td>" + " <td style='background-color:#eee'>" + cardpsw + "</td>" + " <td style='background-color:#eee'>" + map2.get(2) + "</td> " + " </tr>"; contentStart = contentStart + contentKey; } } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } String contentEnd = " </table></br> </br>" + " <h1 style='font:13px Verdana, Geneva, sans-serif; color:#000'><strong>温馨提示:</strong>千万注意!不要将邮件信息购买的订单号等信息随便透露给任何人!!</h1>" + " <h1 style='font:13px Verdana, Geneva, sans-serif; color:#000'>本邮件由系统邮箱发送,请不要回复!!系统邮箱无人职守故对任何邮件都不作回复!!</h1>" + " </div>"; contentStart = contentStart + contentEnd; return contentStart; } // 订单支付 需判断银行支付方式 @RequestMapping(value = "/order/v_orderPay.jspx", method = RequestMethod.POST) public String orderPay(String bank, HttpServletRequest request, String captcha, HttpServletResponse response, ModelMap model) throws Exception { // WebErrors errors = validateCaptcha1(captcha, request, response); // if (errors.hasErrors()) { // return FrontUtils.showError(request, response, model, errors); // } CmsSite site = CmsUtils.getSite(request); String orderCode = request.getParameter("orderCode"); String productName = request.getParameter("productName"); // String sumStr = request.getParameter("sum"); Order orderPay = orderMng.getOrderByCode(orderCode); // System.out.println("下单时实际金额:" + orderPay.getSum()); // System.out.println("下单旱提交金额:" + sumStr); bank = orderPay.getChargeKey(); // 多加一个判断。防止总额被恶意改掉 if (null != orderPay) { String sum = String.valueOf(orderPay.getSum()); if (null != bank) { if (bank.equals("alipay")) { //this.alipay(null, orderCode, productName, sum, request, // response, model); tianGuaTransport2alipay(orderCode, productName, sum, request, response, model); } else { this.ipsPay(bank, orderCode, productName, sum, request, response, model); } // else { // this.alipay(bank, orderCode, productName, sum, request, // response, model); // } } } // 支付类型 return FrontUtils.getTplPath(request, site.getSolutionPath(), "order", ALIPAY_SUBMIT); } //----------------------------------------------------------------------------- /** * 建立请求,转账到支付宝 * @param sParaTemp 请求参数数组 * @param strMethod 提交方式。两个值可选:post、get * @param strButtonName 确认按钮显示文字 * @return 提交表单HTML文本 */ private String tianGuaBuildRequest(String receiver, String amount, String title, String memo, String strMethod, String strButtonName) { StringBuffer sbHtml = new StringBuffer(); String transportUrl = "https://shenghuo.alipay.com/send/payment/fill.htm"; sbHtml.append("<form id=\"alipaysubmit\" name=\"alipaysubmit\" action=\"" + transportUrl + "\" method=\"" + strMethod + "\">"); sbHtml.append("<input type=\"hidden\" name='optEmail' value=\"" + receiver + "\"/>"); sbHtml.append("<input type=\"hidden\" name='payAmount' value=\"" + amount + "\"/>"); sbHtml.append("<input type=\"hidden\" name='title' value=\"" + title + "\"/>"); sbHtml.append("<input type=\"hidden\" name='memo' value=\"" + memo + "\"/>"); //submit按钮控件请不要含有name属性 sbHtml.append("<input type=\"submit\" value=\"" + strButtonName + "\" style=\"display:none;\"></form>"); sbHtml.append("<script>document.forms['alipaysubmit'].submit();</script>"); return sbHtml.toString(); } /** * 转账到指定的支付宝账号 * * @param orderCode * @param productName * @param sum * @param request * @param model * @throws IOException * @throws DocumentException * @throws MalformedURLException */ private void tianGuaTransport2alipay(String orderCode, String productName, String sum, HttpServletRequest request, HttpServletResponse response, ModelMap model){ try { String str = tianGuaBuildRequest("15859296876", sum, orderCode, "请勿修改付款说明,以免影响自动发货", "post", "转账"); response.setContentType("text/html"); response.setCharacterEncoding("GBK"); PrintWriter out; out = response.getWriter(); out.write(str); out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } } /** * 新增甜瓜验证接口 * @param out_trade_no * @param trade_no * @param total_fee * @param time * @return */ private int tianGuaVerify(String out_trade_no, String trade_no, String total_fee, String time, String key){ //时间检验 SimpleDateFormat datetimeformat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); try { Date theDate = datetimeformat.parse(time); Date now = new Date(); long diff = now.getTime() - theDate.getTime(); if(diff > 10000 || diff < 0 ){ System.err.println("time=" + time + ", now=" + now.toString()); return -1; } } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } //MD5检验 String mykey = "dkW_2015"; String temp = "orderSn=" + out_trade_no + "&tradeNo=" + trade_no + "&amount=" + total_fee + "&time=" + time + "&key=" + mykey; System.out.println(temp); temp = MD5Utils.GetMD5Code(temp); System.out.println("key=" + key + ",temp=" + temp); if(key.equals(temp)){ return 1; } return 0; } /** * 新增甜瓜通知接口 * @param request * @param response * @param model * @author chenyan */ @RequestMapping(value = "/order/v_TianGuaCallBack.jspx", method = RequestMethod.POST) public void v_TianGuaCallBack(HttpServletRequest request, HttpServletResponse response, ModelMap model) { // 获取POST过来反馈信息 String out_trade_no = RequestUtils.getQueryParam(request, "orderSn");// 商户订单号 String trade_no = RequestUtils.getQueryParam(request, "tradeNo");// 支付宝交易号 String total_fee = RequestUtils.getQueryParam(request, "amount");// 交易金额 String time = RequestUtils.getQueryParam(request, "time");// 交易金额 String key = RequestUtils.getQueryParam(request, "key"); int ret = tianGuaVerify(out_trade_no, trade_no, total_fee, time, key); if (ret == 1) {// 验证成功 // 请在这里加上商户的业务逻辑程序代码 Order order = orderMng.getOrderByCode(out_trade_no); if (order == null) { System.out.println("根据支付宝返回的参数订单编号:" + out_trade_no + "的订单,异步校验,在数据查找订单为空!交易终止!"); return; } OrderExt ext = extMng.getOrderExtByOrderCode(order.getOrderCode()).get(0); // ——更改数据库的订单相关状态—— order.setChargeCode(trade_no); if (1 != order.getStatus()) order.setStatus(2); if (null == order.getChargeTime() || "".equals(order.getChargeTime())) { order.setChargeTime(new java.sql.Date(new java.util.Date() .getTime())); } if (1 != order.getSendState()) order.setSendState(2); order.setChargeAccount("tiangua"); order.setChargeType(1); // order.setChargeCode(out_trade_no); order = orderMng.updateByUpdater(order); order.setExt(ext); if (2 == order.getStatus()) { //if(null!=orderCodeTemp&&!"".equals(orderCodeTemp)&&orderCodeTemp.equals(out_trade_no)){ this.fetchCard(request, response, model, order); // orderCodeTemp = out_trade_no; //} } System.out.println("根据支付宝返回的参数订单编号:" + out_trade_no + "的订单,异步校验成功!支付成功 "); } else {// 验证失败 System.out.println("根据支付宝返回的参数订单编号:" + out_trade_no + "的订单,异步校验,由于验证失败,交易失败!!! "); } } //----------------------------------------------------------------------------- // 订单支付 支付宝服务器异步通知页面 @RequestMapping(value = "/order/v_onCallBack.jspx", method = RequestMethod.POST) public void v_onCallBack(HttpServletRequest request, HttpServletResponse response, ModelMap model) { System.out.println("支付宝服务器异步通知页面!"); // 请求的域名 StringBuffer p = request.getRequestURL(); int endp = p.length() - "order/v_onCallBack.jspx".length(); String path1 = p.toString().substring(0, endp); // 获取支付宝POST过来反馈信息 Map<String, String> params = new HashMap<String, String>(); Map requestParams = request.getParameterMap(); for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) { String name = (String) iter.next(); String[] values = (String[]) requestParams.get(name); String valueStr = ""; for (int i = 0; i < values.length; i++) { valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ","; } // 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化 // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk"); params.put(name, valueStr); } String out_trade_no = RequestUtils.getQueryParam(request, "out_trade_no");// 商户订单号 String trade_no = RequestUtils.getQueryParam(request, "trade_no");// 支付宝交易号 String trade_status = RequestUtils.getQueryParam(request, "trade_status");// 交易状态 String total_fee = RequestUtils.getQueryParam(request, "total_fee");// 交易金额 String buyer_email = RequestUtils.getQueryParam(request, "buyer_email");// 卖家支付账号 String subject = RequestUtils.getQueryParam(request, "subject");// 商品名称 if (AlipayNotify.verify(params)) {// 验证成功 // 请在这里加上商户的业务逻辑程序代码 Order order = orderMng.getOrderByCode(out_trade_no); OrderExt ext = extMng.getOrderExtByOrderCode(order.getOrderCode()) .get(0); if (order == null) { // AlipayCore.logResult("根据支付宝返回的参数订单编号:" + out_trade_no // + "的订单,异步校验,在数据查找订单为空!交易终止!"); log.info("根据支付宝返回的参数订单编号:" + out_trade_no + "的订单,异步校验,在数据查找订单为空!交易终止!"); return; } if (null == ext || !ext.getProductName().equals(subject)) { log.info("请求域名=" + path1 + "根据支付宝返回的参数订单编号:" + out_trade_no + "的订单,同步校验,订单参数商品名称不对!交易终止!返回名称为:" + subject); // model.addAttribute("msg", "交易失败!"); // cmsLogMng.orderLogSave(request, order.getOrderCode(), // "order.log", "请求域名="+path1+"交易失败,订单有误--返回的名称为:" + subject); return; } // ——更改数据库的订单相关状态—— if (trade_status.equals("TRADE_FINISHED")) { // 判断该笔订单是否在商户网站中已经做过处理 // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 // AlipayCore.logResult("根据支付宝返回的参数订单编号:" + out_trade_no // + "的订单,异步校验成功!交易完成 "); log.info("根据支付宝返回的参数订单编号:" + out_trade_no + "的订单,异步校验成功!交易完成 "); // 如果有做过处理,不执行商户的业务程序 // 注意: // 该种交易状态只在两种情况下出现 // 1、开通了普通即时到账,买家付款成功后。 // 2、开通了高级即时到账,从该笔交易成功时间算起,过了签约时的可退款时限(如:三个月以内可退款、一年以内可退款等)后。 } else if (trade_status.equals("TRADE_SUCCESS")) { order.setChargeCode(trade_no); if (1 != order.getStatus() && 2 != order.getStatus()) order.setStatus(2); if (null == order.getChargeTime() || "".equals(order.getChargeTime())) { order.setChargeTime(new java.sql.Date(new java.util.Date() .getTime())); } if (1 != order.getSendState() && 2 != order.getSendState()) order.setSendState(2); order.setChargeAccount(buyer_email); order.setChargeType(1); // order.setChargeCode(out_trade_no); order = orderMng.updateByUpdater(order); // String productCode= ext.getProductCode(); // Product = productMng.findByProductCode(productCode) order.setExt(ext); if (2 == order.getStatus()) { if(null!=orderCodeTemp&&!"".equals(orderCodeTemp)&&orderCodeTemp.equals(out_trade_no)){ this.fetchCard(request, response, model, order); orderCodeTemp = out_trade_no; } // String msg = getMailContents1(order, request); // model.addAttribute("msg", msg); } // model.addAttribute("msg", "交易成功!"); // 判断该笔订单是否在商户网站中已经做过处理 // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序支付成功 // AlipayCore.logResult("根据支付宝返回的参数订单编号:" + out_trade_no // + "的订单,异步校验成功!支付成功 "); log.info("根据支付宝返回的参数订单编号:" + out_trade_no + "的订单,异步校验成功!支付成功 "); // 如果有做过处理,不执行商户的业务程序 // 注意: // 该种交易状态只在一种情况下出现——开通了高级即时到账,买家付款成功后。 } // AlipayCore.logResult("根据支付宝返回的参数订单编号:" + out_trade_no // + "的订单,异步校验成功!交易完成! "); log.info("根据支付宝返回的参数订单编号:" + out_trade_no + "的订单,异步校验成功!交易完成! "); } else {// 验证失败 // AlipayCore.logResult("根据支付宝返回的参数订单编号:" + out_trade_no // + "的订单,异步校验,由于验证失败,交易失败!!! "); log.info("根据支付宝返回的参数订单编号:" + out_trade_no + "的订单,异步校验,由于验证失败,交易失败!!! "); } } /** * 环讯支付异步返回通知 * * @param request * @param response * @param model * @throws IOException */ @RequestMapping(value = "/order/ips_CallBack.jspx") public void ips_CallBack(HttpServletRequest request, HttpServletResponse response, ModelMap model) throws IOException { System.out.println("环讯支付异步通知!"); // 请求的域名 StringBuffer p = request.getRequestURL(); int endp = p.length() - "order/ips_CallBack.jspx".length(); String path1 = p.toString().substring(0, endp); String rtnUrl = formatString(path1 + "order/ips_CallBack.jspx"); String billno = request.getParameter("billno"); String currency_type = request.getParameter("Currency_type"); String amount = request.getParameter("amount"); String mydate = request.getParameter("date"); String succ = request.getParameter("succ"); String msgips = request.getParameter("msg"); // String attach = request.getParameter("attach"); String ipsbillno = request.getParameter("ipsbillno"); String retEncodeType = request.getParameter("retencodetype"); String signature = request.getParameter("signature"); // 返回订单加密的明文:billno+【订单编号】+currencytype+【币种】+amount+【订单金额】+date+【订单日期】+succ+【成功标志】+ipsbillno+【IPS订单编号】+retencodetype // +【交易返回签名方式】+【商户内部证书】 String content = "billno" + billno + "currencytype" + currency_type + "amount" + amount + "date" + mydate + "succ" + succ + "ipsbillno" + ipsbillno + "retencodetype" + retEncodeType; // 明文:订单编号+订单金额+订单日期+成功标志+IPS订单编号+币种 // request.setCharacterEncoding("iso-8859-1"); // request.setCharacterEncoding("utf-8"); // response.setContentType("text/html"); // response.setCharacterEncoding("gb2312"); // PrintWriter out = response.getWriter(); System.out.println("环讯支付异步返回:v_md5str=" + content); boolean verify = false; if (retEncodeType.equals("17")) { // 登陆http://merchant.ips.com.cn/商户后台下载的商户证书内容 String md5Key = "ABovowjMd1CscDxpnvAUxNbS5G5fxZYLaZNEZDfdzgsbxpH6ZlyOTjLnaLqWr2O3TrH2qhFZEXVGV0VGzy5CaArsEaeDO9nxHo85XEGrUP8wC4HZqZWswBTHzPoE31A5"; cryptix.jce.provider.MD5 b = new cryptix.jce.provider.MD5(); String SignMD5 = b.toMD5(content + md5Key).toLowerCase(); if (SignMD5.equals(signature)) { verify = true; } } if (verify) { if (succ != null) { if (succ.equalsIgnoreCase("Y")) { // 支付成功,商户 根据自己业务做相应逻辑处理 // 此处加入商户系统的逻辑处理(例如判断金额,更新订单状态等等)...... Order order = orderMng.getOrderByCode(billno); if (order == null) { log.info("请求域名=" + path1 + "根据环讯支付返回的参数订单编号:" + billno + "的订单,异步校验,在数据查找订单为空!交易终止!"); return; } OrderExt ext = extMng.getOrderExtByOrderCode( order.getOrderCode()).get(0); if (1 != order.getStatus()) { if (2 != order.getStatus()) { order.setStatus(2); order.setChargeCode(ipsbillno); if (null == order.getChargeTime() || "".equals(order.getChargeTime())) { order.setChargeTime(new java.sql.Date( new java.util.Date().getTime())); } if (1 != order.getSendState()) { if(2 != order.getSendState()){ order.setSendState(2); productMng.updateSaleNum(ext.getProductCode()); } } order.setChargeAccount(ipsbillno); order.setChargeType(5);// 环讯在线 order.setChargeCode(ipsbillno); order = orderMng.updateByUpdater(order); order.setExt(ext); // 多加一个判断以防支付金额不对则不提卡 if (2 == order.getStatus() && null != amount && !"".equals(amount) && Double.valueOf(amount) .equals(order.getSum())) { // 提卡 fetchCard(request, response, model, order); String msg = getMailContents1(order, request); System.out.println("发货成功!"); model.addAttribute("msg", msg); cmsLogMng.orderLogSave(request, order.getOrderCode(), "order.log", "请求域名=" + rtnUrl + ":环讯支付-" + ipsbillno + ":实付金额=" + amount); } if (!Double.valueOf(amount).equals(order.getSum())) { model.addAttribute("msg", "支 |
|||
js多级下拉框联动 | js多级, 下拉框, 联动 | ||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>JS联动下拉框</title> <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> <meta name="ProgId" content="FrontPage.Editor.Document"> <meta name="Originator" content="Microsoft Visual Studio .NET 7.1"> <script language="javascript" > /* ** ================================================================================================== ** 类名:CLASS_LIANDONG_YAO ** 功能:多级连动菜单 ** 作者:YAODAYIZI ** ================================================================================================== **/ function CLASS_LIANDONG_YAO(array) { //数组,联动的数据源 this.array=array; this.indexName=''; this.obj=''; //设置子SELECT // 参数:当前onchange的SELECT ID,要设置的SELECT ID this.subSelectChange=function(selectName1,selectName2) { //try //{ var obj1=document.all[selectName1]; var obj2=document.all[selectName2]; var objName=this.toString(); var me=this; obj1.onchange=function() { me.optionChange(this.options[this.selectedIndex].value,obj2.id) } } //设置第一个SELECT // 参数:indexName指选中项,selectName指select的ID this.firstSelectChange=function(indexName,selectName) { this.obj=document.all[selectName]; console.log(this.obj); this.indexName=indexName; this.optionChange(this.indexName,this.obj.id) } // indexName指选中项,selectName指select的ID this.optionChange=function (indexName,selectName) { var obj1=document.all[selectName]; var me=this; obj1.length=0; obj1.options[0]=new Option("请选择",''); for(var i=0;i<this.array.length;i++) { if(this.array[i][1]==indexName) { //alert(this.array[i][1]+" "+indexName); obj1.options[obj1.length]=new Option(this.array[i][2],this.array[i][0]); } } } } </script> </head> <body> <script src="http://www.21class.com/2004/ajcoun/mystat.asp?siteid=4"></script> <p>js在<a href="http://www.21class.com/kehu/form/class_liandong_yao.js" target="_blank">这里</a> asp数据库调用在<a href="http://www.21class.com/kehu/form/htmlpage1.asp" target="_blank">这里</a></p> <form name="form1" method="post"> <SELECT ID="s1" NAME="s1" > <OPTION selected></OPTION> </SELECT> <SELECT ID="s2" NAME="s2" > <OPTION selected></OPTION> </SELECT> <SELECT ID="s3" NAME="s3"> <OPTION selected></OPTION> </SELECT> <br> <br><br> <SELECT ID="x1" NAME="x1" > <OPTION selected></OPTION> </SELECT> <SELECT ID="x2" NAME="x2" > <OPTION selected></OPTION> </SELECT> <SELECT ID="x3" NAME="x3"> <OPTION selected></OPTION> </SELECT> <SELECT ID="x4" NAME="x4"> <OPTION selected></OPTION> </SELECT> <SELECT ID="x5" NAME="x5"> <OPTION selected></OPTION> </SELECT> </form> </body> <script language="javascript"> //例子1------------------------------------------------------------- //数据源 var array=new Array(); array[0]=new Array("华南地区","根目录","华南地区"); //数据格式 ID,父级ID,名称 array[1]=new Array("华北地区","根目录","华北地区"); array[2]=new Array("上海","华南地区","上海"); array[3]=new Array("广东","华南地区","广东"); array[4]=new Array("徐家汇","上海","徐家汇"); array[5]=new Array("普托","上海","普托"); array[6]=new Array("广州","广东","广州"); array[7]=new Array("湛江","广东","湛江"); //-------------------------------------------- //这是调用代码 var liandong=new CLASS_LIANDONG_YAO(array) //设置数据源 liandong.firstSelectChange("根目录","s1"); //设置第一个选择框 liandong.subSelectChange("s1","s2"); //设置子级选择框 liandong.subSelectChange("s2","s3"); //例子2------------------------------------------------------------- //数据源 var array2=new Array();//数据格式 ID,父级ID,名称 array2[0]=new Array("测试测试","根目录","测试测试"); array2[1]=new Array("华北地区","根目录","华北地区"); array2[2]=new Array("上海","测试测试","上海"); array2[3]=new Array("广东","测试测试","广东"); array2[4]=new Array("徐家汇","上海","徐家汇"); array2[5]=new Array("普托","上海","普托"); array2[6]=new Array("广州","广东","广州"); array2[7]=new Array("湛江","广东","湛江"); array2[8]=new Array("不知道","湛江","不知道"); array2[9]=new Array("5555","湛江","555"); array2[10]=new Array("++++","不知道","++++"); array2[11]=new Array("111","徐家汇","111"); array2[12]=new Array("222","111","222"); array2[13]=new Array("333","222","333"); //-------------------------------------------- //这是调用代码 //设置数据源 var liandong2=new CLASS_LIANDONG_YAO(array2); //设置第一个选择框 liandong2.firstSelectChange("根目录","x1"); //设置子选择框 liandong2.subSelectChange("x1","x2") liandong2.subSelectChange("x2","x3") liandong2.subSelectChange("x3","x4") liandong2.subSelectChange("x4","x5") </script> </html> |
|||
状态模式(State) | 状态模式(state) | ||
20、状态模式(State) 核心思想就是:当对象的状态改变时,同时改变其行为,很好理解!就拿QQ来说,有几种状态,在线、隐身、忙碌等,每个状态对应不同的操作,而且你的好友也能看到你的状态,所以,状态模式就两点:1、可以通过改变状态来获得不同的行为。2、你的好友能同时看到你的变化。看图: State类是个状态类,Context类可以实现切换,我们来看看代码: [java] view plaincopy package com.xtfggef.dp.state; /** * 状态类的核心类 * 2012-12-1 * @author erqing * */ public class State { private String value; public String getValue() { return value; } public void setValue(String value) { this.value = value; } public void method1(){ System.out.println("execute the first opt!"); } public void method2(){ System.out.println("execute the second opt!"); } } [java] view plaincopy package com.xtfggef.dp.state; /** * 状态模式的切换类 2012-12-1 * @author erqing * */ public class Context { private State state; public Context(State state) { this.state = state; } public State getState() { return state; } public void setState(State state) { this.state = state; } public void method() { if (state.getValue().equals("state1")) { state.method1(); } else if (state.getValue().equals("state2")) { state.method2(); } } } 测试类: [java] view plaincopy public class Test { public static void main(String[] args) { State state = new State(); Context context = new Context(state); //设置第一种状态 state.setValue("state1"); context.method(); //设置第二种状态 state.setValue("state2"); context.method(); } } 输出: execute the first opt! execute the second opt! 根据这个特性,状态模式在日常开发中用的挺多的,尤其是做网站的时候,我们有时希望根据对象的某一属性,区别开他们的一些功能,比如说简单的权限控制等。 |
|||
工具类,可以用作获取系统日期、订单编号等 | 基本测试 | ||
package com.alipay.util; import java.util.Date; import java.util.Random; import java.text.SimpleDateFormat; import java.text.DateFormat; /* * *类名:UtilDate *功能:自定义订单类 *详细:工具类,可以用作获取系统日期、订单编号等 *版本:3.3 *日期:2012-08-17 *说明: *以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。 *该代码仅供学习和研究支付宝接口使用,只是提供一个参考。 */ public class UtilDate { /** 年月日时分秒(无下划线) yyyyMMddHHmmss */ public static final String dtLong = "yyyyMMddHHmmss"; /** 完整时间 yyyy-MM-dd HH:mm:ss */ public static final String simple = "yyyy-MM-dd HH:mm:ss"; /** 年月日(无下划线) yyyyMMdd */ public static final String dtShort = "yyyyMMdd"; /** * 返回系统当前时间(精确到毫秒),作为一个唯一的订单编号 * @return * 以yyyyMMddHHmmss为格式的当前系统时间 */ public static String getOrderNum(){ Date date=new Date(); DateFormat df=new SimpleDateFormat(dtLong); return df.format(date); } /** * 获取系统当前日期(精确到毫秒),格式:yyyy-MM-dd HH:mm:ss * @return */ public static String getDateFormatter(){ Date date=new Date(); DateFormat df=new SimpleDateFormat(simple); return df.format(date); } /** * 获取系统当期年月日(精确到天),格式:yyyyMMdd * @return */ public static String getDate(){ Date date=new Date(); DateFormat df=new SimpleDateFormat(dtShort); return df.format(date); } /** * 产生随机的三位数 * @return */ public static String getThree(){ Random rad=new Random(); return rad.nextInt(1000)+""; } /** * 产生随机的六位数 * @return */ public static String getThree(){ int code = (int)((Math.random()*9+1)*100000); } } |
|||
上传图片 | |||
package com.freejuguo.framework.gprs.util; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; /** * @描述: * @作者: suyx * @创建时间: 2013-12-28 下午2:07:59 * @版本: V1.0.0 */ public class A { public static void main(String[] args) { File inFile = new File("D:\\test\\1.jpg"); File outFile = new File("D:\\test2\\2.jpg"); if(!outFile.exists()){ try { outFile.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } try { FileInputStream in = new FileInputStream(inFile); byte[] array = new byte[in.available()]; int len = in.read(array); FileOutputStream out = new FileOutputStream(outFile); out.write(array,0,len); in.close(); out.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } // System.out.println(1200 * 100 / 256); } } |
|||
数组 | arraycopy | ||
public class BasicArray{ public static void main(String args[]){ int myArray[]={1,2,3,4,5,6,7,8,9,10}; int thisArray[]=new int[myArray.length]; int thatArray[]=new int[myArray.length]; System.arraycopy(myArray,0,thisArray,0,myArray.length);//myArray引用变量给thisArray for(int i=0;i<thisArray.length;i++){ //利用控制循环语句打印出thisArray的值 System.out.print(" "+thisArray[i]); } System.out.println(); for(int j=0;j<thisArray.length;j++){ //建立它的值为索引值的阶乘。打印数组的值的控制语句 int a=thisArray[j]; int b=1; for(int m=1;m<=a;m++){ b=b*m; //数组每个数里面的阶乘 } System.out.print(" "+b); } System.out.println(); System.arraycopy(thisArray,0,thatArray,0,thisArray.length); for(int i=0;i<thatArray.length;i++){ System.out.print(" "+thatArray[i]); } } } |
|||
集合容器类 | |||
import java.util.*; import javax.swing.JOptionPane; public class DateExample { public static void main(String args[ ]) { String str=JOptionPane.showInputDialog("输入第一个日期的年份:"); int yearOne=Integer.parseInt(str); str=JOptionPane.showInputDialog("输入该年的月份:"); int monthOne=Integer.parseInt(str); str=JOptionPane.showInputDialog("输入该月份的日期:"); int dayOne=Integer.parseInt(str); str=JOptionPane.showInputDialog("输入第二个日期的年份:"); int yearTwo=Integer.parseInt(str); str=JOptionPane.showInputDialog("输入该年的月份:"); int monthTwo=Integer.parseInt(str); str=JOptionPane.showInputDialog("输入该月份的日期:"); int dayTwo=Integer.parseInt(str); Calendar calendar=Calendar.getInstance(); calendar.set(yearOne, monthOne, dayOne); long timeOne=calendar.getTimeInMillis(); //calendar表示的时间转换成毫秒 calendar.set(yearTwo,monthTwo,dayTwo); long timeTwo=calendar.getTimeInMillis(); //calendar表示的时间转换成毫秒。 Date date1=new Date(timeOne); Date date2=new Date(timeTwo); if(date2.equals(date1)) { System.out.println("两个日期的年、月、日完全相同"); } else if(date2.after(date1)) { System.out.println("您输入的第二个日期大于第一个日期"); } else if(date2.before(date1)) { System.out.println("您输入的第二个日期小于第一个日期"); } long days=Math.abs(timeOne-timeTwo)/1000/3600/24; System.out.println(yearOne+"年"+monthOne+"月"+dayOne+"日和" +yearTwo+"年"+monthTwo+"月"+dayTwo+"相隔"+days+"天"); } } |
|||
类和多像 | 银行存取款 | ||
import java.util.*; public class Bank{ public static void main(String[] args) throws MyException{ bank1 b=new bank1(); b.setID(123456); b.setName("zhangshan"); b.setAddress("闽南科技学院"); b.setBalance(100.0); b.check(); System.out.println("-----------------存款操作:-------------------="); System.out.println("输入存款金额:"); double x,y,z; Scanner reader= new Scanner(System.in); x=reader.nextDouble(); System.out.println("存款后:"); b.savingMoney(x); //实现存款的功能 b.check(); System.out.println("-----------------取款操作:-------------------="); System.out.println("输入取款金额:"); Scanner reader1= new Scanner(System.in); y=reader1.nextDouble(); System.out.println("取款后:"); try{ b.drawMoney(y); //实现取款的功能 } catch(MyException e)//捕捉异常 { System.out.println(e.toString()); } if(y>b.getBalance()) {Scanner reader2= new Scanner(System.in); y=reader2.nextDouble(); b.drawMoney(y); } } } public class bank1{ int ID; String name; String address; double balance;//存款余额 double rate;// 利率 double interest;// public int getID() {//获取账户 return ID; } public void setID(int iD) {//设置账户 ID = iD; } public void setName(String name) {//设置储户名 this.name=name; } public String getName() {//获取储户名 return name; } public String getAddress() {//获取储户地址 return address; } public void setAddress(String address) {//设置储户地址 this.address = address; } public double getBalance() {//获取余额 return balance; } public void setBalance(double balance) {//设置余额 this.balance = balance; } public double getRate() {//获取利率 return rate; } public void setRate(double rate) {//设置利率 this.rate = rate; } public void savingMoney(double money){//存款 balance=balance+money; } public void drawMoney(double money) throws MyException{//取款,发现异常时抛出异常并处理 if(money>this.balance) { throw (new MyException()); } else this.balance=this.balance-money; this.check(); this.setRate(0.05); double interest=0; System.out.println("利息是:"+this.Interest(interest)+"元"); double money1=0; System.out.println("本金加利息是:"+(this.getBalance()+this.Interest(interest))+"元"); } public double Interest(double interest){//计算利息 interest=getRate()*getBalance(); this.interest=interest; return interest; //返回利息 } public double addInterest(double money){//累加利息 money=this.balance+this.interest; return money; } public void check(){ //查询账户信息 int id; String Name; String Add; double Balance; id=getID(); Name=getName(); Add=getAddress(); Balance= getBalance() ; //求账户余额 System.out.println("账号:"+id); System.out.println("姓名:"+Name); System.out.println("地址:"+Add); System.out.println("账户余额:"+Balance+"元"); } } class MyException extends Exception{//自定义异常类 String message; public MyException(){ message="取款数目超过余额,请重新输入取款金额!"; } public String toString(){ return message; } } |
|||
类和对象 | 继承重写 | ||
class Person{ protected String name; protected String addr; protected String sex; protected int age; protected double math; protected double english; public Person(String name,String addr,String sex,int age){ this.name=name; this.addr=addr; this.sex=sex; this.age=age; } public Person(String name,String addr){ this.name=name; this.addr=addr; } public Person(){ } public void put(){ System.out.println(name); System.out.println(addr); System.out.println(sex); System.out.println(age); } } class Student extends Person{ public Student(){} public Student(String name,String addr,String sex,int age,double math,double english){ super(name,addr,sex,age); this.math=math; this.english=english;} public Student(double math,double englist){ this.math=math; this.english=englist; } public void put(){ super.put(); System.out.println(math); System.out.println(english); } } public class TestClass2{ public static void main(String[] args){ Person p=new Person(); p.name="suyixiang"; p.addr="fujianhuian"; p.sex="nan"; p.age=25; p.put(); System.out.println(); System.out.println(); System.out.println(); Student s=new Student(); s.age=23; s.name="wengyijiun"; s.math=92; s.english=91; s.put(); } } |
|||
接口 | 定义一个涨工资的接口类类 | ||
import java.lang.*; interface Add{ //定义一个接口类用来涨工资 public double rice(); } class Person{ //定义一个person类 private String name; private String address; public Person(String name,String address){ this.name=name; this.address=address; } public void setname(String name){ this.name=name; } public String getname(){ return name; } public void setaddress(String address){ this.address=address; } public String getaddress(){ return address; } } class Employee extends Person implements Add{ private String ID; private double wage; private int age; public Employee(String name,String address,String ID,double wage,int age){ super(name,address); this.ID=ID; this.wage=wage; this.age=age; } public void setID(String ID){ this.ID=ID; } public String getID(){ return ID; } public void setwage(double wage){ this.wage=wage; } public double getwage(){ return wage; } public void setage(){ this.age=age; } public int getage(){ return age; } public double rice(){ //重写接口类方法 float i=0.1f; return (this.wage+this.wage*i); } } class Manager extends Employee implements Add{ private String level; public Manager(String name,String address,String ID,double wage,int age,String level){ super(name,address,ID,wage,age); this.level=level; } public String getlevel(){ return level; } public double rice(){ //重写接口类方法 float i=0.2f; return (this.getwage()+this.getwage()*i); } } public class TestInterface{ public static void main(String args[]){ Employee e=new Employee("苏奕祥","福建惠安","122512010045",5000,5); System.out.println("姓名:"+e.getname()); System.out.println("地址:"+e.getaddress()); System.out.println("ID号:"+e.getID()); System.out.println("月工资:"+e.getwage()); System.out.println("工龄:"+e.getage()); System.out.println("一次涨的工资:"+e.rice()); System.out.println("-----------------------------------------"); Manager m=new Manager("黄玉浩","福建漳州","122512010047",7000,8,"总经理"); System.out.println("姓名:"+m.getname()); System.out.println("地址:"+m.getaddress()); System.out.println("ID号:"+m.getID()); System.out.println("月工资:"+m.getwage()); System.out.println("工龄:"+m.getage()); System.out.println("级别:"+m.getlevel()); System.out.println("一次涨的工资:"+m.rice()); } } |
|||
多态 | 类型转换 | ||
import java.io.FileWriter; class A{ void A(){ System.out.println(" *"); } } class B extends A{ void B(){ System.out.println(" ***"); System.out.println(" *****"); } void A(){ System.out.println("*******"); } } public class duotai{ public static void main(String []args){ fun(new A()); fun(new B()); } public static void fun(A a){ if (a instanceof B){ B b=(B)a; b.B(); b.A(); }else{ a.A(); } } } |
|||
多线程 | 银行取款 | ||
/* 用多线程实现以下功能 * author:苏奕祥 #~~~~ * * 假设一个银行的ATM机,它可以允许用户存款也可以取款。现在一个账户上有存款200元,用户A和用户B都拥有在这个账户上存款和取款的权利。用户A将存入100元,而用户B将取出50元,那么最后账户的存款应是250元。实际操作过程如下: (1) 先进行A的存款操作: 1 得到账户的存款数额200,耗时2s。 2 将账户数额增加100,耗时忽略不计 3 将新生成的账户结果300返回到ATM机的服务器上,耗时2s (2) 再进行B的取款操作: 4 得到增加后账户存款数额300,耗时2s。 5 判断取款额是否小于账户余额,若是,则将账户数额减少50,否则抛出异常信息,耗时忽略不计。 6 将新生成的账户结果250返回到ATM机的服务器上,耗时2s。 请根据以上要求,将A的操作和B的操作分别用线程来表示,编写一个Java程序实现该功能。 * 实现一个用户A和用户B 一个存款一个取款 */ import java.util.*; class ATM{ private double money; private static double balance; public ATM(double money){ this.balance=balance+money; } public static void savemoney(double money){ balance=balance+money; } public void setbalance(double balance){ this.balance=balance; } public static double getbalance(){ return balance; } public static void drawmoney(double money) throws MyException{ if(money>balance){ throw (new MyException()); } else balance=balance-money; } public static void check(){ double Balance; Balance=getbalance(); System.out.println("账户余额为:"+Balance); } } class MyException extends Exception{//自定义异常类 String message; public MyException(){ message="取款数目超过余额,请重新输入取款金额!"; } public String toString(){ return message; } } class AA extends Thread{ private String name; private double x; public AA(String name){ this.name=name; } public void run(){ if(this.name=="用户A") { x=100; System.out.println("用户A:输入存款金额:"+x); // Scanner s=new Scanner(System.in); // x=s.nextDouble(); ATM.savemoney(x); System.out.println("执行用户A操作后:"); try{ Thread.sleep(2000); }catch(Exception e){ e.printStackTrace(); } ATM.check(); } } public String getname(){ return name; } } class BB extends Thread{ private String name; double y; public BB(String name){ this.name=name; } public void run(){ if(this.name=="用户B"){ try{ Thread.sleep(5000); }catch(Exception e){ e.printStackTrace(); } y=50; System.out.println("用户B:输入取款金额:"+y); // Scanner s1=new Scanner(System.in); // y=s1.nextDouble(); try { ATM.drawmoney(y); } catch (MyException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("执行用户B操作后:"); try{ Thread.sleep(5000); }catch(Exception e){ e.printStackTrace(); } ATM.check(); } } public void setname(String name){ this.name=name; } public String getname(){ return name; } } public class ThreadTest{ public static void main(String []args)throws MyException{ ATM atm=new ATM(200); System.out.println("当前余额:"+atm.getbalance()); AA aa=new AA("用户A"); BB aaa=new BB("用户B"); aa.start(); aaa.start(); } } |
|||
正则表达式 | 基本测试 | ||
import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegTest { static void test(){ Pattern p=Pattern.compile("LOVE"); Matcher m=p.matcher("I LOVE U I LOVE U I LOVE U"); String str=m.replaceAll("HATE"); System.out.println(str); // Pattern p=Pattern.compile("\\d"); // String str[]=p.split("aa11bbb33cc55gg"); // for(int i=0;i<str.length;i++){ // System.out.println(str[i]); // } // Pattern p=Pattern.compile("\\w(\\d\\d)(\\w+)"); // Matcher m=p.matcher("aa13341bbb"); // if(m.find()){ // int count = m.groupCount(); // System.out.println(m.group()); // for(int i = 0;i<=count;i++){ // System.out.println("group"+i+":"+m.group(i)); // } // } // StringBuffer sb=new StringBuffer(); // while(m.find()){ // m.appendReplacement(sb, "00"); // } // System.out.println(sb.toString()); // m.appendTail(sb); // System.out.println(sb.toString()); // String str=m.replaceAll("XX"); // System.out.println(str); // if(m.find()){ // System.out.println(m.start()); // System.out.println(m.end()); // System.out.println(m.group()); // } // boolean a=m.matches(); // boolean b=m.lookingAt(); // boolean c=m.find(); // System.out.println("matches()匹配结果"+a); // System.out.println("lookingAt()匹配结果"+b); // System.out.println("find()匹配结果"+c); } public static void main(String []args){ test(); } } |
|||
正则表达式2 | 邮箱测试 | ||
import java.util.regex.Matcher; import java.util.regex.Pattern; /* * 邮箱测试 */ public class youxiang { static void test(){ Pattern p=null; Matcher m=null; boolean b=false; p=Pattern.compile( "\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*"); m=p.matcher("469184234@qq.com"); b=m.matches(); System.out.println("enall号码正确:"+b); p=Pattern.compile( "\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*"); m=p.matcher("wser.test.com"); b=m.matches(); System.out.println("enall号码正确:"+b); } public static void main(String args[]){ test(); } } |