Java在线支付(利用易宝支付的接口)

随着现在电商等平台如雨后春笋般的发展,在线支付越来越火,各种移动端的支付也是层出不穷,什么微信支付、微博支付等等,其实万变不离其宗,今天大桥就给大家讲解一个Java利用易宝支付在线支付的例子,当然首先要感谢一些传智播客的黎活明老师。 在线支付的第一步,也就是用户在线支付看到的第一个页面,这个页面里主要包含三项:订单号、金额、所选银行,这三个缺一不可。 <%@ page language="java" import="java.util.*" pageEncoding="GBK"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>支付第一步,选择支付银行</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> </head> <body> <table width="960" border="0" align="center"> <tr> <td width="536" valign="top"> <form action="${pageContext.request.contextPath}/servlet/yeepay/PaymentRequestServlet" method="post"name="paymentform"> <table width="100%" border="0"> <tr> <td height="30" colspan="4"> <table width="100%" height="50" border="0" cellpadding="0" cellspacing="1" bgcolor="#A2E0FF"> <tr> <td align="center" bgcolor="#F7FEFF"> <h3>订单号: <INPUT TYPE="text" NAME="orderid"> 应付金额:¥<INPUT TYPE="text" NAME="amount" size="6">元 </h3> </td> </tr> </table> </td> </tr> <tr> <td colspan="4"></td> </tr> <tr> <td height="30" colspan="4" bgcolor="#F4F8FF"> <span class="STYLE3">请您选择在线支付银行</span> </td> </tr> <tr> <td width="26%" height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="CMBCHINA-NET">招商银行 </td> <td width="25%" height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="ICBC-NET">工商银行 </td> <td width="25%" height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="ABC-NET">农业银行 </td> <td width="24%" height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="CCB-NET">建设银行 </td> </tr> <tr> <td height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="CMBC-NET">中国民生银行总行 </td> <td height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="CEB-NET">光大银行 </td> <td height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="BOCO-NET">交通银行 </td> <td height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="SDB-NET">深圳发展银行 </td> </tr> <tr> <td height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="BCCB-NET">北京银行 </td> <td height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="CIB-NET">兴业银行 </td> <td height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="BCCB-NET">北京银行 </td> <td height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="CIB-NET">兴业银行 </td> <td height="25"><INPUT TYPE="radio" NAME="pd_FrpId" value="SPDB-NET">上海浦东发展银行 </td> <td><INPUT TYPE="radio" NAME="pd_FrpId" value="ECITIC-NET">中信银行 </td> </tr> <tr> <td colspan="4"></td> </tr> <tr> <td colspan="4" align="center"> <input type="submit" value=" 确认支付 "/> </td> </tr> </table> </form> </td> <td colspan="2" valign="top"> <div class="divts"> <table width="400" border="0" align="center" cellpadding="5" cellspacing="0"> </table> </div> <div id="blankmessage"></div> </td> </tr> <tr> <td></td> <td width="290"></td> <td width="120"></td> </tr> </table> </body> </html> 取得前台提交的三个参数,并封装易宝支付所需的其他参数,并把这些参数放到Request对象中。 package cn.bridgeli.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import cn.bridgeli.utils.ConfigInfo; import cn.bridgeli.utils.PanymentUtil; /** * 发起支付请求 */ public class PaymentRequestServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { request.setCharacterEncoding("GBK"); String orderid = request.getParameter("orderid");//订单号 String amount = request.getParameter("amount");//支付金额 String pd_FrpId = request.getParameter("pd_FrpId");//选择的支付银行 String p1_MerId = ConfigInfo.getValue("p1_MerId"); String keyValue = ConfigInfo.getValue("keyValue"); String merchantCallbackURL = ConfigInfo.getValue("merchantCallbackURL"); String messageType = "Buy"; // 请求命令,在线支付固定为Buy String currency = "CNY"; // 货币单位 String productDesc = ""; // 商品描述 String productCat = ""; // 商品种类 String productId = ""; // 商品ID String addressFlag = "0"; // 需要填写送货信息 0:不需要 1:需要 String sMctProperties = ""; // 商家扩展信息 String pr_NeedResponse = "0"; // 应答机制 String md5hmac = PanymentUtil.buildHmac(messageType, p1_MerId, orderid, amount, currency, productId, productCat, productDesc, merchantCallbackURL, addressFlag, sMctProperties, pd_FrpId, pr_NeedResponse, keyValue); request.setAttribute("messageType", messageType); request.setAttribute("merchantID", p1_MerId); request.setAttribute("orderId", orderid); request.setAttribute("amount", amount); request.setAttribute("currency", currency); request.setAttribute("productId", productId); request.setAttribute("productCat", productCat); request.setAttribute("productDesc", productDesc); request.setAttribute("merchantCallbackURL", merchantCallbackURL); request.setAttribute("addressFlag", addressFlag); request.setAttribute("sMctProperties", sMctProperties); request.setAttribute("frpId", pd_FrpId); request.setAttribute("pr_NeedResponse", pr_NeedResponse); request.setAttribute("hmac", md5hmac); request.getRequestDispatcher("/WEB-INF/page/connection.jsp").forward(request, response); } } 因为易宝支付所需的数据都是通过表单提交的,所以取得上一步封装的各个参数,通过一个表单提交到易宝支付提供的接口。所以表单的action应该是易宝支付的接口。 <%@ page language="java" pageEncoding="GBK"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>发起支付请求</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> </head> <body onload="javascript:document.forms[0].submit()"> <!-- http://tech.yeepay.com:8080/robot/debug.action --> <form name="yeepay" action="https://www.yeepay.com/app-merchant-proxy/node" method='post'> <input type='hidden' name='p0_Cmd' value="${messageType}"> <!-- 请求命令,在线支付固定为Buy --> <input type='hidden' name='p1_MerId' value="${merchantID}"> <!-- 商家ID --> <input type="hidden" name="p2_Order" value="${orderId}"> <!-- 商家的交易定单号 --> <input type='hidden' name='p3_Amt' value="${amount}"> <!-- 订单金额 --> <input type='hidden' name='p4_Cur' value="${currency}"> <!-- 货币单位 --> <input type='hidden' name='p5_Pid' value="${productId}"> <!-- 商品ID --> <input type='hidden' name='p6_Pcat' value="${productCat}"> <!-- 商品种类 --> <input type='hidden' name='p7_Pdesc' value="${productDesc}"> <!-- 商品描述 --> <input type='hidden' name='p8_Url' value="${merchantCallbackURL}"> <!-- 交易结果通知地址 --> <input type='hidden' name='p9_SAF' value="${addressFlag}"> <!-- 需要填写送货信息 0:不需要 1:需要 --> <input type='hidden' name='pa_MP' value="${sMctProperties}"> <!-- 商家扩展信息 --> <input type='hidden' name='pd_FrpId' value="${frpId}"> <!-- 银行ID --> <!-- 应答机制 为“1”: 需要应答机制;为“0”: 不需要应答机制 --> <input type="hidden" name="pr_NeedResponse" value="0"> <input type='hidden' name='hmac' value="${hmac}"> <!-- MD5-hmac验证码 --> </form> </body> </html> 编写易宝支付处理上一步处理数据完成后所返回的后台处理类(这个处理类必须在公网上,即使是测试程序,即可以访问的),并根据易宝支付所返回的数据,并完成一下几件事(也就是接收易宝支付处理结果的类): (1). 判断支付的结果 ...

September 13, 2014 · 7 分钟 · Bridge Li

动态代理模拟Spring的AOP

这两天研究了一下Java的动态代理,自己闲着无聊,用动态代理模拟了一下Spring的AOP,代码如下,当然真正的Spring是直接操作二进制文件,很复杂,有兴趣的可以自己研究下。 package cn.bridgeli.aop; public interface UserService { void addUser(); } package cn.bridgeli.aop; public class UserServiceImpl implements UserService { public void addUser() { System.out.println("User add..."); } } package cn.bridgeli.aop; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class UserServiceProxy implements InvocationHandler { private UserService userService; public UserServiceProxy(UserService userService) { this.userService = userService; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("User add start..."); Object object = method.invoke(userService, args); System.out.println("User add end..."); return object; } } package cn.bridgeli.aop; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import org.junit.Test; public class UserServiceTest { @Test public void testAddUser() { UserService userService = new UserServiceImpl(); InvocationHandler invocationHandler = new UserServiceProxy(userService); UserService userServiceProxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), invocationHandler); userServiceProxy.addUser(); } }

