-
一、List列表与Set列表的区别 List列表是有序、可以重复、线程不安全的列表,Set是无序、不能重复、线程不安全的列表。但List和Set可以通过方法来转换为线程安全的,加互斥锁。 Set<Long> set=new HashSet<>(); // 转换为线程安全的集合 Collections.synchronizedSet(set); List<Long> lists=new ArrayList<>(); Collections.synchronizedList(lists); 二、List与Set的转换 1) List转换为set List<Long> ids=new ArrayList<>(); HashSet<Long> set=new HashSet<>(ids); 2) Set转换为List HashSet<Long> set=new HashSet<>(); List<Long> ids=new ArrayList<>(set); 此处都可以使用 addAll()方法来替换。 需要注意的是: List转换为Set的时候,当有重复数据时,转换为出现数据丢失的情况,因为Set集合不允许有重复数据。 ———————————————— 原文链接:https://blog.csdn.net/qq_33036061/article/details/103968822
-
1.显示支付二维码 支付流程 首先用户选好商品后 跳到结算页面 在点击支付提交时应先将表单的数据保存到数据库(一般都会有订单表一二级) 经过后台保存数据后再转发到前台(二维码是后台调用微信生成的) 看到扫码页面 当用户扫码成功后 更改订单状态为已支付(一般情况 根据业务定) 开始首先第一步 当用户选好商品后 点击 支付按钮时发送一个请求到后台控制层 让后跳到扫码页面显示商品信息页面 这个页面应该有一个标签 <img src=”请求的控制类地址” /> 注意下面写的方法 就是输出一个二维码 跳到二维码页面img标签会去访问src这个路径方法 让后开始准备 一般会吧微信支付用到的参数封装成一个类,或者properties,xml,yml等等这样的文件(在企业中基本都是后者)这里使用类 方便一些 导入要使用的jar包和工具类 在控制类中加入以下几个工具方法(也可以封装成工具类) /** * 获取本机IP地址 * @return IP */ private static String getRemortIP(HttpServletRequest request) { if (request.getHeader("x-forwarded-for") == null) { return request.getRemoteAddr(); } return request.getHeader("x-forwarded-for"); } /** * 微信支付签名算法sign */ private String getSign(Map<String,Object> map) { StringBuffer sb = new StringBuffer(); String[] keyArr = (String[]) map.keySet().toArray(new String[map.keySet().size()]);//获取map中的key转为array Arrays.sort(keyArr);//对array排序 for (int i = 0, size = keyArr.length; i < size; ++i) { if ("sign".equals(keyArr[i])) { continue; } sb.append(keyArr[i] + "=" + map.get(keyArr[i]) + "&"); } sb.append("key=" + WeixinPayConfig.key); String sign = Md5Util.string2MD5(sb.toString()); return sign; } /** * 通过返回IO流获取支付地址 * @param in * @return */ private String getElementValue(InputStream in,String key){ SAXReader reader = new SAXReader(); Document document=null; try { document = reader.read(in); } catch (DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } Element root = document.getRootElement(); List<Element> childElements = root.elements(); for (Element child : childElements) { System.out.println(child.getName()+":"+child.getStringValue()); if(key.equals(child.getName())){ return child.getStringValue(); } } return null; } /** * 类型转换 * @author chenp * @param matrix * @return */ public static BufferedImage toBufferedImage(BitMatrix matrix) { int width = matrix.getWidth(); int height = matrix.getHeight(); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { image.setRGB(x, y, matrix.get(x, y) == true ? 0xff000000 : 0xFFFFFFFF); } } return image; } 以上方法都要用到 可以封住成一个工具类 由于是演示这里直接放在当前类中了 上面这些弄完后就可以开工了 首先要测试参数 把刚刚复制的 通过返回IO流获取支付地址getElementValue这个方法里的代码注掉 请求的方法里面 有如下代码 String orderNo=DateUtil.getCurrentDateStr(); // 生成订单号(由项目定) Map<String,Object> map=new HashMap<String,Object>(); map.put("appid", WeixinPayConfig.appid); // 公众账号ID(配置文件里的属性) map.put("mch_id", WeixinPayConfig.mch_id); // 商户号(配置文件里的属性) map.put("device_info", WeixinPayConfig.device_info); // 设备号(配置文件里的属性) map.put("notify_url", WeixinPayConfig.notify_url); // 异步通知地址(配置文件里的属性) map.put("trade_type", "NATIVE"); // 交易类型(表示扫码支付 详情看微信公众平台) map.put("out_trade_no", orderNo); // 商户订单号(由项目定) map.put("body", "测试商品"); // 商品描述(由项目定) map.put("total_fee", 100); // 标价金额(单位 '分') // map.put("spbill_create_ip", getRemortIP(request)); // 终端IP(正式环境下用) map.put("spbill_create_ip", "127.0.0.1"); // 终端IP(测试环境) map.put("nonce_str", StringUtil.getRandomString(30)); // 随机字符串(StringUtil工具类提供) map.put("sign", getSign(map)); // 签名(同类中的getSign方法提供) String xml=XmlUtil.genXml(map); //发送xml (XmlUtil工具类提供) System.out.println(xml); // 发现xml消息(由httpclient-4.5.2.jar,httpcore-4.4.9.jar提供) InputStream in=HttpClientUtil.sendXMLDataByPost(WeixinPayConfig.url, xml).getEntity().getContent(); String code_url=getElementValue(in,""); // 获取二维码地址(同类中的getElementValue方法提供) ``` 让后测试看到下面这段就说明成功了(控制台) 如果错误了可以看一下错误原因 成功后在将getElementValue方法里刚刚注掉的代码解注 然后在访问的方法里继续添加代码 String orderNo=DateUtil.getCurrentDateStr(); // 生成订单号(由项目定) Map<String,Object> map=new HashMap<String,Object>(); map.put("appid", WeixinPayConfig.appid); // 公众账号ID(配置文件里的属性) map.put("mch_id", WeixinPayConfig.mch_id); // 商户号(配置文件里的属性) map.put("device_info", WeixinPayConfig.device_info); // 设备号(配置文件里的属性) map.put("notify_url", WeixinPayConfig.notify_url); // 异步通知地址(配置文件里的属性) map.put("trade_type", "NATIVE"); // 交易类型(表示扫码支付 详情看微信公众平台) map.put("out_trade_no", orderNo); // 商户订单号(由项目定) map.put("body", "测试商品"); // 商品描述(由项目定) map.put("total_fee", 100); // 标价金额(单位 '分') // map.put("spbill_create_ip", getRemortIP(request)); // 终端IP(正式环境下用) map.put("spbill_create_ip", "127.0.0.1"); // 终端IP(测试环境) map.put("nonce_str", StringUtil.getRandomString(30)); // 随机字符串(StringUtil工具类提供) map.put("sign", getSign(map)); // 签名(同类中的getSign方法提供) String xml=XmlUtil.genXml(map); //发送xml (XmlUtil工具类提供) System.out.println(xml); // 发现xml消息(由httpclient-4.5.2.jar,httpcore-4.4.9.jar提供) InputStream in=HttpClientUtil.sendXMLDataByPost(WeixinPayConfig.url, xml).getEntity().getContent(); String code_url=getElementValue(in,"code_url"); // 获取二维码地址(同类中的getElementValue方法提供) MultiFormatWriter multiFormatWriter = new MultiFormatWriter(); Map hints = new HashMap(); BitMatrix bitMatrix = null; try { bitMatrix = multiFormatWriter.encode(code_url, BarcodeFormat.QR_CODE, 250, 250,hints); BufferedImage image = toBufferedImage(bitMatrix); //输出二维码图片流 ImageIO.write(image, "png", response.getOutputStream()); } catch (WriterException e1) { e1.printStackTrace(); } 完成后 测试一下 出现二维码就说明成功了 2.异步请求处理 在1中生成的二维码,用户扫描支付后 将会调用公众平台设置的回调地址 接下来根据回调地址来写方法 然后先是拷贝方法 根1一样 封住成工具类或者放在本类 /** * 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 * @return boolean */ public static boolean isTenpaySign(String characterEncoding, SortedMap<Object, Object> packageParams, String API_KEY) { StringBuffer sb = new StringBuffer(); Set es = packageParams.entrySet(); Iterator it = es.iterator(); while(it.hasNext()) { Map.Entry entry = (Map.Entry)it.next(); String k = (String)entry.getKey(); String v = (String)entry.getValue(); if(!"sign".equals(k) && null != v && !"".equals(v)) { sb.append(k + "=" + v + "&"); } } sb.append("key=" + API_KEY); //算出摘要 String mysign = Md5Util.MD5Encode(sb.toString(), characterEncoding).toLowerCase(); String tenpaySign = ((String)packageParams.get("sign")).toLowerCase(); return tenpaySign.equals(mysign); } 然后回调地址的方法里写 //读取参数 InputStream inputStream ; StringBuffer sb = new StringBuffer(); inputStream = req.getInputStream(); String s ; BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); while ((s = in.readLine()) != null){ sb.append(s); } in.close(); inputStream.close(); System.out.println("sb:"+sb.toString()); //解析xml成map Map<String, String> m = new HashMap<String, String>(); try { m = XmlUtil.doXMLParse(sb.toString()); } catch (JDOMException e) { // TODO Auto-generated catch block e.printStackTrace(); } //过滤空 设置 TreeMap SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>(); Iterator<String> it = m.keySet().iterator(); while (it.hasNext()) { String parameter = it.next(); String parameterValue = m.get(parameter); String v = ""; if(null != parameterValue) { v = parameterValue.trim(); } packageParams.put(parameter, v); } // 微信支付的API密钥 String key = WeixinPayConfig.key; if(isTenpaySign("UTF-8", packageParams, key)){ // 验证通过 if("SUCCESS".equals((String)packageParams.get("result_code"))){ System.out.println("验证通过"); }else{ System.out.println("支付失败"); } }else{ System.out.println("验证未通过"); } 在验证通过后更改 订单的状态 为已支付 在编写根据订单查询订单状态的方法 在二维码页面每隔多少秒就调用一次查看状态 若为已支付状态就可以跳转页面了 3.HTML在线支付 环境准备 加入 HMACSHA256Uitl.java 工具类 接口调用url private static String url="https://api.mch.weixin.qq.com/pay/downloadfundflow"; 使用到的工具方法 /** * 微信支付签名算法sign */ private static String getSign(Map<String,Object> map) { StringBuffer sb = new StringBuffer(); String[] keyArr = (String[]) map.keySet().toArray(new String[map.keySet().size()]);//获取map中的key转为array Arrays.sort(keyArr);//对array排序 for (int i = 0, size = keyArr.length; i < size; ++i) { if ("sign".equals(keyArr[i])) { continue; } sb.append(keyArr[i] + "=" + map.get(keyArr[i]) + "&"); } sb.append("key=" + WeixinPayConfig.key); // String sign = Md5Util.string2MD5(sb.toString()); String sign=HMACSHA256Uitl.HMACSHA256(sb.toString().getBytes(), WeixinPayConfig.key.getBytes()); return sign; } 然后编写方法 因为是测试 这里使用的是main 实际根据业务更改 public static void main(String[] args) throws UnsupportedOperationException, ClientProtocolException, IOException { Map<String,Object> map=new HashMap<String,Object>(); map.put("appid", WeixinPayConfig.appid); // 公众账号ID map.put("mch_id", WeixinPayConfig.mch_id); // 商户号 map.put("nonce_str", StringUtil.getRandomString(30)); // 随机字符串 map.put("bill_date", "20180419"); // 资金账单日期 map.put("account_type", "Basic"); // 资金账户类型 map.put("sign", getSign(map)); // 签名 String xml=XmlUtil.genXml(map); System.out.println(xml); InputStream in=HttpClientUtil.sendXMLDataByHttpsPost(url, xml).getEntity().getContent(); // 发现xml消息 StringBuffer out=new StringBuffer(); byte []b=new byte[4096]; for(int n;(n=in.read(b))!=-1;){ out.append(new String(b,0,n)); } System.out.println(out.toString()); } 出现以上结果就成功了 出现报错的话 根据提示 更改参数即可 自行根据以上逻辑嵌入到页面中即可 3.查询订单 创建参数 private static String url="https://api.mch.weixin.qq.com/pay/orderquery"; 写入配置文件里即可 由于是测试 这里写在类中 再添加工具方法(getElementValue这个方法有重载 跟1,2里的不一样) /** * 通过返回IO流获取支付地址 * @param in * @return */ private static void getElementValue(InputStream in){ SAXReader reader = new SAXReader(); Document document=null; try { document = reader.read(in); } catch (DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } Element root = document.getRootElement(); List<Element> childElements = root.elements(); for (Element child : childElements) { System.out.println(child.getName()+":"+child.getStringValue()); } } 这个和2,1中的方法是同一个 /** * 微信支付签名算法sign */ private static String getSign(Map<String,Object> map) { StringBuffer sb = new StringBuffer(); String[] keyArr = (String[]) map.keySet().toArray(new String[map.keySet().size()]);//获取map中的key转为array Arrays.sort(keyArr);//对array排序 for (int i = 0, size = keyArr.length; i < size; ++i) { if ("sign".equals(keyArr[i])) { continue; } sb.append(keyArr[i] + "=" + map.get(keyArr[i]) + "&"); } sb.append("key=" + WeixinPayConfig.key); String sign = Md5Util.string2MD5(sb.toString()); return sign; } 这里直接写的main方法 具体要求根据业务更改 public static void main(String[] args) throws UnsupportedOperationException, ClientProtocolException, IOException { Map<String,Object> map=new HashMap<String,Object>(); map.put("appid", WeixinPayConfig.appid); // 公众账号ID map.put("mch_id", WeixinPayConfig.mch_id); // 商户号 //map.put("transaction_id", "4200000087201804105653326283"); // 微信订单号 map.put("out_trade_no", "20180405055656553"); // 商户订单号(项目生成的订单号) map.put("mch_id", WeixinPayConfig.mch_id); // 商户号 map.put("nonce_str", StringUtil.getRandomString(30)); // 随机字符串 map.put("sign", getSign(map)); // 签名 String xml=XmlUtil.genXml(map); System.out.println(xml); InputStream in=HttpClientUtil.sendXMLDataByPost(url, xml).getEntity().getContent(); // 发现xml消息 getElementValue(in); } 然后运行 看见结果后 就成功了 如果有错误根据错误提示 排错即可 4.关闭订单 创建参数 private static String url="https://api.mch.weixin.qq.com/pay/closeorder"; 写入配置文件里即可 由于是测试 这里写在类中 这里直接写的main方法 具体要求根据业务更改(还是需要3里面的两个方法) public static void main(String[] args) throws UnsupportedOperationException, ClientProtocolException, IOException { Map<String,Object> map=new HashMap<String,Object>(); map.put("appid", WeixinPayConfig.appid); // 公众账号ID map.put("mch_id", WeixinPayConfig.mch_id); // 商户号 map.put("out_trade_no", "20180404022005421"); // 商户订单号 map.put("nonce_str", StringUtil.getRandomString(30)); // 随机字符串 map.put("sign", getSign(map)); // 签名 String xml=XmlUtil.genXml(map); System.out.println(xml); InputStream in=HttpClientUtil.sendXMLDataByPost(url, xml).getEntity().getContent(); // 发现xml消息 getElementValue(in); } 然后运行 看见结果后 就成功了 如果有错误根据错误提示 排错即可 5.申请退款 首先 退款要用到安全证书 在微信公众平台登陆后 在下面下载下载完后放在磁盘内 然后准备工作 将CertUtil.java 导入在工程内(更改里面的安全证书路径,项目中要配置在配置文件中) 接口调用url private static String url="https://api.mch.weixin.qq.com/secapi/pay/refund"; 使用到的工具方法 /** * 通过返回IO流获取支付地址 * @param in * @return */ private static void getElementValue(InputStream in){ SAXReader reader = new SAXReader(); Document document=null; try { document = reader.read(in); } catch (DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } Element root = document.getRootElement(); List<Element> childElements = root.elements(); for (Element child : childElements) { System.out.println(child.getName()+":"+child.getStringValue()); } } /** * 微信支付签名算法sign */ private static String getSign(Map<String,Object> map) { StringBuffer sb = new StringBuffer(); String[] keyArr = (String[]) map.keySet().toArray(new String[map.keySet().size()]);//获取map中的key转为array Arrays.sort(keyArr);//对array排序 for (int i = 0, size = keyArr.length; i < size; ++i) { if ("sign".equals(keyArr[i])) { continue; } sb.append(keyArr[i] + "=" + map.get(keyArr[i]) + "&"); } sb.append("key=" + WeixinPayConfig.key); String sign = Md5Util.string2MD5(sb.toString()); return sign; } public static void main(String[] args) throws UnsupportedOperationException, ClientProtocolException, IOException { Map<String,Object> map=new HashMap<String,Object>(); map.put("appid", WeixinPayConfig.appid); // 公众账号ID map.put("mch_id", WeixinPayConfig.mch_id); // 商户号 map.put("transaction_id", "4200000094201804192059258077"); // 微信订单号 //map.put("out_trade_no", "20180419105343760"); // 商户订单号 map.put("nonce_str", StringUtil.getRandomString(30)); // 随机字符串 map.put("out_refund_no", DateUtil.getCurrentDateStr()); // 商户退款单号 map.put("total_fee", 100); // 订单金额 map.put("refund_fee", 10); // 退款金额 map.put("sign", getSign(map)); // 签名 String xml=XmlUtil.genXml(map); System.out.println(xml); InputStream in=HttpClientUtil.sendXMLDataByHttpsPost(url, xml).getEntity().getContent(); // 发现xml消息 getElementValue(in); } 出现以上结构就成功了 出现报错的话 根据提示 更改参数即可 7 查询退款 接口调用url private static String url="https://api.mch.weixin.qq.com/pay/refundquery "; 使用到的工具方法 /** * 通过返回IO流获取支付地址 * @param in * @return */ private static void getElementValue(InputStream in){ SAXReader reader = new SAXReader(); Document document=null; try { document = reader.read(in); } catch (DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } Element root = document.getRootElement(); List<Element> childElements = root.elements(); for (Element child : childElements) { System.out.println(child.getName()+":"+child.getStringValue()); } } /** * 微信支付签名算法sign */ private static String getSign(Map<String,Object> map) { StringBuffer sb = new StringBuffer(); String[] keyArr = (String[]) map.keySet().toArray(new String[map.keySet().size()]);//获取map中的key转为array Arrays.sort(keyArr);//对array排序 for (int i = 0, size = keyArr.length; i < size; ++i) { if ("sign".equals(keyArr[i])) { continue; } sb.append(keyArr[i] + "=" + map.get(keyArr[i]) + "&"); } sb.append("key=" + WeixinPayConfig.key); String sign = Md5Util.string2MD5(sb.toString()); return sign; } 然后编写方法 因为是测试 这里使用的是main 实际根据业务更改 public static void main(String[] args) throws UnsupportedOperationException, ClientProtocolException, IOException { Map<String,Object> map=new HashMap<String,Object>(); map.put("appid", WeixinPayConfig.appid); // 公众账号ID map.put("mch_id", WeixinPayConfig.mch_id); // 商户号 // map.put("transaction_id", "4200000094201804192059258077"); // 微信订单号 // map.put("out_trade_no", "20180419105343760"); // 商户订单号 // map.put("out_refund_no", "20180427112536831"); // 商户退款单号 map.put("refund_id", "50000506552018042704327042706"); // 微信退款单号 map.put("nonce_str", StringUtil.getRandomString(30)); // 随机字符串 // map.put("offset", 1); // 偏移量 map.put("sign", getSign(map)); // 签名 String xml=XmlUtil.genXml(map); System.out.println(xml); InputStream in=HttpClientUtil.sendXMLDataByPost(url, xml).getEntity().getContent(); // 发现xml消息 getElementValue(in); } 出现报错的话 根据提示 更改参数即可 本文资料+工具类+Demo https://pan.baidu.com/s/1pwnfknFwCLV86aBa3wCQoQ ———————————————— 原文链接:https://blog.csdn.net/u014131617/article/details/85631453
-
1.时间类型的处理中遇到的问题时间类型的参数处理中我们可能会遇到字符串类型的时间参数,可能会遇到Date类型的时间参数,可能会遇到DateTime类型的时间参数,可能会到时间戳类型的时间参数,那么他们之间是如果转换的呢?要怎么样才能获得我们需要的时间类型呢?本文中将进行简单转换介绍。2.转换介绍2.1 字符串类型和DateTime类型的相互转换2.1.1 字符类型转成DateTime类型string startTime="2022-10-29 13:34:35"; DateTime parseTime = DateTime.Parse(startTime); 2.1.2 DateTime类型转成String类型DateTime date = new DateTime(); string format = "YYYY-MM-dd-HH-mm-ss"; string formatStr = date.ToString(format); 2.2 时间戳转换为Date2.2.1 获取当前时间的时间戳在获得当前的时间戳的时候,一般是会获取到毫秒级别的,但是我们一般使用只需要到秒就可以了,所以可以除以1000来获取精确到秒的时间戳。此时我们获取的时间戳是long类型数据,我们使用时常常会进行转换,比如转换成字符串类型的时间戳:String timestamp = String.valueOf(new Date().getTime() / 1000); 将字符串类型的时间戳转换成Integer类型的时间戳:int integer = Integer.valueOf(timestamp);2.2.2 将精确到秒的时间戳转换成Date如果想获取到秒的时间戳需要乘以1000在进行new Date的转换,如果不乘转换出来有可能会造成前面年份变成1970年这种的情况。long longTimeStamp = new Long(new Long(timeStamp) * 1000); Date date = new Date(longTimeStamp); 2.2.3 将Date类型转换为格式化好的字符串类型SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String dareString = simpleDateFormat.format(date); 2.3 LocalDateTime和Date直接的转换因为我们知道Date和SimpleDateFormat类都是线程不安全的,而现在高并发的处理越来越广泛,因此我们开始越来越多的使用LocalDateTime和DateTimeFormatter因为他们都是线程安全的,那么在使用LocalDateTime的时候就会涉及到转换的问题,常遇到的就是LocalDateTime和Date直接的转换,下面我们进行简单的介绍:2.3.1 Date类型和LocalDate之间的转换Date date = new Date(); Instant instant = date.toInstant(); ZoneId zoneId = ZoneId.systemDefault(); LocalDate localDate = instant.atZone(zoneId).toLocalDate(); ZoneId zoneId = ZoneId.systemDefault(); ZonedDateTime zdt = localDate.atStartOfDay().atZone(zoneId); Date date = Date.from(zdt.toInstant());2.3.2 Date类型和LocalDateTime之间的转换Date date = new Date();Instant instant = date.toInstant();ZoneId zoneId = ZoneId.systemDefault();LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();ZoneId zoneId = ZoneId.systemDefault();ZonedDateTime zdt = localDateTime.atZone(zoneId);Date date = Date.from(zdt.toInstant());2.3.3 LocalDateTime转字符串LocalDateTime dt = LocalDateTime.now(); String formatTime = dt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));以上就是时间类型转换中所遇到的各种转换问题的简单整理。
-
↵()↵↵:r↵(),↵1.简介在数据类型的处理过程中我们知道有基础的八大数据类型,还有与其对应的java中帮我们封装好的包装器类。为什么数据类型会分为两种类型呢?原因是Java语言是一种面向对象的语言,这种语言中的一切都是对象(万物皆对象),为了的程序编写的方便我们引入了基本数据类型,但是基础数据类型只是用于数据的存储我们没办法去操作这些基本数据类型,因此我们为了能够将这些基本数据类型转化为对象进行操作,就对八大基本数据类型中的每一种基本数据类型都引入了对应的包装类型,这样我们就能通过基本数据类型的包装器类对其进行操作了,而且从java5开始引入了自动装箱/拆箱机制,使得二者可以互相进行转换转换。2.八大基本数据类型对应的包装器类介绍byte(整数类型 8位1个字节) -->对应的包装器类:Byteshort(整数类型 16位2个字节) -->对应的包装器类: Shortint(整数类型 32位4个字节) -->对应的包装器类:Integerlong(整数类型 64位8个字节) -->对应的包装器类:Longfloat (浮点类型 32位4个字节)-->对应的包装器类:Floatdouble(浮点类型 64位8个字节) -->对应的包装器类:Doublechar (字符类型 2个字节)-->对应的包装器类:Characterboolean(布尔类型 1个字节) -->对应的包装器类:Boolean3.类型转换我们知道基本数据类型和他们对应的包装器类之间是可以转换的,下面我们以int、Integer、long、Long之间的转换为例子:int->long:属于小类型向大类型转换,会自动转换;long->int :属于大类型向小类型转换,需要强制转换;int->Integer :属于基本数据类型向包装数据类型转换,会自动封箱,可以通过直接赋值或者new的方式将其装进去;int->Long :属于基本数据类型向包装数据类型转换,会自动封箱,可以通过直接赋值或者new的方式将其装进去;long->Integer : 可以通过Math.toIntExact(xxx)方法进行转换;long->Long : 属于基本数据类型向包装数据类型转换,会自动封箱,可以通过直接赋值或者new的方式将其装进去;Integer->int : 属于包装数据类型向基本数据类型转换,自动拆箱;Integer->long :属于自动拆箱获取对应int类型数据之后会自动转化为long类型;Integer->Long : 不能强制或直接获取,但是可以通过先转换为int/long基本数据类型,然后再进行转换。Long->int : 包装数据类型向小范围的基本数据类型转换,自动拆箱之后需要强制转换。或者调用获取值得api;Long->long : 包装类型转基本类型,自动拆箱;Long->Integer : 不能强制或直接获取,但是可以通过先转换为int/long基本数据类型,然后再进行转换。以上就是基本数据类型和对应的包装器类之间的简单介绍。
-
一,面向对象介绍 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步- 步实现 ,使用的时候再一个- 一个的依次调用就可以了。 面向对象是把事务分解成为一个个对象,然后由对象之间分工与合作,面向对象编程具有灵活、代码可复用、容易维护和开发的优点 面向对象特性:封装,继承,多态 面向过程 ●优点: 性能比面向对象高,适合跟硬件联系很紧密 的东西,例如单片机就采用的面向过程编程。 ●缺点:没有面向对象易维护、易复用、易扩展。 面向对象 ●优点:易维护、易复用、易扩展,由于面向对象有 封装、继承、多态性的特性,可以设计出低耦合的 系统,使系统更加灵活、更加易于维护 ●缺点: 性能比面向过程低 面向对象的思维特点: 1.抽取(抽象)对象共用的属性和行为组织(封装)成一个类(模板) 2.对类进行实例化,获取类的对象 二,创建生成实例 类construtor 构造函数 constructor()方法是类的构造函数(默认方法) ,用于传递参数返回实例对象,通过new命令生成对象实例时,自动调用该方法。如果没有显示定义类内部会自动给我们创建一 个constructor() (1)通过class关键字创建类,类名习惯性定义首字母大写 (2)类里面的constructor函数,可以接受传递过来的参数,同时返回实例对象 (3)constructor 函数只要new生成实例时,就会自动调用这个函数,即使不写这个函数,类也会自动生成这个函数 (4)生成实例new不能省略 (5)最后注意语法规范,创建类类名后面不要加小括号,生成实例类名后面加小括号,构造函数不需要加function 三,继承 儿子继承父亲的东西 extends 在继承的时候千万不要忘记 extends 哦! 四,super关键字 1.继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的方法 2.继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方发(就近原则) 注意: 利用super 调用父类的构造函数super必须在子类的this之前调用 ———————————————— 版权声明:本文为CSDN博主「Aic山鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/zhaochen1127/article/details/127188794
-
依赖下载 micronaut-data-jdbc-3.8.1 时提示500错误信息。cid:link_0错误信息{"errors":[{"status":500,"message":"DownloadFromCacheAndS3Failed, sha1 is 29398d538f5cb6d84486e6b0658f6e19127f8a47"}]}无法正确的下载改依赖信息,期望能通过华为镜像正常的下载依赖。感谢!!!
-
1. 什么是动态代理? 动态代理是通过创建代理对象,在不改变原有代码的基础上,给程序增加新的功能,实现了程序的功能增强。 2.动态代理的实现方式有几种? JDK动态代理 CGLB动态代理 3. JDK动态代理 使用了JDK中的InvocationHandler接口,Method类和Proxy类。JDK的动态代理的要求:目标类必须要有接口。(目标类就是那个我们需要增强功能的方法所在的那个类,也是接口实现类所在的类)。我们通常回给目标类中要增强的方法增加上日志,事务等非业务功能。 4. CGLB动态代理 CGLB动态代理即Code Generation Library,是一个开源的第三方工具库,其原理是继承,去生成目标类的子类对象,这样对子类的功能进行增强。但是要求:目标类不能用final修饰,目标类中的方法也不能被final修饰。 5.动态代理的效率 CGLB动态代理的效率要大于JDK动态代理的效率。 6.为什么要使用动态代理呢? 设计出来动态代理是为了解决一定的需求,因为在我们实际的开发过程中,经常会遇到,要给写好的某个方法的前面或者是后面增加方法,甚至是给好几个类的方法增加新的功能。若是我们直接在方法上写上新的增加的方法,就会显得很乱,而且很冗余。 那么我们初步改进可以通过写一个工具类去解决,在一个工具类中写上我们要增强的方法,但是要求这些增强的方法是静态修饰的,这样我们就可以在原有的代码上,使用类名.方法名的方式,来给原有的功能增加新的功能。这样一定程度上的解决了代码混乱的程度,但是还是不太完美。 再次改进:这个时候就是使用动态代理。 这就体现了动态代理的优势,即在不修改任何原有代码的情况下,实现给原有功能的增强。 7. JDK动态代理详细使用介绍 由于我们在Java项目中,直接使用动态代理的地方不多,所以我们都是使用的aspectj框架中写好的动态代理。aspectj框架中的动态代理就是封装的JDK动态代理。 下面将仔细介绍使用JDK动态代理的步骤: 最好可以先创建一个工具类,将要增强的功能先写好,这样我们便可以一句代码能调动这个用来增强的功能。 自定义类,去实现InvocationHandler接口,并且,重写invoke()方法。 在这个自定义的类中,添加Objeck属性,并且写上有参的构造方法。 在invoke()方法中写上如下代码 然后去主类中,使用动态代理,实现功能的增强。 注意: 上面的JDK动态代理的原理是反射机制。 我们可以使用proxy.getClass().getName()看到的值为com.sun.proxy.$Proxy ———————————————— 版权声明:本文为CSDN博主「白胡子永远」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_44362089/article/details/127386386
-
ThrowableThrowable 是 Java 语言中所有错误与异常的超类。Throwable 包含两个子类:Error(错误)和 Exception(异常),它们通常用于指示发生了异常情况。Throwable 包含了其线程创建时线程执行堆栈的快照,它提供了 printStackTrace() 等接口用于获取堆栈跟踪数据等信息。Error(错误)定义:Error 类及其子类。程序中无法处理的错误,表示运行应用程序中出现了严重的错误。特点:此类错误一般表示代码运行时 JVM 出现问题。通常有 VirtualMachineError(虚拟机运行错误)、NoClassDefFoundError(类定义错误)等。比如 OutOfMemoryError:内存不足错误;StackOverflowError:栈溢出错误。此类错误发生时,JVM 将终止线程。这些错误是不受检异常,非代码性错误。因此,当此类错误发生时,应用程序不应该去处理此类错误。按照Java惯例,我们是不应该实现任何新的Error子类的!Exception(异常)程序本身可以捕获并且可以处理的异常。Exception 这种异常又分为两类:运行时异常和编译时异常。运行时异常定义:RuntimeException 类及其子类,表示 JVM 在运行期间可能出现的异常。特点:Java 编译器不会检查它。也就是说,当程序中可能出现这类异常时,倘若既"没有通过throws声明抛出它",也"没有用try-catch语句捕获它",还是会编译通过。比如NullPointerException空指针异常、ArrayIndexOutBoundException数组下标越界异常、ClassCastException类型转换异常、ArithmeticExecption算术异常。此类异常属于不受检异常,一般是由程序逻辑错误引起的,在程序中可以选择捕获处理,也可以不处理。虽然 Java 编译器不会检查运行时异常,但是我们也可以通过 throws 进行声明抛出,也可以通过 try-catch 对它进行捕获处理。如果产生运行时异常,则需要通过修改代码来进行避免。例如,若会发生除数为零的情况,则需要通过代码避免该情况的发生!RuntimeException 异常会由 Java 虚拟机自动抛出并自动捕获(就算我们没写异常捕获语句运行时也会抛出错误!!),此类异常的出现绝大数情况是代码本身有问题应该从逻辑上去解决并改进代码。编译时异常定义: Exception 中除 RuntimeException 及其子类之外的异常。特点: Java 编译器会检查它。如果程序中出现此类异常,比如 ClassNotFoundException(没有找到指定的类异常),IOException(IO流异常),要么通过throws进行声明抛出,要么通过try-catch进行捕获处理,否则不能通过编译。在程序中,通常不会自定义该类异常,而是直接使用系统提供的异常类。该异常我们必须手动在代码里添加捕获语句来处理该异常。2.受检异常与非受检异常Java 的所有异常可以分为受检异常(checked exception)和非受检异常(unchecked exception)。受检异常编译器要求必须处理的异常。正确的程序在运行过程中,经常容易出现的、符合预期的异常情况。一旦发生此类异常,就必须采用某种方式进行处理。除 RuntimeException 及其子类外,其他的 Exception 异常都属于受检异常。编译器会检查此类异常,也就是说当编译器检查到应用中的某处可能会此类异常时,将会提示你处理本异常——要么使用try-catch捕获,要么使用方法签名中用 throws 关键字抛出,否则编译不通过。非受检异常编译器不会进行检查并且不要求必须处理的异常,也就说当程序中出现此类异常时,即使我们没有try-catch捕获它,也没有使用throws抛出该异常,编译也会正常通过。该类异常包括运行时异常(RuntimeException极其子类)和错误(Error)
-
一、通用Mapper中的方法解析方法功能说明int countByExample(UserExample example) thorws SQLException按条件计数int deleteByPrimaryKey(Integer id) thorws SQLException按主键删除int deleteByExample(UserExample example) thorws SQLException按条件查询String/Integer insert(User record) thorws SQLException插入数据(返回值为ID)User selectByPrimaryKey(Integer id) thorws SQLException按主键查询List selectByExample(UserExample example) thorws SQLException按条件查询List selectByExampleWithBLOGs(UserExample example) thorws SQLException按条件查询(包括BLOB字段)。只有当数据表中的字段类型有为二进制的才会产生。int updateByPrimaryKey(User record) thorws SQLException按主键更新int updateByPrimaryKeySelective(User record) thorws SQLException按主键更新值不为null的字段int updateByExample(User record, UserExample example) thorws SQLException按条件更新int updateByExampleSelective(User record, UserExample example) thorws SQLException按条件更新值不为null的字段二、Example实例解析mybatis的逆向工程中会生成实例及实例对应的example,example用于添加条件,相当where后面的部分import tk.mybatis.mapper.entity.Example; Example example = new Example(JavaBean.class); Example.Criteria criteria = example.createCriteria();方法说明example.setOrderByClause(“字段名 ASC”);添加升序排列条件,DESC为降序example.setDistinct(false)去除重复,boolean型,true为选择不重复的记录。criteria.andXxxIsNull添加字段xxx为null的条件criteria.andXxxIsNotNull添加字段xxx不为null的条件criteria.andXxxEqualTo(value)添加xxx字段等于value条件criteria.andXxxNotEqualTo(value)添加xxx字段不等于value条件criteria.andXxxGreaterThan(value)添加xxx字段大于value条件criteria.andXxxGreaterThanOrEqualTo(value)添加xxx字段大于等于value条件criteria.andXxxLessThan(value)添加xxx字段小于value条件criteria.andXxxLessThanOrEqualTo(value)添加xxx字段小于等于value条件criteria.andXxxIn(List<?>)添加xxx字段值在List<?>条件criteria.andXxxNotIn(List<?>)添加xxx字段值不在List<?>条件criteria.andXxxLike(“%”+value+”%”)添加xxx字段值为value的模糊查询条件criteria.andXxxNotLike(“%”+value+”%”)添加xxx字段值不为value的模糊查询条件criteria.andXxxBetween(value1,value2)添加xxx字段值在value1和value2之间条件criteria.andXxxNotBetween(value1,value2)添加xxx字段值不在value1和value2之间条件三、使用案例1.查询① selectByPrimaryKey() 按主键查询//相当于:select * from user where id = 100; User user = UserMapper.selectByPrimaryKey(100); ② selectByExample() 和 selectByExampleWithBLOGs()//相当于:select * from user where username = 'wyw' // and username is null order by username asc,email desc UserExample example = new UserExample(); Criteria criteria = example.createCriteria(); criteria.andUsernameEqualTo("wyw"); criteria.andUsernameIsNull(); example.setOrderByClause("username asc,email desc"); Listlist = XxxMapper.selectByExample(example);2.插入数据①insert()//相当于:insert into user(ID,username,password,email) values //('dsfgsdfgdsfgds','jack','1234','hello@126.com'); User user = new User(); user.setId("dsfgsdfgdsfgds"); user.setUsername("jack"); user.setPassword("1234") user.setEmail("hello@163.com"); XxxMapper.insert(user);3.更新数据①updateByPrimaryKey()//相当于:update user set username='rose', password='5678', //email='hello@163.com' where id='a01' User user =new User(); user.setId("a01"); user.setUsername("rose"); user.setPassword("5678"); user.setEmail("hello@163.com"); XxxMapper.updateByPrimaryKey(user);②updateByPrimaryKeySelective()//相当于:update user set password='7890' where id='a01' User user = new User(); user.setId("a01"); user.setPassword("7890"); XxxMapper.updateByPrimaryKey(user);③ updateByExample() 和 updateByExampleSelective()//相当于:update user set password='6666' where username='jack' UserExample example = new UserExample(); Criteria criteria = example.createCriteria(); criteria.andUsernameEqualTo("jack"); User user = new User(); user.setPassword("6666"); XxxMapper.updateByPrimaryKeySelective(user,example);updateByExample()更新所有的字段,包括字段为null的也更新建议使用 updateByExampleSelective()更新想更新的字段4.删除数据①deleteByPrimaryKey()//相当于:delete from user where id=1 XxxMapper.deleteByPrimaryKey(1); ②deleteByExample()//相当于:delete from user where username='jack' UserExample example = new UserExample(); Criteria criteria = example.createCriteria(); criteria.andUsernameEqualTo("jack"); XxxMapper.deleteByExample(example);5.查询数据数量①countByExample()//相当于:select count(*) from user where username='jack' UserExample example = new UserExample(); Criteria criteria = example.createCriteria(); criteria.andUsernameEqualTo("jack"); int count = XxxMapper.countByExample(example);原文链接:https://www.cnblogs.com/tian-ci/p/10543089.html
-
tk.MyBatis常用Mapper接口及Example方法说明一、通用Mapper中的方法解析方法功能说明int countByExample(UserExample example) thorws SQLException按条件计数int deleteByPrimaryKey(Integer id) thorws SQLException按主键删除int deleteByExample(UserExample example) thorws SQLException按条件查询String/Integer insert(User record) thorws SQLException插入数据(返回值为ID)User selectByPrimaryKey(Integer id) thorws SQLException按主键查询List selectByExample(UserExample example) thorws SQLException按条件查询List selectByExampleWithBLOGs(UserExample example) thorws SQLException按条件查询(包括BLOB字段)。只有当数据表中的字段类型有为二进制的才会产生。int updateByPrimaryKey(User record) thorws SQLException按主键更新int updateByPrimaryKeySelective(User record) thorws SQLException按主键更新值不为null的字段int updateByExample(User record, UserExample example) thorws SQLException按条件更新int updateByExampleSelective(User record, UserExample example) thorws SQLException按条件更新值不为null的字段二、Example实例解析mybatis的逆向工程中会生成实例及实例对应的example,example用于添加条件,相当where后面的部分import tk.mybatis.mapper.entity.Example; Example example = new Example(JavaBean.class); Example.Criteria criteria = example.createCriteria();1234方法说明example.setOrderByClause(“字段名 ASC”);添加升序排列条件,DESC为降序example.setDistinct(false)去除重复,boolean型,true为选择不重复的记录。criteria.andXxxIsNull添加字段xxx为null的条件criteria.andXxxIsNotNull添加字段xxx不为null的条件criteria.andXxxEqualTo(value)添加xxx字段等于value条件criteria.andXxxNotEqualTo(value)添加xxx字段不等于value条件criteria.andXxxGreaterThan(value)添加xxx字段大于value条件criteria.andXxxGreaterThanOrEqualTo(value)添加xxx字段大于等于value条件criteria.andXxxLessThan(value)添加xxx字段小于value条件criteria.andXxxLessThanOrEqualTo(value)添加xxx字段小于等于value条件criteria.andXxxIn(List<?>)添加xxx字段值在List<?>条件criteria.andXxxNotIn(List<?>)添加xxx字段值不在List<?>条件criteria.andXxxLike(“%”+value+”%”)添加xxx字段值为value的模糊查询条件criteria.andXxxNotLike(“%”+value+”%”)添加xxx字段值不为value的模糊查询条件criteria.andXxxBetween(value1,value2)添加xxx字段值在value1和value2之间条件criteria.andXxxNotBetween(value1,value2)添加xxx字段值不在value1和value2之间条件使用案例1.查询① selectByPrimaryKey() 按主键查询//相当于:select * from user where id = 100; User user = UserMapper.selectByPrimaryKey(100); 12② selectByExample() 和 selectByExampleWithBLOGs()//相当于:select * from user where username = 'wyw' // and username is null order by username asc,email desc UserExample example = new UserExample(); Criteria criteria = example.createCriteria(); criteria.andUsernameEqualTo("wyw"); criteria.andUsernameIsNull(); example.setOrderByClause("username asc,email desc"); Listlist = XxxMapper.selectByExample(example);123456782.插入数据①insert()//相当于:insert into user(ID,username,password,email) values //('dsfgsdfgdsfgds','jack','1234','hello@126.com'); User user = new User(); user.setId("dsfgsdfgdsfgds"); user.setUsername("jack"); user.setPassword("1234") user.setEmail("hello@163.com"); XxxMapper.insert(user);123456783.更新数据①updateByPrimaryKey()//相当于:update user set username='rose', password='5678', //email='hello@163.com' where id='a01' User user =new User(); user.setId("a01"); user.setUsername("rose"); user.setPassword("5678"); user.setEmail("hello@163.com"); XxxMapper.updateByPrimaryKey(user);12345678②updateByPrimaryKeySelective()//相当于:update user set password='7890' where id='a01' User user = new User(); user.setId("a01"); user.setPassword("7890"); XxxMapper.updateByPrimaryKey(user);12345③ updateByExample() 和 updateByExampleSelective()//相当于:update user set password='6666' where username='jack' UserExample example = new UserExample(); Criteria criteria = example.createCriteria(); criteria.andUsernameEqualTo("jack"); User user = new User(); user.setPassword("6666"); XxxMapper.updateByPrimaryKeySelective(user,example); updateByExample()更新所有的字段,包括字段为null的也更新 建议使用 updateByExampleSelective()更新想更新的字段124.删除数据①deleteByPrimaryKey()//相当于:delete from user where id=1XxxMapper.deleteByPrimaryKey(1);②deleteByExample()//相当于:delete from user where username='jack' UserExample example = new UserExample(); Criteria criteria = example.createCriteria(); criteria.andUsernameEqualTo("jack"); XxxMapper.deleteByExample(example);5.查询数据数量①countByExample()//相当于:select count(*) from user where username='jack' UserExample example = new UserExample(); Criteria criteria = example.createCriteria(); criteria.andUsernameEqualTo("jack"); int count = XxxMapper.countByExample(example);原文链接:https://blog.csdn.net/qq_33578833/article/details/104531530
-
1.准备工作 移动应用微信登录是基于OAuth2.0协议标准 构建的微信OAuth2.0授权登录系统。 在进行微信OAuth2.0授权登录接入之前,在微信开放平台注册开发者帐号,并拥有一个已审核通过的移动应用,并获得相应的AppID和AppSecret,申请微信登录且通过审核后,可开始接入流程。 2.授权流程说明 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数; 通过code参数加上AppID和AppSecret等,通过API换取access_token; 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。 3. 获取access_token时序图 4. maven依赖 commons-httpclient commons-httpclient 3.0.1 org.springframework.boot spring-boot-devtools org.apache.commons commons-io 1.3.2 org.apache.commons commons-lang3 3.4 org.apache.httpcomponents httpclient 4.3.2 com.alibaba fastjson 1.2.38 5.在application.yml文件中配置你的 #第三方微信登录(用你自己的) #appID App的ID #appSecret weixinconfig: weixinappID: wxf7865421a3c4d5f weixinappSecret: 6cdbe6d4ce6sbcf0593c913d8a0ce12 创建配置类 import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Component @ConfigurationProperties(prefix="weixinconfig") public class WeixinLoginProperties { private String weixinappID; // 商户appid private String weixinappSecret; // 私钥 pkcs8格式的 public String getWeixinappID() { return weixinappID; } public void setWeixinappID(String weixinappID) { this.weixinappID = weixinappID; } public String getWeixinappSecret() { return weixinappSecret; } public void setWeixinappSecret(String weixinappSecret) { this.weixinappSecret = weixinappSecret; } } 6.第一步:请求CODE 这一步客户端会把code传过来 ,不用你操心 7.第二步:通过code获取access_token package io.renren.api.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.configurationprocessor.json.JSONException; import org.springframework.boot.configurationprocessor.json.JSONObject; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import io.renren.api.dao.TpAccesstokenMapper; import io.renren.api.dao.TpUsersMapper; import io.renren.api.entity.TpAccesstoken; import io.renren.api.entity.TpAccesstokenExample; import io.renren.api.entity.TpAccumulativeAward; import io.renren.api.entity.TpUsers; import io.renren.api.entity.TpUsersExample; import io.renren.api.properties.WeixinLoginProperties; import io.renren.api.service.TpAccesstokenService; import io.renren.api.service.TpAccumulativeAwardService; import io.renren.api.service.TpUsersService; import io.renren.common.utils.R; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.math.BigDecimal; import java.net.URI; import java.util.List; import javax.annotation.Resource; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; /** * 第三方微信登录 * @author Administrator * */ @SuppressWarnings("deprecation") @Controller @RequestMapping("/api") public class WeXinController { //微信公众平台申请 //应用唯一标识,在微信开放平台提交应用审核通过后获得 appID //应用密钥AppSecret,在微信开放平台提交应用审核通过后获得 appSecret //TpAccesstoken 用来保存微信返回的用户信息oppid等 @Resource private WeixinLoginProperties weixinLoginProperties; @Autowired TpUsersService tpUsersService; @Autowired TpUsersMapper tpUsersMapper; @Autowired TpAccesstokenService tpAccesstokenService; @Autowired TpAccesstokenMapper tpAccesstokenMapper; @Autowired TpAccumulativeAwardService tpAccumulativeAwardService; /** * 获取accessToken,该步骤返回的accessToken期限为一个月 * * @param code * @return * @throws Exception */ @SuppressWarnings("all") @RequestMapping("weixincallback") @ResponseBody public R getAccessToken(String code) throws Exception { String appID = weixinLoginProperties.getWeixinappID(); String appSecret = weixinLoginProperties.getWeixinappSecret(); String accesstoken; String openid = null; String refreshtoken; int expiresIn; String unionid;//可通过获取用户基本信息中的unionid来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号, //用户的unionid是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid是相同的。 if (code != null) { System.out.println(code); } String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+appID+"&secret="+appSecret+"&code="+code+"&grant_type=authorization_code"; URI uri = URI.create(url); org.apache.http.client.HttpClient client = new DefaultHttpClient(); HttpGet get = new HttpGet(uri); HttpResponse response; try { response = client.execute(get); if (response.getStatusLine().getStatusCode() == 200) { HttpEntity entity = response.getEntity(); BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8")); StringBuilder sb = new StringBuilder(); for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) { sb.append(temp); } JSONObject object = new JSONObject(sb.toString().trim()); System.out.println("object:"+object); accesstoken = object.getString("access_token"); System.out.println("accesstoken:"+accesstoken); openid = object.getString("openid"); System.out.println("openid:"+openid); refreshtoken = object.getString("refresh_token"); System.out.println("refreshtoken:"+refreshtoken); expiresIn = (int) object.getLong("expires_in"); unionid = object.getString("unionid"); // 将用户信息保存到数据库 //1.先查询用户是否是第一次第三方登录如果是第一次那么是将用户信息添加到数据库 如果不是那么是更新到数据库 TpUsers userInfo = getUserInfo(accesstoken,openid); Integer userId = userInfo.getUserId(); TpAccesstokenExample example = new TpAccesstokenExample(); example.createCriteria().andOpenidEqualTo(openid); List list = tpAccesstokenMapper.selectByExample(example); if(list!=null&&list.size()>0) { //那么该用户不是第一次 执行更新操作 TpAccesstoken tpAccesstoken = list.get(0); tpAccesstoken.setAccesstoken(accesstoken); tpAccesstoken.setUserId(userId); tpAccesstoken.setExpiresIn(expiresIn); tpAccesstoken.setOpenid(openid); tpAccesstoken.setRefreshtoken(refreshtoken); tpAccesstokenService.save(tpAccesstoken); }else { TpAccesstoken tpAccesstoken=new TpAccesstoken(); tpAccesstoken.setUserId(userId); tpAccesstoken.setAccesstoken(accesstoken); tpAccesstoken.setExpiresIn(expiresIn); tpAccesstoken.setOpenid(openid); tpAccesstoken.setRefreshtoken(refreshtoken); tpAccesstokenService.save(tpAccesstoken); //tpAccesstokenService.insertAccesstoken(userId,openid, accesstoken, expiresIn, refreshtoken); } //refreshAccessToken(openid); System.out.println("Openid"+userInfo.getOpenid()); return R.ok().put("userInfo", userInfo).put("openid", openid); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } return R.ok().put("openid", openid); } /* * * 1 { 2 "access_token":"ACCESS_TOKEN", 3 "expires_in":7200, 4 * "refresh_token":"REFRESH_TOKEN", 5 "openid":"OPENID", 6 "scope":"SCOPE", 7 * "unionid":"o6_bmasdasdsad6_2sgVt7hMZOPfL" 8 } 复制代码 复制代码 参数 说明 access_token * 接口调用凭证 expires_in access_token 接口调用凭证超时时间,单位(秒) refresh_token * 用户刷新access_token openid 授权用户唯一标识 scope 用户授权的作用域,使用逗号(,)分隔 unionid * 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。 * */ /** * 刷新token * * @param openID * @return */ @SuppressWarnings({ "unused", "resource" }) private void refreshAccessToken(String openid) { String refreshtoken=null; TpAccesstoken tpAccesstoken=new TpAccesstoken(); String appID = weixinLoginProperties.getWeixinappID(); String appSecret = weixinLoginProperties.getWeixinappSecret(); TpAccesstokenExample example = new TpAccesstokenExample(); example.createCriteria().andOpenidEqualTo(openid); List list = tpAccesstokenMapper.selectByExample(example); if(list!=null&&list.size()>0) { tpAccesstoken = list.get(0); refreshtoken = tpAccesstoken.getRefreshtoken(); } String uri = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid="+appID+"&grant_type=refresh_token&refresh_token="+refreshtoken; org.apache.http.client.HttpClient client = new DefaultHttpClient(); HttpGet get = new HttpGet(URI.create(uri)); try { HttpResponse response = client.execute(get); if (response.getStatusLine().getStatusCode() == 200) { BufferedReader reader = new BufferedReader( new InputStreamReader(response.getEntity().getContent(), "UTF-8")); StringBuilder builder = new StringBuilder(); for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) { builder.append(temp); } JSONObject object = new JSONObject(builder.toString().trim()); String accessToken = object.getString("access_token"); String refreshToken = object.getString("refresh_token"); openid = object.getString("openid"); int expires_in = (int) object.getLong("expires_in"); tpAccesstoken.setAccesstoken(accessToken); tpAccesstoken.setExpiresIn(expires_in); tpAccesstoken.setOpenid(openid); tpAccesstoken.setRefreshtoken(refreshToken); tpAccesstokenService.save(tpAccesstoken); } } catch (ClientProtocolException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 根据accessToken获取用户信息 * * @param accessToken * @param openID * @return * @throws Exception */ @SuppressWarnings({ "unused", "resource" }) public TpUsers getUserInfo(String accessToken, String openID) throws Exception { String appID = weixinLoginProperties.getWeixinappID(); String appSecret = weixinLoginProperties.getWeixinappSecret(); String uri = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openID; org.apache.http.client.HttpClient client = new DefaultHttpClient(); HttpGet get = new HttpGet(URI.create(uri)); try { HttpResponse response = client.execute(get); if (response.getStatusLine().getStatusCode() == 200) { BufferedReader reader = new BufferedReader( new InputStreamReader(response.getEntity().getContent(), "UTF-8")); StringBuilder builder = new StringBuilder(); for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) { builder.append(temp); } JSONObject object = new JSONObject(builder.toString().trim()); String country = object.getString("country"); String nikeName = object.getString("nickname"); String unionid = object.getString("unionid"); String province = object.getString("province"); String city = object.getString("city"); String openid = object.getString("openid"); String sex = object.getString("sex"); String headimgurl = object.getString("headimgurl"); String language = object.getString("language"); BigDecimal bigDecimal=new BigDecimal(0.0); TpUsersExample example=new TpUsersExample(); example.createCriteria().andOpenidEqualTo(openid); List list = tpUsersMapper.selectByExample(example); if(list!=null&&list.size()>0) { TpUsers tpUsers = list.get(0); System.out.println("---------"); return tpUsers; }else { TpUsers tpUsers=new TpUsers(); tpUsers.setOauth("wx"); tpUsers.setOpenid(openid); tpUsers.setUnionid(unionid); tpUsers.setUserName(nikeName); tpUsers.setUserMoney(bigDecimal); tpUsersService.save(tpUsers); System.out.println("+++++++"); return tpUsers; } } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } return null; } @RequestMapping("/isaccesstoken") @SuppressWarnings({ "resource" }) private boolean isAccessTokenIsInvalid(String accessToken,String openID) { String url = "https://api.weixin.qq.com/sns/auth?access_token=" + accessToken + "&openid=" + openID; URI uri = URI.create(url); org.apache.http.client.HttpClient client = new DefaultHttpClient(); HttpGet get = new HttpGet(uri); HttpResponse response; try { response = client.execute(get); if (response.getStatusLine().getStatusCode() == 200) { HttpEntity entity = response.getEntity(); BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8")); StringBuilder sb = new StringBuilder(); for (String temp = reader.readLine(); temp != null; temp = reader.readLine()) { sb.append(temp); } JSONObject object = new JSONObject(sb.toString().trim()); /* { "errcode":0,"errmsg":"ok" } 错误的Json返回示例: { "errcode":40003,"errmsg":"invalid openid" }*/ int errorCode = object.getInt("errcode"); if (errorCode == 0) { return true; } } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } return false; } } 获取第一步的code后,请求以下链接进行refresh_token: https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN 参数说明 参数 是否必须 说明 appid 是 应用唯一标识 grant_type 是 填refresh_token refresh_token 是 填写通过access_token获取到的refresh_token参数 返回说明 正确的返回: { "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" } 参数 说明 access_token 接口调用凭证 expires_in access_token接口调用凭证超时时间,单位(秒) refresh_token 用户刷新access_token openid 授权用户唯一标识 scope 用户授权的作用域,使用逗号(,)分隔 错误返回样例: {"errcode":40030,"errmsg":"invalid refresh_token"} 刷新或续期access_token使用 接口说明 access_token是调用授权关系接口的调用凭证,由于access_token有效期(目前为2个小时)较短,当access_token超时后,可以使用refresh_token进行刷新,access_token刷新结果有两种: 1.若access_token已超时,那么进行refresh_token会获取一个新的access_token,新的超时时间; 2.若access_token未超时,那么进行refresh_token不会改变access_token,但超时时间会刷新,相当于续期access_token。 refresh_token拥有较长的有效期(30天)且无法续期,当refresh_token失效的后,需要用户重新授权后才可以继续获取用户头像昵称。 请求方法 使用/sns/oauth2/access_token接口获取到的refresh_token进行以下接口调用: http请求方式: GET https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN 参数说明 参数 是否必须 说明 appid 是 应用唯一标识 grant_type 是 填refresh_token refresh_token 是 填写通过access_token获取到的refresh_token参数 返回说明 正确的返回: { "access_token":"ACCESS_TOKEN", "expires_in":7200, "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" } 参数 说明 access_token 接口调用凭证 expires_in access_token接口调用凭证超时时间,单位(秒) refresh_token 用户刷新access_token openid 授权用户唯一标识 scope 用户授权的作用域,使用逗号(,)分隔 错误返回样例: { "errcode":40030,"errmsg":"invalid refresh_token" } 获取用户个人信息(UnionID机制) 接口说明 此接口用于获取用户个人信息。开发者可通过OpenID来获取用户基本信息。特别需要注意的是,如果开发者拥有多个移动应用、网站应用和公众帐号,可通过获取用户基本信息中的unionid来区分用户的唯一性,因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号,用户的unionid是唯一的。换句话说,同一用户,对同一个微信开放平台下的不同应用,unionid是相同的。请注意,在用户修改微信头像后,旧的微信头像URL将会失效,因此开发者应该自己在获取用户信息后,将头像图片保存下来,避免微信头像URL失效后的异常情况。 请求说明 http请求方式: GET https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID 参数说明 参数 是否必须 说明 access_token 是 调用凭证 openid 是 普通用户的标识,对当前开发者帐号唯一 lang 否 国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语,默认为zh-CN 返回说明 正确的Json返回结果: { "openid":"OPENID", "nickname":"NICKNAME", "sex":1, "province":"PROVINCE", "city":"CITY", "country":"COUNTRY", "headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0", "privilege":[ "PRIVILEGE1", "PRIVILEGE2" ], "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL" } 参数 说明 openid 普通用户的标识,对当前开发者帐号唯一 nickname 普通用户昵称 sex 普通用户性别,1为男性,2为女性 province 普通用户个人资料填写的省份 city 普通用户个人资料填写的城市 country 国家,如中国为CN headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空 privilege 用户特权信息,json数组,如微信沃卡用户为(chinaunicom) unionid 用户统一标识。针对一个微信开放平台帐号下的应用,同一用户的unionid是唯一的。 建议: 开发者最好保存unionID信息,以便以后在不同应用之间进行用户信息互通。 错误的Json返回示例: { "errcode":40003,"errmsg":"invalid openid" } 工具类 package io.renren.common.utils; import java.util.HashMap; import java.util.Map; /** * 返回数据 * * @author chenshun * @email sunlightcs@gmail.com * @date 2016年10月27日 下午9:59:27 */ public class R extends HashMap { private static final long serialVersionUID = 1L; public R() { put("code", 0); put("msg", "success"); } public static R error() { return error(500, "未知异常,请联系管理员"); } public static R error(String msg) { return error(500, msg); } public static R error(int code, String msg) { R r = new R(); r.put("code", code); r.put("msg", msg); return r; } public static R ok(String msg) { R r = new R(); r.put("msg", msg); return r; } public static R ok(Map map) { R r = new R(); r.putAll(map); return r; } public static R ok() { return new R(); } @Override public R put(String key, Object value) { super.put(key, value); return this; } } 原文链接:https://blog.csdn.net/weixin_42694286/article/details/84344786
-
一、前言 我在网上找了很多关于识别一维码和二维码的资料,总结一下,手机端目前能找到ZXing,ZBar都只能支持单个一维码,单个和多个二维码的识别,当图片有二维码和一维码同时存在,也只能识别二维码,而且ZXing还在持续更新中,所以最好的选择是ZXing。二、代码和使用/*** 扫描的工具类-------一维码二维码(识别图片)* **/public class BarcodeUtil {/**** 获取图片的一维码----目前只支持一个条形码 filename --图片的绝对路径* */public static String getOneBarcode(String filename, Context context) {String onebarcode = "";Bitmap img = BitmapUtils.getCompressedBitmap(filename);BitmapDecoder decoder = new BitmapDecoder(context);Result result = decoder.getRawResult(img);String resP = "";if (result != null&& codeType(DecodeFormatManager.ONE_D_FORMATS,result.getBarcodeFormat())) {resP = "|" + result.getResultPoints()[1].getX() + "|"+ result.getResultPoints()[1].getY() + "|";onebarcode = result.getText() + resP;}return onebarcode;}/**** 获取图片的二维码----目前可支持多个二维码 filename --图片的绝对路径* */public static String getTwoBarcode(String filename) {String twobarcode = "";Bitmap img = BitmapUtils.getCompressedBitmap(filename);int[] intArray = new int[img.getWidth() * img.getHeight()];img.getPixels(intArray, 0, img.getWidth(), 0, 0, img.getWidth(),img.getHeight());LuminanceSource source = new RGBLuminanceSource(img.getWidth(),img.getHeight(), intArray);BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));QRCodeMultiReader odecoder = new QRCodeMultiReader();Result[] results;String resP = "";try {results = odecoder.decodeMultiple(bitmap);if (results != null) {for (Result result2 : results) {if (result2 != null&& codeType(DecodeFormatManager.QR_CODE_FORMATS,result2.getBarcodeFormat())) {resP = "|" + result2.getResultPoints()[1].getX() + "|"+ result2.getResultPoints()[1].getY() + "|";twobarcode += result2.getText() + resP;}}}} catch (NotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}return twobarcode;}/**** 确认扫描的** */private static boolean codeType(final Collection type,BarcodeFormat barcodeFormat) {for (BarcodeFormat barcode : type) {if (barcodeFormat.equals(barcode)) {return true;}}return false;}}说明 :我这个同时返回了一维码或二维码包含的信息还有它所在位置的左上角的那个坐标点。(result.getResultPoints()[1].getX() +result.getResultPoints()[1].getY() 这是左上角那个点的坐标) 一维码只返回两个坐标,二维码返回了4个,根据你的需要去取。重点说明:对多个二维码的识别,需要使用QRCodeMultiReader去识别,很多地方找不到这个类的具体使用方法,你需要下载一个比较新版本的ZXing包,里面才有这方法。其他相关的一些工具类,你也可以在对应的里面找到。因为关于ZXing的使用很容易在GitHub等地方找到demo,但是对多个扫描的二维码的识别就基本没有使用的例子,使用的方法都提供了,但没有直接的使用总结,所以我这里贴的就是我的一个简单的使用和说明,希望可以帮到你。原文链接:https://juejin.cn/post/6844903549487284238
-
公司是做广告服务的,运转模式一句话就是:在车内设备上播放广告主投放的广告,并获取收益,现在有个需求是,要统计广告主投放的广告里面的二维码的扫码量,进行数据分析,为后面人物画像做准备,因多种事业环境因素,让广告主提供统计数据或者提供链接给我们,我们生成二维码等,根本不太可能,所以,只能自己撸启袖子干! 我疏导了下流程,如下: 1.广告审核的时候,判断图片是否包含二维码 2.包含二维码的图片,对原图片里面二维码进行识别并定位 3.获取原图片里二维码的信息和坐标信息(x,y,w,h),并保存起来 4.开发一个接口,这个接口可以理解为新二维码的链接路径 5.根据坐标使用上面接口如(www.abc?taskId=10&imei=2ej3dd)生成新二维码并推送到设备 6.设备获取推送的包含二维码的图片并根据后台分发的坐标信息生成新的二维码 7.设备根据坐标和其他需要携带的参数生成新二维码 8.用户扫码跳转到接口路径,接口获得相关参数记录扫码量并重定向到原图片里面二维码路径 至此,大功告成! 一个东西的技术实现,都是站在前人的肩膀上去累积,优化,总结的,我大概在网上看了下,貌似没有人遇到这种需求,参考了opencv java版本的代码,毕竟不是做图像识别的,这方面的知识有限,所以用了zxing实现.于是自己硬着头皮上,基本实现了我们的业务需求,但,二维码的坐标识别还是有些许的差别,还是把代码分享出来,起抛砖引玉的作用,同时,也希望大家能够在这个基础上进行优化... 以下为代码片段 先加入maven依赖: com.google.zxing core 3.3.3 com.google.zxing javase 3.3.3 下面为完整java代码: package com.bpb.qrcode; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import javax.imageio.ImageIO; import com.google.zxing.Binarizer; import com.google.zxing.BinaryBitmap; import com.google.zxing.DecodeHintType; import com.google.zxing.EncodeHintType; import com.google.zxing.LuminanceSource; import com.google.zxing.MultiFormatReader; import com.google.zxing.NotFoundException; import com.google.zxing.Result; import com.google.zxing.ResultPoint; import com.google.zxing.client.j2se.BufferedImageLuminanceSource; import com.google.zxing.common.HybridBinarizer; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import lombok.extern.slf4j.Slf4j; @Slf4j public class QRCodeTools3 { /** * * @Title: deEncodeByPath * @Description: 替换原图片里面的二维码 * @param @param filePath * @param @param newPath 设定文件 * @return void 返回类型 * @throws */ public static void deEncodeByPath(String filePath, String newPath) { // 原图里面二维码的url String originalURL = null; try { // 将远程文件转换为流 BufferedImage readImage = ImageIO.read(new File(filePath)); LuminanceSource source = new BufferedImageLuminanceSource(readImage); Binarizer binarizer = new HybridBinarizer(source); BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer); Map hints = new HashMap(); hints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); Result result = null; result = new MultiFormatReader().decode(binaryBitmap, hints); originalURL = result.getText(); // 解码 ResultPoint[] resultPoint = result.getResultPoints(); System.out.println("原二维码里面的url:" + originalURL + ",\npoints1: " + resultPoint[0] + ",\npoints2: " + resultPoint[1] + ",\npoints2: " + resultPoint[2] + ",\npoints2: " + resultPoint[3]); // 获得二维码坐标 float point1X = resultPoint[0].getX(); float point1Y = resultPoint[0].getY(); float point2X = resultPoint[1].getX(); float point2Y = resultPoint[1].getY(); // 替换二维码的图片文件路径 BufferedImage writeFile = ImageIO.read(new File(newPath)); // 宽高 final int w = (int) Math .sqrt(Math.abs(point1X - point2X) * Math.abs(point1X - point2X) + Math.abs(point1Y - point2Y) * Math.abs(point1Y - point2Y)) + 12 * (7 - 1); final int h = w; Hashtable hints2 = new Hashtable(); hints2.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); hints2.put(EncodeHintType.CHARACTER_SET, "UTF-8"); hints2.put(EncodeHintType.MARGIN, 1); Graphics2D graphics = readImage.createGraphics(); //此处,偏移,会有定位问题 int x = Math.round(point1X) - 36; int y = Math.round(point2Y) - 36; // 开始合并绘制图片 graphics.drawImage(writeFile, x, y, w, h, null); // logo边框大小 graphics.setStroke(new BasicStroke(2)); // //logo边框颜色 graphics.setColor(Color.WHITE); graphics.drawRect(x, y, w, h); readImage.flush(); graphics.dispose(); // 打印替换后的图片 NewImageUtils.generateWaterFile(readImage, "F:\\image\\save.jpg"); } catch (IOException e) { log.error("资源读取失败" + e.getMessage()); e.printStackTrace(); } catch (NotFoundException e) { log.error("读取图片二维码坐标前发生异常:" + e.getMessage()); e.printStackTrace(); } } public static void main(String[] args) { deEncodeByPath("F:\\image\\zfb.jpg", "F:\\image\\gzh.jpg"); } } 原文链接:https://blog.csdn.net/u012891290/article/details/86582687
-
Zxing是Google提供的关于条码(一维码、二维码)的解析工具,提供了二维码的生成与解析的方法,现在我简单介绍一下使用Java利用Zxing生成与解析二维码1、二维码的生成 1.1 将Zxing-core.jar 包加入到classpath下。 1.2 二维码的生成需要借助MatrixToImageWriter类,该类是由Google提供的,可以将该类拷贝到源码中,这里我将该类的源码贴上,可以直接使用。import com.google.zxing.common.BitMatrix; import javax.imageio.ImageIO; import java.io.File; import java.io.OutputStream; import java.io.IOException; import java.awt.image.BufferedImage; public final class MatrixToImageWriter { private static final int BLACK = 0xFF000000; private static final int WHITE = 0xFFFFFFFF; private MatrixToImageWriter() {} public static BufferedImage toBufferedImage(BitMatrix matrix) { int width = matrix.getWidth(); int height = matrix.getHeight(); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE); } } return image; } public static void writeToFile(BitMatrix matrix, String format, File file) throws IOException { BufferedImage image = toBufferedImage(matrix); if (!ImageIO.write(image, format, file)) { throw new IOException("Could not write an image of format " + format + " to " + file); } } public static void writeToStream(BitMatrix matrix, String format, OutputStream stream) throws IOException { BufferedImage image = toBufferedImage(matrix); if (!ImageIO.write(image, format, stream)) { throw new IOException("Could not write an image of format " + format); } } }1.3 编写生成二维码的实现代码try { String content = "120605181003;http://www.cnblogs.com/jtmjx"; String path = "C:/Users/Administrator/Desktop/testImage"; MultiFormatWriter multiFormatWriter = new MultiFormatWriter(); Map hints = new HashMap(); hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, 400, 400,hints); File file1 = new File(path,"餐巾纸.jpg"); MatrixToImageWriter.writeToFile(bitMatrix, "jpg", file1); } catch (Exception e) { e.printStackTrace(); } 现在运行后即可生成一张二维码图片,是不是很简单啊? 接下来我们看看如何解析二维码2、二维码的解析 2.1 将Zxing-core.jar 包加入到classpath下。 2.2 和生成一样,我们需要一个辅助类( BufferedImageLuminanceSource),同样该类Google也提供了,这里我同样将该类的源码贴出来,可以直接拷贝使用个,省去查找的麻烦BufferedImageLuminanceSource import com.google.zxing.LuminanceSource; import java.awt.Graphics2D; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; public final class BufferedImageLuminanceSource extends LuminanceSource { private final BufferedImage image; private final int left; private final int top; public BufferedImageLuminanceSource(BufferedImage image) { this(image, 0, 0, image.getWidth(), image.getHeight()); } public BufferedImageLuminanceSource(BufferedImage image, int left, int top, int width, int height) { super(width, height); int sourceWidth = image.getWidth(); int sourceHeight = image.getHeight(); if (left + width > sourceWidth || top + height > sourceHeight) { throw new IllegalArgumentException("Crop rectangle does not fit within image data."); } for (int y = top; y < top + height; y++) { for (int x = left; x < left + width; x++) { if ((image.getRGB(x, y) & 0xFF000000) == 0) { image.setRGB(x, y, 0xFFFFFFFF); // = white } } } this.image = new BufferedImage(sourceWidth, sourceHeight, BufferedImage.TYPE_BYTE_GRAY); this.image.getGraphics().drawImage(image, 0, 0, null); this.left = left; this.top = top; } @Override public byte[] getRow(int y, byte[] row) { if (y < 0 || y >= getHeight()) { throw new IllegalArgumentException("Requested row is outside the image: " + y); } int width = getWidth(); if (row == null || row.length < width) { row = new byte[width]; } image.getRaster().getDataElements(left, top + y, width, 1, row); return row; } @Override public byte[] getMatrix() { int width = getWidth(); int height = getHeight(); int area = width * height; byte[] matrix = new byte[area]; image.getRaster().getDataElements(left, top, width, height, matrix); return matrix; } @Override public boolean isCropSupported() { return true; } @Override public LuminanceSource crop(int left, int top, int width, int height) { return new BufferedImageLuminanceSource(image, this.left + left, this.top + top, width, height); } @Override public boolean isRotateSupported() { return true; } @Override public LuminanceSource rotateCounterClockwise() { int sourceWidth = image.getWidth(); int sourceHeight = image.getHeight(); AffineTransform transform = new AffineTransform(0.0, -1.0, 1.0, 0.0, 0.0, sourceWidth); BufferedImage rotatedImage = new BufferedImage(sourceHeight, sourceWidth, BufferedImage.TYPE_BYTE_GRAY); Graphics2D g = rotatedImage.createGraphics(); g.drawImage(image, transform, null); g.dispose(); int width = getWidth(); return new BufferedImageLuminanceSource(rotatedImage, top, sourceWidth - (left + width), getHeight(), width); } } 2.3 编写解析二维码的实现代码 try { MultiFormatReader formatReader = new MultiFormatReader(); String filePath = "C:/Users/Administrator/Desktop/testImage/test.jpg"; File file = new File(filePath); BufferedImage image = ImageIO.read(file);; LuminanceSource source = new BufferedImageLuminanceSource(image); Binarizer binarizer = new HybridBinarizer(source); BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer); Map hints = new HashMap(); hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); Result result = formatReader.decode(binaryBitmap,hints); System.out.println("result = "+ result.toString()); System.out.println("resultFormat = "+ result.getBarcodeFormat()); System.out.println("resultText = "+ result.getText()); } catch (Exception e) { e.printStackTrace(); } 现在运行后可以看到控制台打印出了二维码的内容。 到此为止,利用Zxing生成和解析二维码就讲述演示完毕,主要为自己做备忘,同时方便有需要的人。原文链接:https://www.cnblogs.com/jtmjx/archive/2012/06/18/2545209.html
-
ColorConvertOp java.awt.image包下面有个类java.awt.image.ColorConvertOp,类名直译就是”颜色转换操作”。 顾名思义,它的作用就是将一个色彩空间(color space)的图像转换为另一个色彩空间的图像。有了这个神器我们就能轻易的将一张彩色图你像转换成灰度(gray)或其他色彩空间图像。 代码非常简单,只要一行。 public BufferedImage toGray(BufferedImage srcImg){ return new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null).filter(srcImg, null); } 依此类推,你可以参照ColorConvertOp的参数说明将图像转为其他格式。 java.awt.color.ColorSpace中列出了很多支持的色彩空间定义TYPE_RGB,TYPE_CMYK,TYPE_HSV,TYPE_YCbCr…. Raster.getDataElements 有时我们通过ImageIO得到解码后的图像数据对象(BufferedImage)以后,需要获取图像矩阵的裸数据(即一个存储图像数据的byte数组)。 BufferedImage中提供了一个getRGB()方法,它返回的是一个ARGB格式int[]数组(每个int型元素的4个字节分别代表一个像素的Alpha,Red,Green,Blue四个通道) 如果你要从这个方法获取RGB的数组,你还得自己写转换代码: /** * 返回图像的RGB格式字节数组 * @param image * @return */ public static byte[] getMatrixRGB(BufferedImage image){ int w = image.getWidth(); int h = image.getHeight(); int[] intArray = new int[w * h]; byte[] matrixRGB = new byte[w * h * 3]; image.getRGB(0, 0, w, h, intArray, 0, w); // ARGB->RGB for(int i=0,b=0;i matrixRGB[b++]=(byte) (matrixRGB[i]&0x000000FF); matrixRGB[b++]=(byte) ((matrixRGB[i]&0x0000FF00)>>8); matrixRGB[b++]=(byte) ((matrixRGB[i]&0x00FF0000)>>16); } return matrixRGB; } 好烦呐,我以前就是这么干的,真的没有提供更好的方法吗? 不是没有更好的方法,而是我学艺不精没找到而已。 在仔细研究了BufferedImage的代码之后,才明白getRGB()只是BufferedImage为默认 RGB 颜色模型 (TYPE_INT_ARGB)提供的一个便利性封装。 通过getRGB()源码可以知道BufferedImage对象中真正的图像数据是由成员对象raster(java.awt.image.WritableRaster)管理。而WritableRaster是java.awt.image.Raster的子类。Raster中getDataElements方法可以我们所需要的字节数组。 还以前面图像转灰度举例,如果要从灰度图像中获取图像矩阵的字节数组,代码示例如下: /** * 获取灰度图像的字节数组 * @param image * @return */ public static byte[] getMatrixGray(BufferedImage image) { // 转灰度图像 BufferedImage grayImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null).filter(image, grayImage); // getData方法返回BufferedImage的raster成员对象 return (byte[]) grayImage.getData().getDataElements(0, 0, image.getWidth(), image.getHeight(), null); } 注意这里return语句使用了(byte[])强制类型转换,因为getDataElements返回的是打开声明 java.lang.Object对象。 也就是说getDataElements返回的未必是byte[]类型,为什么呢?看下面getDataElements方法的说明: 看不懂没关系,我们可以看到这里的返回的类型可能是:TYPE_BYTE,TYPE_USHORT,TYPE_INT,TYPE_SHORT,TYPE_FLOAT,TYPE_DOUBLE。并不一定是byte。 那么问题来了,如何控制返回的数组类型是byte[]呢? 同样,我们可以使用前面的ColorConvertOp对象进行转换。 比如我们需要得到图像的RGB数据: /** * 获取图像RGB格式数据 * @param image * @return */ public static byte[] getMatrixRGB(BufferedImage image){ if(image.getType()!=BufferedImage.TYPE_3BYTE_BGR){ // 转sRGB格式 BufferedImage rgbImage = new BufferedImage( image.getWidth(), image.getHeight(), BufferedImage.TYPE_3BYTE_BGR); new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_sRGB), null).filter(image, rgbImage); // 从Raster对象中获取字节数组 return (byte[]) rgbImage.getData().getDataElements(0, 0, rgbImage.getWidth(), rgbImage.getHeight(), null); }else{ return (byte[]) image.getData().getDataElements(0, 0, image.getWidth(), image.getHeight(), null); } } 原文链接:https://blog.csdn.net/10km/article/details/51866321
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签