总想自己动动手系列·2·本地和外网(Liunx服务器上部署的web项目)按照自定义的报文格式进行交互(完结篇)
一、准备工作
(1)创建一个web-project工程,部署本地可正常访问,部署在云服务上可访问。
(2)理解如何在web.xml文件中配置过滤器,和创建一个自定义的过滤器。
(3)懂得如何打war包,和部署云服务上。
(4)准备相关jar包。
二、本地Java-Project和本地web-Project交互
(1)创建一个web-project工程,需要注意tomcat、jdk、j2ee的版本。本案例用的是:tomcat7.0、jdk1.7.08、j2ee6,版本不兼容,会导致tomcat无法启动。
(2)创建一个请求过滤器。
1 package com.xfwl.filter; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.PrintWriter; 6 import java.util.HashMap; 7 import java.util.Iterator; 8 import java.util.Map; 9 import java.util.Set; 10 import java.util.Map.Entry; 11 12 import javax.servlet.Filter; 13 import javax.servlet.FilterChain; 14 import javax.servlet.FilterConfig; 15 import javax.servlet.ServletException; 16 import javax.servlet.ServletRequest; 17 import javax.servlet.ServletResponse; 18 import javax.servlet.http.HttpServletRequest; 19 import javax.servlet.http.HttpServletResponse; 20 21 import com.xfwl.tool.SecurityUtil; 22 /** 23 * 请求过滤器 24 * @author xfwl 25 * 26 */ 27 public class RequestFilter implements Filter { 28 29 private FilterConfig config = null; 30 @Override 31 public void destroy() { 32 System.out.println("销毁..."); 33 } 34 /** 35 * 开始过滤操作 36 */ 37 @Override 38 public void doFilter(ServletRequest req, ServletResponse resp,FilterChain chain) throws IOException, ServletException { 39 // 强制类型转换 40 HttpServletRequest request = (HttpServletRequest) req; 41 HttpServletResponse response = (HttpServletResponse) resp; 42 // 获取web.xm设置的编码集,设置到Request、Response中 43 request.setCharacterEncoding(config.getInitParameter("charset")); 44 response.setContentType(config.getInitParameter("contentType")); 45 response.setCharacterEncoding(config.getInitParameter("charset")); 46 /** 47 * 解析请求报文 48 */ 49 System.out.println("执行中..."); 50 String miWen=getRequestBody(request); 51 if("".equals(miWen)|| miWen==null){ 52 // 将请求转发到目的地 53 chain.doFilter(request, response); 54 }else{ 55 System.out.println("[密文]"+miWen); 56 StringBuffer MingWen=SecurityUtil.deCioherMsg(miWen,"lvjun"); 57 System.out.println("[明文]"+MingWen); 58 Map<String,Object> recMap=SecurityUtil.parseRecMsgFormat(MingWen.toString()); 59 Set<Entry<String, Object>> set = recMap.entrySet(); 60 Iterator<Entry<String, Object>> it = set.iterator(); 61 System.out.println("----------------------"); 62 while (it.hasNext()) { 63 Entry<String, Object> ey = it.next(); 64 String key = ey.getKey(); 65 String value = (String) ey.getValue(); 66 System.out.println(key+":"+value); 67 } 68 System.out.println("----------------------"); 69 /** 70 * 处理数据并生成响应报文并返回 71 */ 72 Map<String,Object> sendMap =new HashMap<String, Object>(); 73 sendMap.put("RETURN_CODE", "90"); 74 sendMap.put("RETURN_MSG", "交易成功"); 75 StringBuffer sb=SecurityUtil.createMsgFormat(sendMap); 76 StringBuffer finRespData= SecurityUtil.encryptMsg(sb.toString(), "lvjun"); 77 writeResponse(response,finRespData.toString()); 78 } 79 } 80 /** 81 * 获取请求数据 82 * @param req 83 * @return 84 */ 85 private String getRequestBody(HttpServletRequest req) { 86 try { 87 BufferedReader reader = req.getReader(); 88 StringBuffer sb = new StringBuffer(); 89 String line = null; 90 while ((line = reader.readLine()) != null) { 91 sb.append(line); 92 } 93 String json = sb.toString(); 94 return json; 95 } catch (IOException e) { 96 System.out.println("获取请求报文数据失败!"); 97 } 98 return ""; 99 } 100 /** 101 * 输出响应数据 102 * @param response 103 * @param responseString 104 * @throws IOException 105 */ 106 private void writeResponse(ServletResponse response, String responseString) 107 throws IOException { 108 PrintWriter out = response.getWriter(); 109 out.print(responseString); 110 out.flush(); 111 out.close(); 112 } 113 /** 114 * 初始化配置 115 */ 116 @Override 117 public void init(FilterConfig config) throws ServletException { 118 this.config = config; 119 System.out.println("初始化..."); 120 } 121 }
(3)创建一个验证工具类
1 package com.xfwl.tool; 2 3 import java.util.HashMap; 4 import java.util.Iterator; 5 import java.util.List; 6 import java.util.Map; 7 import java.util.Map.Entry; 8 import java.util.Set; 9 10 import org.dom4j.Document; 11 import org.dom4j.DocumentException; 12 import org.dom4j.DocumentHelper; 13 import org.dom4j.Element; 14 15 /** 16 * 数据安全工具 17 * @author Jason 18 * 19 */ 20 public class SecurityUtil { 21 /** 22 * 加密数据 23 */ 24 public static StringBuffer encryptMsg(String data,String encygen) { 25 return new StringBuffer(AESUtil.encrypt(data, encygen)); 26 } 27 /** 28 * 解析数据 29 */ 30 public static StringBuffer deCioherMsg(String data,String deciogen) { 31 return new StringBuffer(AESUtil.decrypt(data, deciogen)); 32 } 33 /** 34 * 生成送报文: 35 * 上送报文和响应报文都需要约定一种报文格式 36 */ 37 public static StringBuffer createMsgFormat(Map<String,Object> dataMap){ 38 StringBuffer msg=new StringBuffer(); 39 msg.append("<service>"); 40 /*msg.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");*/ 41 msg.append("<SYS_HEAD>"); 42 //存放:业务类型码 43 msg.append("<HEAD_BSNCODE>100001</HEAD_BSNCODE>"); 44 msg.append("</SYS_HEAD>"); 45 msg.append("<BODY>"); 46 //存放:业务数据 47 Set<Entry<String, Object>> set = dataMap.entrySet(); 48 Iterator<Entry<String, Object>> it = set.iterator(); 49 while (it.hasNext()) { 50 Entry<String, Object> ey = it.next(); 51 String key = ey.getKey(); 52 String value = (String) ey.getValue(); 53 msg.append("<"+key+">"+value+"</"+key+">"); 54 } 55 msg.append("</BODY>"); 56 msg.append("</service>"); 57 return msg; 58 } 59 /** 60 * 解析响应报文:通过dom4j解析xml字符串 61 * @param args 62 */ 63 public static Map<String,Object> parseRecMsgFormat(String xml){ 64 Map<String,Object> recMap =new HashMap<String, Object>(); 65 Document doc=null; 66 Element root=null; 67 List<Element> elems=null; 68 List<Element> elems_head=null; 69 List<Element> elems_body=null; 70 try { 71 doc=DocumentHelper.parseText(xml); 72 root=doc.getRootElement(); 73 elems=root.elements(); 74 for(Element elem:elems){ 75 //开始解析结点的属性 76 if("SYS_HEAD".equals(elem.getName())){ 77 //检查报文头 78 elems_head=elem.elements(); 79 for(Element head:elems_head){ 80 if("HEAD_BSNCODE".equals(head.getName())){ 81 recMap.put("HEAD_BSNCODE", head.getText()); 82 } 83 } 84 }else if("BODY".equals(elem.getName())){ 85 //检查报文体 86 elems_body=elem.elements(); 87 for(Element body:elems_body){ 88 recMap.put(body.getName(), body.getText()); 89 } 90 } 91 /*List<Attribute> attrs=elem.attributes(); 92 for(Attribute attr:attrs){ 93 //开始解析结点的属性 94 if("HEAD_BSNCODE".equals(attr.getText())){ 95 System.out.println(elem.getName()+":"+elem.getText()); 96 } 97 }*/ 98 } 99 } catch (DocumentException e) { 100 e.printStackTrace(); 101 } 102 return recMap; 103 } 104 }
(4)修改web.xml,配置过滤器
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app version="3.0" 3 xmlns="http://java.sun.com/xml/ns/javaee" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 6 http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> 7 <display-name></display-name> 8 <!-- 默认界面 --> 9 <welcome-file-list> 10 <welcome-file>index.jsp</welcome-file> 11 </welcome-file-list> 12 <!-- 配置过滤器 --> 13 <filter> 14 <filter-name>filter</filter-name> 15 <filter-class>com.xfwl.filter.RequestFilter</filter-class> 16 <init-param> 17 <param-name>charset</param-name> 18 <param-value>UTF-8</param-value> 19 </init-param> 20 <init-param> 21 <param-name>contentType</param-name> 22 <param-value>text/html;charset=UTF-8</param-value> 23 </init-param> 24 </filter> 25 <filter-mapping> 26 <filter-name>filter</filter-name> 27 <!-- * 代表截获所有的请求 或指定请求/test.do /xxx.do --> 28 <url-pattern>/*</url-pattern> 29 </filter-mapping> 30 </web-app>
(5)部署项目并在本地启动tomcat服务
(6)在执行本系列的上一篇中所创建的java-project项目
1 package com.xfwl.message.test; 2 3 import java.net.URLConnection; 4 import java.util.HashMap; 5 import java.util.Map; 6 7 import com.xfwl.message.serverMsg.HTTPServerClient; 8 9 public class TestAction3 { 10 public static void main(String[] args) { 11 Map<String,Object> sendMap =new HashMap<String, Object>(); 12 sendMap.put("ADMIN", "小风微灵"); 13 sendMap.put("PWD", "xfwl123"); 14 15 HTTPServerClient client=new HTTPServerClient(sendMap); 16 URLConnection uc=client.getClient("http://47.105.58.153:8080/ServerClientPro/index.jsp"); 17 //URLConnection uc=client.getClient("http://127.0.0.1:8080/ServerClientPro/test.do"); 18 client.sendDataMsg(uc,"lvjun"); 19 client.receiveDataMsg(uc,"lvjun"); 20 //解析响应报文 21 String recXml="<service><SYS_HEAD><HEAD_BSNCODE>100001</HEAD_BSNCODE></SYS_HEAD><BODY><ADMIN>小风微灵</ADMIN><PWD>xfwl123</PWD></BODY></service>"; 22 client.parseRecMsgFormat(recXml); 23 24 } 25 }
执行结果:
1 建立[http://localhost:8080/ServerClientPro/index.jsp]链接.... 2 发送报文[明文]:<service><SYS_HEAD><HEAD_BSNCODE>100001</HEAD_BSNCODE></SYS_HEAD><BODY><ADMIN>小风微灵</ADMIN><PWD>xfwl123</PWD></BODY></service> 3 发送报文[密文]:oT+IL24P52UJmNyxUWrImyA+HhFpfM6Ho0WBdwD0iH9vhyhwzMZBNXw+9AyMbWQQinmwA5j+vEzV 4 lSSrCiaQEqEuBtP+x+E8Scuzf8hoY6AkHP7la1/HLPjuCJ7qi7QumwZGDcqHayMZGeVO8hk2aAlR 5 KASYGnQaoJNhoiEiu4dpkBIYBXbcrjcKy5xPnSEM 6 7 关闭连接 8 获取返回数据: 9 oT+IL24P52UJmNyxUWrImyA+HhFpfM6Ho0WBdwD0iH9vhyhwzMZBNXw+9AyMbWQQinmwA5j+vEzV 10 lSSrCiaQEnBNbuW52YU4s2iCWx4LO5EYsUx2UfggGP559kQneTznDU9bAM4mmzpBA1PwxHti9M00 11 mkV4+RbTzZl9RpPbjp057Q4Yu9CrA5uxImbr1TOBM6m1cUhDCZAAppCGuAR2KQ== 12 [密文]oT+IL24P52UJmNyxUWrImyA+HhFpfM6Ho0WBdwD0iH9vhyhwzMZBNXw+9AyMbWQQinmwA5j+vEzVlSSrCiaQEnBNbuW52YU4s2iCWx4LO5EYsUx2UfggGP559kQneTznDU9bAM4mmzpBA1PwxHti9M00mkV4+RbTzZl9RpPbjp057Q4Yu9CrA5uxImbr1TOBM6m1cUhDCZAAppCGuAR2KQ== 13 [明文]<service><SYS_HEAD><HEAD_BSNCODE>100001</HEAD_BSNCODE></SYS_HEAD><BODY><RETURN_MSG>交易成功</RETURN_MSG><RETURN_CODE>90</RETURN_CODE></BODY></service> 14 ---------------------- 15 RETURN_MSG:交易成功 16 RETURN_CODE:90 17 HEAD_BSNCODE:100001 18 ----------------------
(7)观察本地web-project项目控制台打印的内容
1 执行中... 2 [密文]oT+IL24P52UJmNyxUWrImyA+HhFpfM6Ho0WBdwD0iH9vhyhwzMZBNXw+9AyMbWQQinmwA5j+vEzVlSSrCiaQEqEuBtP+x+E8Scuzf8hoY6AkHP7la1/HLPjuCJ7qi7QumwZGDcqHayMZGeVO8hk2aAlRKASYGnQaoJNhoiEiu4dpkBIYBXbcrjcKy5xPnSEM 3 [明文]<service><SYS_HEAD><HEAD_BSNCODE>100001</HEAD_BSNCODE></SYS_HEAD><BODY><ADMIN>小风微灵</ADMIN><PWD>xfwl123</PWD></BODY></service> 4 ---------------------- 5 PWD:xfwl123 6 ADMIN:小风微灵 7 HEAD_BSNCODE:100001 8 ----------------------
从上面的打印内容可以得知,web服务器接收到了本期上送的报文,并成功解析处理和作出响应,并且本地java-project也接收到了这种响应。
三、本地Java-Project和云服务器上部署的web-Project交互
(1)将本地的web-project打war包
第一步:导出1
第二步:导出2
第三步:查看war包
由于此时的war包中,并没有j2ee相关的jar包,所以需要找到手动放入到war包中
第四步:找到J2EE相关的Jar包,注意J2EE版本
将Jar包放入war包中
第四步:将该war包上传到云服务上tomcat下的webapps目录下,启动服务
上传war包
启动服务
第五步:本地java-project发出请求报文
1 建立[http://47.105.58.153:8080/ServerClientPro/index.jsp]链接.... 2 发送报文[明文]:<service><SYS_HEAD><HEAD_BSNCODE>100001</HEAD_BSNCODE></SYS_HEAD><BODY><ADMIN>小风微灵</ADMIN><PWD>xfwl123</PWD></BODY></service> 3 发送报文[密文]:oT+IL24P52UJmNyxUWrImyA+HhFpfM6Ho0WBdwD0iH9vhyhwzMZBNXw+9AyMbWQQinmwA5j+vEzV 4 lSSrCiaQEqEuBtP+x+E8Scuzf8hoY6AkHP7la1/HLPjuCJ7qi7QumwZGDcqHayMZGeVO8hk2aAlR 5 KASYGnQaoJNhoiEiu4dpkBIYBXbcrjcKy5xPnSEM 6 7 关闭连接 8 获取返回数据: 9 oT+IL24P52UJmNyxUWrImyA+HhFpfM6Ho0WBdwD0iH9vhyhwzMZBNXw+9AyMbWQQinmwA5j+vEzV 10 lSSrCiaQEnBNbuW52YU4s2iCWx4LO5EYsUx2UfggGP559kQneTznDU9bAM4mmzpBA1PwxHti9M00 11 mkV4+RbTzZl9RpPbjp057Q4Yu9CrA5uxImbr1TOBM6m1cUhDCZAAppCGuAR2KQ== 12 [密文]oT+IL24P52UJmNyxUWrImyA+HhFpfM6Ho0WBdwD0iH9vhyhwzMZBNXw+9AyMbWQQinmwA5j+vEzVlSSrCiaQEnBNbuW52YU4s2iCWx4LO5EYsUx2UfggGP559kQneTznDU9bAM4mmzpBA1PwxHti9M00mkV4+RbTzZl9RpPbjp057Q4Yu9CrA5uxImbr1TOBM6m1cUhDCZAAppCGuAR2KQ== 13 [明文]<service><SYS_HEAD><HEAD_BSNCODE>100001</HEAD_BSNCODE></SYS_HEAD><BODY><RETURN_MSG>交易成功</RETURN_MSG><RETURN_CODE>90</RETURN_CODE></BODY></service> 14 ---------------------- 15 RETURN_MSG:交易成功 16 RETURN_CODE:90 17 HEAD_BSNCODE:100001 18 ----------------------
第六步:查看云服务上的tomcat日志
从上面的日志中,可以看出,服务器是接收到了请求报文,但是却抛出了加密因子数据异常,经过分析和找度娘,知道了原因,是AES获取生成随机加密因子时候,Window系统与Liunx系统的不同造成的。
造成这一现象的代码块是:
1 /** 2 * 生成加密秘钥:window系统和Linux系统环境不同,造成加密因子不统一 3 * @param password 加密因子 4 * @return 5 */ 6 private static SecretKeySpec getSecretKey(final String password) { 7 //返回生成指定算法密钥生成器的 KeyGenerator 对象 8 KeyGenerator kg = null; 9 try { 10 kg = KeyGenerator.getInstance(KEY_ALGORITHM); 11 //AES 要求密钥长度为 128 12 kg.init(128, new SecureRandom(password.getBytes())); 13 //生成一个密钥 14 SecretKey secretKey = kg.generateKey(); 15 16 return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 转换为AES专用密钥 17 } catch (NoSuchAlgorithmException ex) { 18 Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex); 19 } 20 return null; 21 }
修改后的代码
1 /** 2 * 生成加密秘钥:window系统和Linux系统环境不同,造成加密因子不统一 3 * @param password 加密因子 4 * @return 5 */ 6 private static SecretKeySpec getSecretKey2(final String password) { 7 //返回生成指定算法密钥生成器的 KeyGenerator 对象 8 KeyGenerator kg = null; 9 SecureRandom random=null; 10 try { 11 kg = KeyGenerator.getInstance(KEY_ALGORITHM); 12 try { 13 random=SecureRandom.getInstance("SHA1PRNG","SUN"); 14 random.setSeed(password.getBytes()); 15 //AES 要求密钥长度为 128 16 kg.init(128,random); 17 //生成一个密钥 18 SecretKey secretKey = kg.generateKey(); 19 return new SecretKeySpec(secretKey.getEncoded(), KEY_ALGORITHM);// 转换为AES专用密钥 20 } catch (NoSuchProviderException e) { 21 e.printStackTrace(); 22 } 23 } catch (NoSuchAlgorithmException ex) { 24 Logger.getLogger(AESUtil.class.getName()).log(Level.SEVERE, null, ex); 25 } 26 return null; 27 }
代码调整后,重新执行,查看日志有如下:
可见,Window系统和Linux系统造成加密因子的差异性得到了解决。