September 12, 2014 · 1 分钟 · Bridge Li

JXL解析Excel常用方法

目前在市场上有两个最出名的第三方的JAR包:JXL和POI,他们在处理Excel上都有着不俗的表现,但他们有着细微的差别,主要差别如下: JXL在处理数据方面速度比较快,而POI相对较慢,当数据较少时,其实并不明显; JXL对图片的支持更好,而POI对图片的支持稍弱,但对图片也是支持的; JXL对公示的支持能力稍弱,对于复杂的公式显得无能为力,而POI则做得很好,所以如果做财务软件的话,请慎重选择,建议POI,否则很有可能会引起一些意想不到的问题; JXL的代码简单,也易于理解,下面是JXL处理Excel的常用方法(将来有可能的话,我会把POI的也贴出来,供大家参考): import java.io.File; import java.io.IOException; import java.util.Date; import jxl.CellView; import jxl.Sheet; import jxl.Workbook; import jxl.format.Alignment; import jxl.format.Border; import jxl.format.BorderLineStyle; import jxl.format.CellFormat; import jxl.format.Colour; import jxl.format.VerticalAlignment; import jxl.write.Blank; import jxl.write.Boolean; import jxl.write.DateFormat; import jxl.write.DateTime; import jxl.write.Formula; import jxl.write.Label; import jxl.write.Number; import jxl.write.NumberFormat; import jxl.write.WritableCell; import jxl.write.WritableCellFormat; import jxl.write.WritableFont; import jxl.write.WritableSheet; import jxl.write.WritableWorkbook; import jxl.write.WriteException; import jxl.write.biff.RowsExceededException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class JxlHelper { private static final Logger LOG = LoggerFactory.getLogger(JxlHelper.class); private WritableSheet sheet; public JxlHelper(WritableSheet sheet) { this.sheet = sheet; } public JxlHelper() { } public static WritableWorkbook createWritableWorkbook(String filePath) { WritableWorkbook wwb = null; try { wwb = Workbook.createWorkbook(new File(filePath)); } catch (IOException e) { LOG.error("Create Writable Workbook Failed: IOException", e); } return wwb; } public static WritableWorkbook createWritableWorkbook(String filePath, Workbook wb) { WritableWorkbook wwb = null; try { wwb = Workbook.createWorkbook(new File(filePath), wb); } catch (IOException e) { LOG.error("Create Writable Workbook Failed: IOException", e); } return wwb; } public static Workbook getWorkbook(String filePath) throws Exception { Workbook wb = Workbook.getWorkbook(new File(filePath)); return wb; } public void createSheet(WritableWorkbook wwb, String sheetName, int index) { try { wwb.createSheet(sheetName, index); } catch (Exception e) { LOG.error("Create Sheet Failed", e); } } public void copySheet(WritableWorkbook wwb, int copySheetIndex, String pasteSheetName, int pasteSheetIndex) { try { wwb.copySheet(copySheetIndex, pasteSheetName, pasteSheetIndex); } catch (Exception e) { LOG.error("Copy Sheet Failed", e); } } public void copySheet(WritableWorkbook wwb, String copySheetName, String pasteSheetName, int pasteSheetIndex) { try { wwb.copySheet(copySheetName, pasteSheetName, pasteSheetIndex); } catch (Exception e) { LOG.error("Copy Sheet Failed", e); } } public void removeSheet(WritableWorkbook wwb, int index) { try { wwb.removeSheet(index); } catch (Exception e) { LOG.error("Remove Sheet Failed", e); } } public Sheet[] getSheets(WritableWorkbook wwb) { return wwb.getSheets(); } public void setString(int column, int row, String value, int fontSize) throws WriteException { if (value != null) { sheet.addCell(new Label(column, row, value)); } else { sheet.addCell(new Blank(column, row)); } setCellStyle(column, row, fontSize); } public void setString(int column, int row, String value, CellFormat st) throws WriteException { if (value != null) { sheet.addCell(new Label(column, row, value, st)); } else { sheet.addCell(new Blank(column, row, st)); } } public void setNumber(int column, int row, double value, CellFormat st) throws WriteException { sheet.addCell(new Number(column, row, value, st)); } public void setFormatNumber(int column, int row, double value, int fontSize, LocationEnum location, String format) throws WriteException { Number numCell = new Number(column, row, value); sheet.addCell(numCell); WritableFont font = new WritableFont(WritableFont.createFont(SystemConstant.INVOICE_FONT), fontSize, WritableFont.NO_BOLD); NumberFormat numberFormat = null; WritableCellFormat cellFormat = null; if (!StringUtil.isNullOrEmpty(format)) { numberFormat = new NumberFormat(format); cellFormat = new WritableCellFormat(font, numberFormat); } else { cellFormat = new WritableCellFormat(font); } try { cellFormat.setBorder(Border.ALL, BorderLineStyle.THIN); if (location.equals(LocationEnum.LEFT)) { cellFormat.setBorder(Border.LEFT, BorderLineStyle.THICK); } else if (location.equals(LocationEnum.RIGHT)) { cellFormat.setBorder(Border.RIGHT, BorderLineStyle.THICK); } cellFormat.setAlignment(Alignment.RIGHT); cellFormat.setVerticalAlignment(VerticalAlignment.CENTRE); WritableCell writableCell = sheet.getWritableCell(column, row); writableCell.setCellFormat(cellFormat); } catch (WriteException e) { LOG.error("Set Format Number Failed: WriteException", e); } } public void setBoolean(int column, int row, boolean value) throws WriteException { Boolean boolCell = new Boolean(column, row, value); sheet.addCell(boolCell); } public void setFormatDateTime(int column, int row, Date value, String format) throws WriteException { if (value != null) { WritableCell writableCell = sheet.getWritableCell(column, row); CellFormat cf = writableCell.getCellFormat(); DateTime cell = new DateTime(column, row, value); DateFormat dateFormat = new DateFormat(format); WritableCellFormat wcf = new WritableCellFormat(dateFormat); wcf.setFont(new WritableFont(WritableFont.ARIAL)); wcf.setBorder(Border.LEFT, cf.getBorderLine(Border.LEFT)); wcf.setBorder(Border.RIGHT, cf.getBorderLine(Border.RIGHT)); wcf.setAlignment(Alignment.CENTRE); cell.setCellFormat(wcf); sheet.addCell(cell); } } public void setCellStype2(int column, int row) throws WriteException { WritableFont font = new WritableFont(WritableFont.ARIAL, 10, WritableFont.BOLD); WritableCellFormat cellFormat = new WritableCellFormat(font); cellFormat.setBorder(Border.ALL, BorderLineStyle.THIN); cellFormat.setAlignment(Alignment.CENTRE); cellFormat.setVerticalAlignment(VerticalAlignment.CENTRE); WritableCell writableCell = sheet.getWritableCell(column, row); writableCell.setCellFormat(cellFormat); } public void setFormatDateTime(int column, int row, Date value, CellFormat st) throws WriteException { if (value != null) { sheet.addCell(new DateTime(column, row, value, st)); } else { sheet.addCell(new Blank(column, row, st)); } } public void setFormula(int column, int row, String formula) { try { Formula f = new Formula(column, row, formula); sheet.addCell(f); WritableCellFormat cellFormat = new WritableCellFormat(); cellFormat.setAlignment(Alignment.LEFT); cellFormat.setVerticalAlignment(VerticalAlignment.CENTRE); cellFormat.setBorder(Border.ALL, BorderLineStyle.THIN); WritableCell writableCell = sheet.getWritableCell(column, row); writableCell.setCellFormat(cellFormat); } catch (Exception e) { LOG.error("Set Formula Failed", e); } } public void setFormula(int column, int row, String formula, CellFormat st) { try { sheet.addCell(new Formula(column, row, formula, st)); } catch (Exception e) { LOG.error("Set Formula Failed", e); } } public void setCellStyle(int column, int row, int fontSize) { WritableFont font = new WritableFont(WritableFont.ARIAL, fontSize, WritableFont.BOLD); WritableCellFormat cellFormat = new WritableCellFormat(font); try { cellFormat.setAlignment(Alignment.CENTRE); cellFormat.setVerticalAlignment(VerticalAlignment.CENTRE); WritableCell writableCell = sheet.getWritableCell(column, row); writableCell.setCellFormat(cellFormat); } catch (WriteException e) { LOG.error("Set Cell Style Failed: WriteException", e); } } public void setSumCellBorder(int column, int row, LocationEnum location, String format) { NumberFormat nf = null; if (StringUtil.isNotNull(format)) { nf = new NumberFormat(format); } WritableCellFormat cellFormat = new WritableCellFormat(nf); try { cellFormat.setBorder(Border.ALL, jxl.format.BorderLineStyle.THIN); cellFormat.setBorder(Border.TOP, jxl.format.BorderLineStyle.DOUBLE); if (location.equals(LocationEnum.RIGHT)) { cellFormat.setBorder(Border.RIGHT, jxl.format.BorderLineStyle.THICK); } cellFormat.setBorder(Border.BOTTOM, jxl.format.BorderLineStyle.THICK); cellFormat.setAlignment(Alignment.RIGHT); cellFormat.setVerticalAlignment(jxl.format.VerticalAlignment.CENTRE); WritableCell writableCell = sheet.getWritableCell(column, row); writableCell.setCellFormat(cellFormat); } catch (WriteException e) { LOG.error("Set Sum Cell Border Failed: WriteException", e); } } public void setCellStyle(int column, int row) { WritableFont font = new WritableFont(WritableFont.ARIAL); WritableCellFormat cellFormat = new WritableCellFormat(font); try { cellFormat.setAlignment(Alignment.LEFT); cellFormat.setVerticalAlignment(VerticalAlignment.TOP); } catch (WriteException e) { LOG.error("Set Cell Style Failed: WriteException", e); } WritableCell writableCell = sheet.getWritableCell(column, row); writableCell.setCellFormat(cellFormat); } public void hiddenRow(int row) throws RowsExceededException { // sheet.setRowView(row, true); CellView cv = new CellView(); cv.setHidden(true); sheet.setRowView(row, cv); } public void removeRow(int row) { sheet.removeRow(row); } public void insertRow(int row, int height) { sheet.insertRow(row); try { sheet.setRowView(row, height); } catch (RowsExceededException e) { LOG.error("Insert Row Failed: RowsExceededException", e); } } public void mergeCells(int columnStart, int rowsStart, int columnEnd, int rowsEnd) { try { sheet.mergeCells(columnStart, rowsStart, columnEnd, rowsEnd); } catch (RowsExceededException e) { LOG.error("Merge Cells Failed: RowsExceededException", e); } catch (WriteException e) { LOG.error("Merge Cells Failed: WriteException", e); } } public static void close(WritableWorkbook wwb, Workbook wb) { try { if (null != wwb) { wwb.close(); } if (null != wb) { wb.close(); } } catch (WriteException e) { LOG.error("Close WritableWorkbook or Workbook Failed: WriteException", e); } catch (IOException e) { LOG.error("Close WritableWorkbook or Workbook Failed: IOException", e); } } public void setBackgroundColour(int column, int row) { try { WritableCellFormat cellFormat = new WritableCellFormat(); cellFormat.setBackground(Colour.PALE_BLUE); cellFormat.setAlignment(Alignment.LEFT); WritableCell writableCell = sheet.getWritableCell(column, row); writableCell.setCellFormat(cellFormat); } catch (WriteException e) { LOG.error("Set Background Colour Failed: WriteException", e); } } }

September 6, 2014 · 5 分钟 · Bridge Li

Maven Missing artifact解决之道

前几天没事用maven重构自己的微信公众平台开发的代码,当下载一个Jar包时,遇到一个问题:Missing artifact net.sf.json-lib:json-lib:jar:2.2.3,去仓库看,这个Jar包确实没下载下来,因为自己的maven是半路里出家的(自己完全在网上找的一些乱七八糟的资源自学的),所以不知道咋回事,于是就去网上找解决的办法,也许是没找对地方,死活就是解决不了(为避免误导大家,就不列举这些方法了),问同事怎么办,一同事说应该是你下载的时候的网断了之类的导致资源下载了一半,然后网再连上,就不接着下载了,感觉似乎挺有道理,删了还是不行,那是不是网站被和谐了,采用VPN结果还是不行,最后仔细观察,终于发现了一下端倪: 也就是说 <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.2.3</version> </dependency> 对应多个Jar,maven不知道下载那个Jar,所以就报错了,正确的解决方法是加一个标签:,即变成: <dependency> <groupId>net.sf.json-lib</groupId> <artifactId>json-lib</artifactId> <version>2.2.3</version> <classifier>jdk13</classifier> </dependency> 就没问题了。

September 3, 2014 · 1 分钟 · Bridge Li

反射机制入门

Java程序允许在执行期间获取一个已知名称的类的详细内部构造,这种机制被称为“反射”,反射在struts2、Spring、hibernate等Java常见框架中有着许多经典运用,下面是Java反射机制的入门代码,看了这些代码,相信读者应该对Java的反射机制会有一个入门级的了解,再看那些框架源码时会省力不少。 import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.TypeVariable; public class TestReflection { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { String str = "T"; Class c = Class.forName(str); Object o = c.newInstance(); T t = (T) c.newInstance(); t.m(); Method[] methods = c.getMethods(); for (Method method : methods) { if ("m".equals(method.getName())) { method.invoke(o); } if ("getS".equals(method.getName())) { TypeVariable<Method>[] typeParameters = method.getTypeParameters(); Class returnType = method.getReturnType(); } } } } class T { int i; String s; static { System.out.println("T loaded..."); } public T() { System.out.println("T Constructed..."); } public String getS() { return s; } public void setI(int i) { this.i = i; } public void m() { System.out.println("m invoked..."); } }

August 31, 2014 · 1 分钟 · Bridge Li

JSP自定义标签

虽然html很好,尤其是html5越来越火,但仍有很多网站是用JSP做的,JSP里面虽然有很多标签,但我们是否可以自己定义自己的呢?当然可以,参考代码如下: 写自己的taglib类,并重写里面的方法 public class DropDownBoxTaglib extends TagSupport { private static final long serialVersionUID = 1L; @Override public int doStartTag() throws JspTagException { return SKIP_BODY; } @Override public int doEndTag() throws JspTagException { HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); RequestTypeService requestTypeService = (RequestTypeService) applicationContext.getBean("requestTypeService"); List<RequestType> requestTypes = requestTypeService.query(); request.setAttribute("REQUESTTYPES", requestTypes); try { pageContext.include("/component/request_type_select.jsp"); } catch (ServletException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return EVAL_PAGE; } @Override public void release() { super.release(); } } 对应的tld文件 <?xml version="1.0" encoding="UTF-8"?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd" version="2.0"> <tlib-version>1.0</tlib-version> <jsp-version>1.1</jsp-version> <short-name>aug</short-name> <tag> <name>select</name> <tag-class>cn.bridgeli.DropDownBoxTaglib</tag-class> <body-content>empty</body-content> <!-- <attribute> <name>formatKey</name> <required>false</required> <rtexprvalue>true</rtexprvalue> </attribute> --> </tag> </taglib> 具体哪个文件使用该taglib <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <% List<RequestType>requestTypes = (List<RequestType>)request.getAttribute("REQUESTTYPES");%> <select name="requestTypeId" id="requestTypeId" style="width: 608px;"> <option>-Select a request type Please-</option> <% for(int i = 0; i< requestTypes.size(); i++) { RequestType requestType = requestTypes.get(i); %> <option value=<%= requestType.getId() %>><%= requestType.getName() %></option> <% } %> </select>

August 30, 2014 · 1 分钟 · Bridge Li

软件分层的一般方法

1. 软件设计的目的:高内聚、低耦合,为了达到这一目的:(1). 模块化; (2). 分层 软件分层依据:(1). 逻辑分层;(2). 物理分层 命名空间:(1). 类:属性和方法;(2). 包:其实就是一个文件夹 包名命名规范:域名倒写+项目名+逻辑或模块,例如:cn.bridgeli.weixin.service DB Web的死四层结构:view、servlet、service、dao servlet向service传递DTO或者VO,service向DAO传递model,dao直接保存数据到数据库 类的命名规范:实体名+包的最后一层,但model除外 例如:UserService、User 2. 哪些代码写到哪一层 (1). 一个表对应一个model类 (2). 一个表对应一个dao(四个方法) Create、update、getById、delete(可能没有,markfordelete,但依然会这么命名),其他方法一般都以:create、update、delete、get(返回一个对象)、save、find或者query(返回一个list,统一用一个就行)等关键字打头 (3). Service由界面操作的都有service,但log没有service层 (4)servlet接受用户请求 在开发中,不能跨层调用,不能调上层,只能调下层或者本层的方法 (5). Util工具包,所有方法全部是static的,只放一些常用工具,例如StringUtil,检验字符串是否为空、一个字符串是否包含另一个字符串;jdbc中的DBUtil,getConn、getPstmt、getRs以及close等方法

August 30, 2014 · 1 分钟 · Bridge Li

日志的配置

在系统开发中,尤其是上线后,没有日志那绝对是一件不可想象的事,但日志的配置却很简单,一般配置后只要做少量的修改,几乎可以永远到处都可以用了,下面给出日志配置的一般方法。 注:该配置的Jar包为:log4j、slf4j-api、slf-log4j,即使用slf日志接口,log4j的实现(当然你也可以使用其他的实现,例如hibernate自带的slf的实现)这一目前为止的最佳实践。 log4j.rootCategory=INFO, stdout, logfile, errorLog log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %t %c{2}:%L - %m%n #log4j.category.org.springframework.beans.factory=info log4j.appender.consoleAppender.layout.ConversionPattern =ProcessDefinitionId=%X{mdcProcessDefinitionID} executionId=%X{mdcExecutionId} mdcProcessInstanceID=%X{mdcProcessInstanceID} mdcBusinessKey=%X{mdcBusinessKey} %m%n" log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender log4j.appender.logfile.file=C:/invoice/log/log.log log4j.appender.logfile.layout=org.apache.log4j.PatternLayout log4j.appender.logfile.DatePattern='.'yyyy-MM-dd #log4j.appender.logfile.layout.ConversionPattern=[%d %6p at %C.%M(%F:%L)] %m%n log4j.appender.logfile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %l %m%n log4j.appender.logfile.Threshold=INFO log4j.appender.errorLog=org.apache.log4j.DailyRollingFileAppender log4j.appender.errorLog.file=C:/invoice/log/error.log log4j.appender.errorLog.layout=org.apache.log4j.PatternLayout log4j.appender.errorLog.DatePattern='.'yyyy-MM-dd log4j.appender.errorLog.layout.ConversionPattern=[%d %6p at %C.%M(%F:%L)] %m%n log4j.appender.errorLog.Threshold=ERROR # SQL: #log4j.logger.com.ibatis=DEBUG #log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG #log4j.logger.com.ibatis.sqlmap.engine.cache.CacheModel=DEBUG #log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientImpl=DEBUG #log4j.logger.com.ibatis.sqlmap.engine.builder.xml.SqlMapParser=DEBUG #log4j.logger.com.ibatis.common.util.StopWatch=DEBUG #log4j.logger.java.sql.Connection=DEBUG #log4j.logger.java.sql.Statement=DEBUG #log4j.logger.java.sql.PreparedStatement=DEBUG #log4j.logger.java.sql.ResultSet=DEBUG 注:这是一最简单的一种配置,还有很多其他的配置项可以灵活配置,例如打印hibernate的SQL语句,而且还可以配置当产生error级别的日志时,自动发送邮件到指定邮箱,具体请参考:http://futeng.iteye.com/blog/2109231

August 29, 2014 · 1 分钟 · Bridge Li

简单邮件的解析

昨天讲了邮件的发送(这是一个个人笔记,如果有人要参考的话,估计需要做大量的修改才行,但整体逻辑是不会错),既然有发送,肯定会有邮件的解析,那么今天大桥就再写一个例子程序,关于邮件怎么解析。 @Service("parseMailService") public class ParseMailServiceImpl { private static final Logger LOG = LoggerFactory.getLogger(ParseMailServiceImpl.class); private static final String[] flagOfMailEnds = {"<DIV><BR></DIV>", "From:<", "From: <", "Sent: ", "Kind regards,", "Kind Regards,", "Best regards,", "Best Regards,", "Kind regards,", "Regards,", "Thanks", "--- Original Message ---", "> ---", "---"}; private static final String[] flagOfMailStarts = {"Hi,", "</HEAD>"}; private static final String[] regExHtmls = {"<[^>]+>", "<[^>]+"}; @Autowired private MailServerService mailServerService; public void parseMail() throws Exception { LOG.info("==Start parse Mail=="); Session session = mailServerService.getSession(); Store store = session.getStore(“pop3”); store.connect(MAIL_SERVER_HOST, MAIL_ADDRESS, MAIL_SERVER_PASSWORD); Folder folder = store.getFolder("INBOX"); folder.open(Folder.READ_WRITE); Message[] messages = folder.getMessages(); int mailNo = Integer.parseInt((String) execution.getVariable(SystemConstant.MAIL_NO)); Message message = messages[mailNo]; Map<String, String> contents = parseMessage(message); message.setFlag(Flags.Flag.DELETED, true); // message.saveChanges(); mailServerService.closeConn(folder, store); LOG.info("==Mail parse success, this mail from: " + contents.get("user") + "=="); } private String splitContentBySpecialCharacter(String context) { // Remove mail bottom for (String flagOfMailEnd : flagOfMailEnds) { int endIndex = context.indexOf(flagOfMailEnd); if (endIndex > -1) { context = context.substring(0, endIndex); } } // Remove mail top for (String flagOfMailStart : flagOfMailStarts) { int startIndex = context.indexOf(flagOfMailStart); if (startIndex > -1) { context = context.substring(startIndex + flagOfMailStart.length()); } } // Filter the HTML tags for (String regExHtml : regExHtmls) { Pattern p_html = Pattern.compile(regExHtml, Pattern.CASE_INSENSITIVE); Matcher m_html = p_html.matcher(context); context = m_html.replaceAll(""); } context.replaceAll(" ", ""); // Filter "rn" Pattern CRLF1 = Pattern.compile("(rn|r|n|nr){3,}"); Matcher m1 = CRLF1.matcher(context); context = m1.replaceAll(""); Pattern CRLF = Pattern.compile("(rn|r|n|nr)"); Matcher m = CRLF.matcher(context); context = m.replaceAll(" "); return context; } public Map<String, String> parseMessage(Message message) throws MessagingException, IOException { Map<String, String> contents = new HashMap<String, String>(); StringBuffer content = new StringBuffer(300); content = getMailTextContent(message, content); contents.put("comment", splitContentBySpecialCharacter(content.toString())); return contents; } public StringBuffer getMailTextContent(Part part, StringBuffer content) throws MessagingException, IOException { boolean isContainTextAttach = part.getContentType().indexOf("name") > 0; if (part.isMimeType("text/*") && !isContainTextAttach) { if (content.length() > 0) { content.setLength(0); } content.append(part.getContent().toString()); } else if (part.isMimeType("message/rfc822")) { getMailTextContent((Part) part.getContent(), content); } else if (part.isMimeType("multipart/*")) { Multipart multipart = (Multipart) part.getContent(); int partCount = multipart.getCount(); for (int i = 0; i < partCount; i++) { BodyPart bodyPart = multipart.getBodyPart(i); getMailTextContent(bodyPart, content); } } return content; } } @Service("mailServerService") public class MailServerServiceImpl implements MailServerService { private static final Logger LOG = LoggerFactory.getLogger(MailServerServiceImpl.class); @Override public Session getSession() { Properties props = System.getProperties(); props.put("mail.smtp.port", 25); Session session = Session.getDefaultInstance(props); return session; } @Override public void closeConn(Folder folder, Store store) { try { if (null != folder) { folder.close(true); } if (null != store) { store.close(); } } catch (MessagingException e) { LOG.error("Close connection fail with mail server", e); } } }

August 29, 2014 · 2 分钟 · Bridge Li

如何利用模板发送邮件

目前web应用很多时候都需要像用户发送邮件,尤其是在我们注册的时候,其实这些邮件很多时候内容都是类似的,仅仅是一些有户名等不同,那么我们是否可以利用一个模板呢,模板里面有一些占位符,当我们要发送邮件的时候,仅仅把这些占位符做一替换就行了呢?答案肯定是可以的,请看下面的例子程序: 1. 邮件模板mailTemplate.xml <?xml version="1.0" encoding="UTF-8"?> <email> <ProjectMail> <subject id="ProjectSubject"> <![CDATA[Hello%toUsername%]]></subject> <content id="ProjectMailBody"> <![CDATA[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <HTML> <HEAD> <META http-equiv=Content-Type content="text/html; charset=UTF-8"> <META content="MSHTML 6.00.6000.17063" name=GENERATOR> <STYLE> TABLE { margin-left: 20px; } TD { border: 1px solid #CBCBCB; } .dataString { text-align:left; padding-left:3px; } .tableTittle{ background-color: #FF9900; } </STYLE> </HEAD> <BODY bgColor=#ffffff> <DIV> <FONT face=Arial size=2></FONT> </DIV> <DIV> <FONT face=Arial size=2> Hi %name%, </FONT> </DIV> <br> <DIV> <FONT face=Arial size=2> 欢迎注册 </FONT> </DIV> <br> <DIV> <FONT face=Arial size=2> 该邮件是系统自动发出,请不要直接回复,谢谢 </FONT> </DIV> <br> <table width="800" border="1" cellspacing="0" cellpadding="0"> <tr class="tableTittle"> <th width="25%"> <font size="2" face="Arial" class="dataString" > <p align="center"> Name </p> </font> </th> <th width="25%"> <font size="2" face="Arial" class="dataString" > <p align="center"> Date and time </p> </font> </th> </tr> <#listItems></#listItems> </table> <br> <DIV> <FONT face=Arial size=2></FONT> </DIV> <DIV> <FONT face=Arial size=2> Kind regards, </FONT> </DIV> <DIV> <FONT face=Arial size=2> Bridge </FONT> </DIV> </BODY> </HTML> ]]> </content> </ProjectMail> </email> Java代码: @Service("mailService") public class MailServiceImpl implements MailService { private static final Logger LOG = LoggerFactory.getLogger(MailServiceImpl.class); private static final String DO_INVOICE_ITMES ="<#listItems></#listItems>"; private static final String NAME = "%name%"; @Override public void sendMail() { List<String> mailCCList = new ArrayList<String>(); String attachmentPath = null; Map<String, String> mail = buildMail(receiverName); String emailContent = mail.get("mailContent"); String subject = mail.get("emailSubject"); toSendMail(receiverMailAddress, mailCCList, emailContent, subject, attachmentPath, attachmentName); } private void toSendMail(String toAddress, List<String> mailCCList, String emailContent, String subject, String attachmentPath, String attachmentName) { Properties props = new Properties(); // Set the attribute of mail server props.put("mail.smtp.host", MAIL_SERVER_HOST)); // Need to be authorized, such ability through validation (must have this one) props.put("mail.smtp.auth", "true"); // Build a session with props objects Session session = Session.getDefaultInstance(props); // Using the session as parameters define the message object MimeMessage message = new MimeMessage(session); Transport transport = null; try { // Load the sender's address message.setFrom(new InternetAddress(MAIL_ADDRESS)); // Load the recipient address message.addRecipient(Message.RecipientType.TO, new InternetAddress(toAddress)); if (StringUtil.isNotEmpty(mailCCList)) { InternetAddress[] to_mail = new InternetAddress[mailCCList.size()]; for (int i = 0; i < mailCCList.size(); i++) { to_mail[i] = new InternetAddress(mailCCList.get(i)); } message.addRecipients(Message.RecipientType.CC, to_mail); } // Load the subject message.setSubject(subject); // Add mail each part to the multipart, including the text content and accessories MimeMultipart multipart = new MimeMultipart(); // Set the HTML content of the message BodyPart contentPart = new MimeBodyPart(); // To set the content and format/encoding of BodyPart contentPart.setContent(emailContent, "text/html;charset=UTF-8"); multipart.setSubType("related"); multipart.addBodyPart(contentPart); // Add attachment if (!StringUtil.isNullOrEmpty(attachmentName)) { contentPart = new MimeBodyPart(); DataSource source = new FileDataSource(attachmentPath); // Add attachment's content contentPart.setDataHandler(new DataHandler(source)); // Add attachment's title contentPart.setFileName(attachmentName); multipart.addBodyPart(contentPart); } // Add multipart object to the message message.setContent(multipart); // Save the mail message.saveChanges(); transport = session.getTransport("smtp"); // Connect the mail server transport.connect(MAIL_SERVER_HOST, MAIL_SERVER_USERNAME, MAIL_SERVER_PASSWORD); // Send mail transport.sendMessage(message, message.getAllRecipients()); LOG.info("Send mail to: " + toAddress + ",success"); } catch (AddressException e) { LOG.error(e); } catch (NoSuchProviderException e) { LOG.error(e); } catch (MessagingException e) { LOG.error(e); } finally { try { if (null != transport) { transport.close(); } } catch (MessagingException e) { LOG.error(e); } } } private Map<String, String> buildMail(String receiverName) { StringBuilder itemsBuilder = new StringBuilder(); Element emailTemplateRoot = getXMLRootElement("mailTemplate.xml"); String emailSubject = emailTemplateRoot.selectSingleNode("//*[@id='ProjectSubject']").getText().replace(TOUSERNAME, receiverName.toUpperCase()); StringBuilder content = new StringBuilder(); String mailTemplateContent = emailTemplateRoot.selectSingleNode("//*[@id='ProjectMailBody']").getText(); mailTemplateContent = mailTemplateContent.replace(NAME, receiverName).replace(DO_INVOICE_ITMES, itemsBuilder.toString()); content.append(mailTemplateContent); Map<String, String> mail = new HashMap<String, String>(); mail.put("emailSubject", emailSubject); mail.put("mailContent", content.toString()); return mail; } private String getColumnDataString(String data) { String columnData = null; columnData = "<td class='dataString'><font size='2' face='Arial'><p align='center'>" + data + "</p></font></td>" + "n"; return columnData; } private Element getXMLRootElement(String emailFile) { SAXReader reader = new SAXReader(); InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(emailFile); Document document = null; try { document = reader.read(inputStream); } catch (DocumentException e) { LOG.error("Get XML Root Element fail, DocumentException", e); } return document.getRootElement(); } } 2015.05.25补记: ...

August 28, 2014 · 5 分钟 · Bridge Li