java项目实战应用知识概括

java项目实战应用知识概括

  • Jasypt 加密
  • ICU4J
  • Idea插件
  • BI商业智能
  • Google验证码Kaptcha
  • 数据脱敏
  • QRCode二维码
  • 邮件发送与接收
  • 富文本与Markdown
  • Java调用第三方接口
  • 短链接服务
  • Data URL
  • 埋点

Jasypt 加密

简介:

  • Jasypt这个Java类包为开发人员提供一种简单的方式来为项目增加加密功能,包括:密码Digest认证,文本和对象加密,集成hibernate,Spring Security(Acegi)来增强密码管理。Jasypt开发团队推出了Java加密工具Jasypt 1.4,它可与Spring Framework、Hibernate和Acegi Security集成。
  • 与项目有关的一位开发者表示,Jasypt是一个Java库,可以使开发者不需太多操作来给Java项目添加基本加密功能,而且不需要知道加密原理。
  • Jasypt也即Java Simplified Encryption是Sourceforge.net上的一个开源项目。在当地时间11月23号的通告中,Jasypt 1.4的新特征包括:加密属性文件(encryptable properties files)、Spring Framework集成、加密Hibernate数据源配置、新的命令行工具、URL加密的Apache wicket集成以及升级文档。
  • 根据Jasypt文档,该技术可用于加密任务与应用程序,例如加密密码、敏感信息和数据通信、创建完整检查数据的sums.其他性能包括高安全性、基于标准的加密技术、可同时单向和双向加密的加密密码、文本、数字和二进制文件。Jasypt也可以与Acegi Security整合也即Spring Security。Jasypt亦拥有加密应用配置的集成功能,而且提供一个开放的API从而任何一个Java Cryptography Extension都可以使用Jasypt。
  • Jasypt还符合RSA标准的基于密码的加密,并提供了无配置加密工具以及新的、高可配置标准的加密工具。

详解:

  • java simplified encrtption :java简化加密。
  • jsaypt是一个对源码进行加密的技术,可以包装我们在源码配置文件里面的有段的敏感信息,如用户名密码等。
  • 他是一种加密的手段,注意加密后的密码要使用需要设置秘钥不然不能正产启动项目
  • jasypt中的加密与解密Demo

秘钥:

  • 解密秘钥也在配置文件里头啊,别人拿到你服务器上面的部署代码后,不是很轻松的就可以解开这个密码了?
  • 为了防止salt(盐)泄露,反解出密码.删除掉application.properties中的jasypt.encryptor.password 可以在本地运行中加参数(在VM options中)
  • 或是在项目部署的时候使用命令传入salt(盐)值。打包时隐藏jasypt.encryptor.password,就需要打包时maven命令增加参数clean package -Djasypt.encryptor.password=Bt%XJ^n1j8mz 。不加参数的话打包就会报错。
  • 配置电脑本地环境变量APP_PASSWORD --> 启动应用程序 --> 应用程序启动完成 --> 删除环境变量APP_PASSWORD。

ICU4J

简介:

  • 网页源码的编码探测一般有两种方式,一种是通过分析网页源码中Meta信息,比如contentType,来取得编码,
  • 但是某些网页不的contentType中不含任何编码信息,这时需要通过第二种方式进行探测,第二种是使用统计学和启发式方法对网页源码进行编码探测。ICU4J就是基于第二种方式的类库。由IBM提供。

Idea插件

IntelliJ IDEA 的 HTTP Client:

  • 简单的说就是能直接在 IDEA 的代码编辑器中 创建,编辑,执行 HTTP请求,(纯编码操作)
  • HTTP Client 是 IDEA 默认绑定好并启用的插件,如果你那里没有启用,按照下图启用就好java项目实战应用知识概括_第1张图片
  • IntelliJ IDEA 的 HTTP Client

RestfulToolkit辅助功能:

  • RestfulToolkit 同样是个插件,在插件市场搜索安装即可java项目实战应用知识概括_第2张图片
  • 安装了这个插件后,打开侧边栏,项目的所有接口信息都会展现在此处:java项目实战应用知识概括_第3张图片

Live Template:

  • 项目中请求内容各有不同,IDEA标准提供的GET POST 请求案例可能还不能满足我们的需求,这时我们就可以利用 LiveTemplate 定制自己的模版,迅速生成request 内容

JSON Viewer:

  • JSON Viewer是一款 Chrome浏览器插件,在浏览器 Omini-box 中输入 json-viewer + Tab,
    粘贴json在此处,就可以对json数据进行格式化了

Alibaba Java Coding Guidelines:

  • 对于Java代码规范,业界有统一的标准,不少公司对此都有一定的要求。但是即便如此,庞大的Java使用者由于经验很水平的限制,未必有规范编码的意识,而且即便经验丰富的老Java程序员也无法做到时刻将规范牢记于心。所以对于代码规范扫描工具,一经问世就广受青睐,阿里巴巴出品的AlibabaJava Coding Guidelines(阿里巴巴Java代码规约扫描,以下简称为AJCG)插件便是其中之一。
  • 与很多其它流行的同类工具(如FindBugs,Lint等)相比,它更专注于Java代码规范,而且默认采用中文,对于英文没那么好的开发者而言,这无疑是一种福利。
  • 使用:在IDEA上边栏中点击Tools,再选中阿里编码规约。

BI商业智能

简介:

  • 商业智能(Business Intelligence,简称:BI),又称商业智慧或商务智能,指用现代数据仓库技术、线上分析处理技术、数据挖掘和数据展现技术进行数据分析以实现商业价值。
  • 可以认为商业智能是对商业信息的搜集、管理和分析过程,目的是使企业的各级决策者获得知识或洞察力(insight),促使他们做出对企业更有利的决策。商业智能一般由数据仓库、联机分析处理、数据挖掘、数据备份和恢复等部分组成。商业智能的实现涉及到软件、硬件、咨询服务及应用,其基本体系结构包括数据仓库、联机分析处理和数据挖掘三个部分。
  • 因此把商业智能看成是一种解决方案应该比较恰当。商业智能的关键是从许多来自不同的企业运作系统的数据中提取出有用的数据并进行清理,以保证数据的正确性,然后经过抽取(Extraction)、转换(Transformation)和装载(Load),即ETL过程,合并到一个企业级的数据仓库里,从而得到企业数据的一个全局视图,在此基础上利用合适的查询和分析工具、数据挖掘工具(大数据魔镜)、OLAP工具等对其进行分析和处理(这时信息变为辅助决策的知识),最后将知识呈现给管理者,为管理者的决策过程提供支持。
  • BI与大数据的区别:
    java项目实战应用知识概括_第4张图片
  • 链接:商业智能BI 到底是什么

商业智能BI的工作原理:

  • 商业智能BI是一个复杂的技术集合,它包含ETL、DW、OLAP、DM等多个环节(这里的几个名词后文会有详细解释)。如图所示,简单的说,就是把交易系统已经发生过的数据,通过ETL工具抽取到主题明确的数据仓库中,OLAP处理后生成Cube或报表,透过Portal展现给用户,用户利用这些经过分类(Classification)、聚集(Clustering)、描述和可视化(Description and Visualization)的数据,支持业务决策。
    java项目实战应用知识概括_第5张图片

Google验证码Kaptcha

简介:

  • Kaptcha 是一个可高度配置的实用验证码生成工具,可自由配置的选项如:
    ①验证码的字体
    ②验证码字体的大小
    ③验证码字体的字体颜色
    ④验证码内容的范围(数字,字母,中文汉字!)
    ⑤验证码图片的大小,边框,边框粗细,边框颜色
    ⑥验证码的干扰线
    ⑦验证码的样式(鱼眼样式、3D、普通模糊、…)
  • 链接:kaptcha谷歌验证码工具

SpringBoot之配置google kaptcha:

  • 项目中引入POM:
<dependency>
    <groupId>com.google.code.kaptchagroupId>
    <artifactId>kaptchaartifactId>
    <version>2.3version>
dependency>
  • kaptcha提供了KaptchaServlet来处理验证码的生成并放入session,但这方式在如今的分布式、前后端分离、集群的部署条件显然不适用。
 <servlet>
    <servlet-name>Kaptchaservlet-name>
    <servlet-class>com.google.code.kaptcha.servlet.KaptchaServletservlet-class>
    <init-param>
      <param-name>kaptcha.borderparam-name>
      <param-value>noparam-value>
    init-param>
    <init-param>
      <param-name>kaptcha.textproducer.char.stringparam-name>
      <param-value>02345689param-value>
    init-param>
    <init-param>
      <param-name>kaptcha.background.clear.fromparam-name>
      <param-value>whiteparam-value>
    init-param>
    <init-param>
      <param-name>kaptcha.background.clear.toparam-name>
      <param-value>whiteparam-value>
    init-param>
    <init-param>
      <param-name>kaptcha.obscurificator.implparam-name>
      <param-value>com.google.code.kaptcha.impl.WaterRippleparam-value>
    init-param>
    <init-param>
      <param-name>kaptcha.noise.colorparam-name>
      <param-value>255,96,0param-value>
    init-param>
  servlet>
  <servlet-mapping>
    <servlet-name>Kaptchaservlet-name>
    <url-pattern>/images/captcha.jpgurl-pattern>
  servlet-mapping>
  • kaptcha生成验证的核心接口类有:
    ①com.google.code.kaptcha.Producer,该接口目前只有一个默认实现类:com.google.code.kaptcha.impl.DefaultKaptcha
    ②com.google.code.kaptcha.text.TextProducer,该忌口目前只有一个默认实现类:com.google.code.kaptcha.text.impl.DefaultTextCreator
  • 其中Producer是用来处理生成图片的,TextProducer是用来处理生成验证码问题的。当然我们也可以去实现这个接口来实现自己的自定义的实现。
  • 控制验证码的图片的生成的规则的配置信息都放到了com.google.code.kaptcha.util.Config类中:
kaptcha.border  是否有边框  默认为true  我们可以自己设置yes,no  
kaptcha.border.color   边框颜色   默认为Color.BLACK  
kaptcha.border.thickness  边框粗细度  默认为1  
kaptcha.producer.impl   验证码生成器  默认为DefaultKaptcha  
kaptcha.textproducer.impl   验证码文本生成器  默认为DefaultTextCreator  
kaptcha.textproducer.char.string   验证码文本字符内容范围  默认为abcde2345678gfynmnpwx  
kaptcha.textproducer.char.length   验证码文本字符长度  默认为5  
kaptcha.textproducer.font.names    验证码文本字体样式  默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)  
kaptcha.textproducer.font.size   验证码文本字符大小  默认为40  
kaptcha.textproducer.font.color  验证码文本字符颜色  默认为Color.BLACK  
kaptcha.textproducer.char.space  验证码文本字符间距  默认为2  
kaptcha.noise.impl    验证码噪点生成对象  默认为DefaultNoise  
kaptcha.noise.color   验证码噪点颜色   默认为Color.BLACK  
kaptcha.obscurificator.impl   验证码样式引擎  默认为WaterRipple  
kaptcha.word.impl   验证码文本字符渲染   默认为DefaultWordRenderer  
kaptcha.background.impl   验证码背景生成器   默认为DefaultBackground  
kaptcha.background.clear.from   验证码背景颜色渐进   默认为Color.LIGHT_GRAY  
kaptcha.background.clear.to   验证码背景颜色渐进   默认为Color.WHITE  
kaptcha.image.width   验证码图片宽度  默认为200  
kaptcha.image.height  验证码图片高度  默认为50
  • 案例:
//创建字符
String kaptchaText = kaptchaProducer.createText();
log.info("capText = {} ,kaptchaKey = {} ", kaptchaText, kaptchaKey);

//创建图片
BufferedImage bi = kaptchaProducer.createImage(kaptchaText);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(bi, "jpeg", outputStream);
String base64Image = "data:image/jpeg;base64," + Base64.encodeBase64String(outputStream.toByteArray());

Kaptcha详细配置表:
java项目实战应用知识概括_第6张图片
验证码作用:

  • 验证码(CAPTCHA)是“Completely Automated Public Turing test to tell
    Computers and Humans Apart”(全自动区分计算机和人类的图灵测试)的缩写,是一种区分用户是计算机还是人的公共全自动程序。
  • 可以防止:恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试,实际上用验证码是现在很多网站通行的方式,我们利用比较简易的方式实现了这个功能。
  • 这个问题可以由计算机生成并评判,但是必须只有人类才能解答。由于计算机无法解答CAPTCHA的问题,所以回答出问题的用户就可以被认为是人类。

数据脱敏

什么是数据脱敏?

  • 数据脱敏(Data Masking),顾名思义,是屏蔽敏感数据,对某些敏感信息(比如,身份证号、手机号、卡号、客户姓名、客户地址、邮箱地址、薪资等等)通过脱敏规则进行数据的变形,实现隐私数据的可靠保护。业界常见的脱敏规则有,替换、重排、加密、截断、掩码,用户也可以根据期望的脱敏算法自定义脱敏规则。
  • 通常,良好的数据脱敏实施,需要遵循如下两个原则:
    ①尽可能地为脱敏后的应用,保留脱敏前的有意义信息;
    ②最大程度地防止黑客进行破解。
  • 数据脱敏分为静态数据脱敏和动态数据脱敏。
    ①静态数据脱敏,是数据的“搬移并仿真替换”,是将数据抽取进行脱敏处理后,下发给下游环节,随意取用和读写的,脱敏后数据与生产环境相隔离,满足业务需求的同时保障生产数据库的安全。
    ②动态数据脱敏,在访问敏感数据的同时实时进行脱敏处理,可以为不同角色、不同权限、不同数据类型执行不同的脱敏方案,从而确保返回的数据可用而安全。
  • 链接:数据脱敏是什么?
  • 案例:
 public static void main(String[] args) {
        String phone = "13123456789";
        String phoneNumber = phone.substring(0, 3) + "****" + phone.substring(7, phone.length());
        System.out.println("phone总长度:" + phone.length());
        System.out.println("phone前3位:" + phone.substring(0, 3));
        System.out.println("phone中4位:" + phone.substring(3, 7));
        System.out.println("phone后4位:" + phone.substring(7, phone.length()));
        System.out.println("phone中4*:" + phoneNumber);
     }

QRCode二维码

二维码简述:

  • 二维码其实就是一种编码技术,只是这种编码技术是用在图片上了,将给定的一些文字,数字转换为一张经过特定编码的图片,而解析二维码则相反,就是将一张经过编码的图片解析为数字或者文字。
  • 当然了,这种编码的低层实现并不是那么的简单,都是那些顶级研发人员做的事,我们只需要简单了解并知道怎么使用就可以了。
  • 那么肯定是要导入jar包依赖的吧,我用的是谷歌提供的一个com.google.zxing.core包
  • 链接:java实现二维码的生成与解析

二维码与解析二维码详解:

  • 二维码生成:字符在变成只有0和1组成的数字序列后,再进行一系列优化算法,就得到了最终的二进制编码。在最后这串编码中,一个0对应的就是一个白色小方块,一个1对应的就是一个黑色小方块,我们把这些小方块,按照8个一组,填进大方块里,这就是一个完整的,可以被手机相机识别的二维码图案了。
  • 二维码解析:二维码扫描”实际上就是通过手机相机扫描『二维码图片』,将『二维码图片』中的字符串数据通过解码的方式解析出来。
  • 因此可以用任何文字生成二维码,在通过二维码扫描解析出文字。
  • 二维码扫码登录的原理:
    java项目实战应用知识概括_第7张图片
  • 此外二维码有一个难题就是不好携带个人信息在二维码中,
    因此各家APP的扫一扫都会在扫出URL后在发送请求时加上对应的个人信息。
    但有些例外:付款码,因此付款码不能轻易暴露。
    ③此外扫一扫能否自动访问就看你手机安装的二维码扫描软件的功能了,大部分二维码扫描软件读取到网址会自动跳转,有些会先询问你是否打开。
  • 各家APP的扫一扫确实是个好办法,但如果这家APP做的是一个开放平台呢,解决办法就是这家APP开放一些API出来。
    微信扫一扫解析出登录地址,微信APP底层加上当前APP登录用户的信息,再发送请求到对应的URL。
    这其中的请求参数是如何的,我们要到微信开放平台扫一扫功能中查看。

二维码代码使用:

  • 谷歌提供的帮助类:
package com.yc.qrcode;
 
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import com.google.zxing.LuminanceSource;
 
public 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;
	}
 
	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;
	}
 
	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;
	}
 
	public boolean isCropSupported() {
		return true;
	}
 
	public LuminanceSource crop(int left, int top, int width, int height) {
		return new BufferedImageLuminanceSource(image, this.left + left, this.top + top, width, height);
	}
 
	public boolean isRotateSupported() {
		return true;
	}
 
	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);
	}
 
}
  • 工具类:
package com.yc.qrcode;
 
import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Shape;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.OutputStream;
import java.util.Hashtable;
import java.util.Random;
import javax.imageio.ImageIO;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
 
public class QRCodeUtil {
	private static final String CHARSET = "utf-8";
	private static final String FORMAT_NAME = "JPG";
	// 二维码尺寸
	private static final int QRCODE_SIZE = 300;
	// LOGO宽度
	private static final int WIDTH = 60;
	// LOGO高度
	private static final int HEIGHT = 60;
 
	private static BufferedImage createImage(String content, String imgPath, boolean needCompress) throws Exception {
		Hashtable hints = new Hashtable();
		hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
		hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
		hints.put(EncodeHintType.MARGIN, 1);
		BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE,
				hints);
		int width = bitMatrix.getWidth();
		int height = bitMatrix.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, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
			}
		}
		if (imgPath == null || "".equals(imgPath)) {
			return image;
		}
		// 插入图片
		QRCodeUtil.insertImage(image, imgPath, needCompress);
		return image;
	}
 
	private static void insertImage(BufferedImage source, String imgPath, boolean needCompress) throws Exception {
		File file = new File(imgPath);
		if (!file.exists()) {
			System.err.println("" + imgPath + "   该文件不存在!");
			return;
		}
		Image src = ImageIO.read(new File(imgPath));
		int width = src.getWidth(null);
		int height = src.getHeight(null);
		if (needCompress) { // 压缩LOGO
			if (width > WIDTH) {
				width = WIDTH;
			}
			if (height > HEIGHT) {
				height = HEIGHT;
			}
			Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
			BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
			Graphics g = tag.getGraphics();
			g.drawImage(image, 0, 0, null); // 绘制缩小后的图
			g.dispose();
			src = image;
		}
		// 插入LOGO
		Graphics2D graph = source.createGraphics();
		int x = (QRCODE_SIZE - width) / 2;
		int y = (QRCODE_SIZE - height) / 2;
		graph.drawImage(src, x, y, width, height, null);
		Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
		graph.setStroke(new BasicStroke(3f));
		graph.draw(shape);
		graph.dispose();
	}
 
	public static void encode(String content, String imgPath, String destPath, boolean needCompress) throws Exception {
		BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
		mkdirs(destPath);
		// String file = new Random().nextInt(99999999)+".jpg";
		// ImageIO.write(image, FORMAT_NAME, new File(destPath+"/"+file));
		ImageIO.write(image, FORMAT_NAME, new File(destPath));
	}
 
	public static BufferedImage encode(String content, String imgPath, boolean needCompress) throws Exception {
		BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
		return image;
	}
 
	public static void mkdirs(String destPath) {
		File file = new File(destPath);
		// 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)
		if (!file.exists() && !file.isDirectory()) {
			file.mkdirs();
		}
	}
 
	public static void encode(String content, String imgPath, String destPath) throws Exception {
		QRCodeUtil.encode(content, imgPath, destPath, false);
	}
	// 被注释的方法
	/*
	 * public static void encode(String content, String destPath, boolean
	 * needCompress) throws Exception { QRCodeUtil.encode(content, null, destPath,
	 * needCompress); }
	 */
 
	public static void encode(String content, String destPath) throws Exception {
		QRCodeUtil.encode(content, null, destPath, false);
	}
 
	public static void encode(String content, String imgPath, OutputStream output, boolean needCompress)
			throws Exception {
		BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
		ImageIO.write(image, FORMAT_NAME, output);
	}
 
	public static void encode(String content, OutputStream output) throws Exception {
		QRCodeUtil.encode(content, null, output, false);
	}
 
	public static String decode(File file) throws Exception {
		BufferedImage image;
		image = ImageIO.read(file);
		if (image == null) {
			return null;
		}
		BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
		BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
		Result result;
		Hashtable hints = new Hashtable();
		hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
		result = new MultiFormatReader().decode(bitmap, hints);
		String resultStr = result.getText();
		return resultStr;
	}
 
	public static String decode(String path) throws Exception {
		return QRCodeUtil.decode(new File(path));
	}
 
}

邮件发送与接收

邮件与Java:

  • 关于要使用JavaMail的原因?
    ①用户注册后,网站发送一封激活邮件验证;
    ②用户过生日,系统发送生日祝福邮件;
    ③将最新活动和优惠以邮件的形式告知会员等等…
  • 什么是电子邮箱?
    ①电子邮箱(E-mail 地址) 需要在邮件服务器上进行申请,确切的说,电子邮箱其实就是用户在邮件服务器上申请的一个账户,用户在邮件服务器上申请了一个账号后,邮件服务器就会为这个账号分配一定的空间,用户从而可以使用这个账号以及空间,发送电子邮件和保存别人发送过来的电子邮件。
  • 什么是邮箱服务器?
    ①服务器指的是一台电脑安装了一个服务器软件,那么这台电脑就可以称为是WEB服务器,那么同样的一台电脑安装了邮件服务器软件,那么这台电脑称为是邮件服务器。
    邮件收发协议
  • SMTP协议(发送邮件):
    ①简单邮件传输协议 (Simple Mail Transfer Protocol, SMTP) 是在Internet传输email的事实标准。
    ②SMTP是一个相对简单的基于文本的协议。在其之上指定了一条消息的一个或多个接收者(在大多数情况下被确认是存在的),然后消息文本会被传输。可以很简单地通过telnet程序来测试一个SMTP服务器。SMTP使用TCP端口25。要为一个给定的域名决定一个SMTP服务器,需要使用MX (Mail eXchange) DNS。
    ②用户脸上邮件服务器后,要想给它发送一封电子邮件,需要遵循一定的通讯规则,SMTP协议就是用于定义这种规则的。因此,通常我们也把处理用户SMTP请求(邮件发送请求)的邮件服务器称之为SMTP服务器。
  • POP3协议(接收邮件):
    ①POP3,全名为“Post Office Protocol - Version 3”,即“邮局协议版本3”。是TCP/IP协议族中的一员,由RFC1939 定义。本协议主要用于支持使用客户端远程管理在服务器上的电子邮件。提供了SSL加密的POP3协议被称为POP3S。
    ②POP 协议支持“离线”邮件处理。其具体过程是:邮件发送到服务器上,电子邮件客户端调用邮件客户机程序以连接服务器,并下载所有未阅读的电子邮件。这种离线访问模式是一种存储转发服务,将邮件从邮件服务器端送到个人终端机器上,一般是PC机或 MAC。一旦邮件发送到 PC 机或MAC上,邮件服务器上的邮件将会被删除。但目前的POP3邮件服务器大都可以“只下载邮件,服务器端并不删除”,也就是改进的POP3协议。
    java项目实战应用知识概括_第8张图片
  • 什么是IMAP(接收邮件):
    ①IMAP全称为Internet Message Access Protocol(互联网邮件访问协议),IMAP允许从邮件服务器上获取邮件的信息、下载邮件等。IMAP与POP类似,都是一种邮件获取协议。
  • IMAP和POP3协议有什么不同呢?
    ①两者最大的区别在于,IMAP允许双向通信,即在客户端的操作会反馈到服务器上,例如在客户端收取邮件、标记已读等操作,服务器会跟着同步这些操作。
    ②而对于POP协议虽然也允许客户端下载服务器邮件,但是在客户端的操作并不会同步到服务器上面的,例如在客户端收取或标记已读邮件,服务器不会同步这些操作。

JavaMail概述:

  • 链接:
    ①JavaMail发送和接收邮件
    ②JavaMail详解
  • JavaMail是由Sun定义的一套收发电子邮件的API,不同的厂商可以提供自己的实现类。但它并没有包含在JDK中,而是作为JavaEE的一部分。
  • JavaMail的关键对象: JavaMail对收发邮件进行了高级的抽象,形成了一些关键的的接口和类,它们构成了程序的基础,下面我们分别来了解一下这些最常见的对象:
  • ①Properties:属性对象
属性名 属性类型 说明
mail.stmp.host String SMTP服务器地址,如smtp.sina.com.cn
mail.stmp.port int SMTP服务器端口号,默认为25
mail.stmp.auth boolean SMTP服务器是否需要用户认证,默认为false
mail.stmp.user String SMTP默认的登陆用户名
mail.stmp.from String 默认的邮件发送源地址
mail.stmp.socketFactory.class String socket工厂类类名,通过设置该属性可以覆盖提供者默认的实现,必须实现javax.net.SocketFactory接口
mail.stmp.socketFactory.port int 指定socket工厂类所用的端口号,如果没有规定,则使用默认的端口号
mail.smtp.socketFactory.fallback boolean 设置为true时,当使用指定的socket类创建socket失败后,将使用java.net.Socket创建socket,默认为true
mail.stmp.timeout int I/O连接超时时间,单位为毫秒,默认为永不超时
  • ②Session:会话对象
    <1>Session是一个很容易被误解的类,这归咎于混淆视听的类名。千万不要以为这里的Session像HttpSession一样代表真实的交互会话,但创建Session对象时,并没有对应的物理连接,它只不过是一对配置信息的集合。Session的主要作用包括两个方面:
    1、接收各种配置属性信息:通过Properties对象设置的属性信息;
    2、初始化JavaMail环境:根据JavaMail的配置文件,初始化JavaMail环境,以便通过Session对象创建其他重要类的实例。
    3、所以,如果把Session更名为Configure也许更容易理解一些。JavaMail提供者在Jar包的META-INF目录下,通过以下文件提供了基本配置信息,以便session能够根据这个配置文件加载提供者的实现类。
  • ③Transport和Store:传输和存储
    <1>邮件操作只有发送或接收两种处理方式,JavaMail将这两种不同操作描述为传输(javax.mail.Transport)和存储(javax.mail.Store),传输对应邮件的发送,而存储对应邮件的接收。
    <2>Session提供了几个用于创建Transport和Store实例的方法,在具体讲解这些方法之前,我们事先了解一下Session创建Transport和Store的内部机制。我们知道提供者在javamail.providers配置文件中为每一种支持的邮件协议定义了实现类,Session根据协议类型(stmp、pop3等)和邮件操作方式(传输和存储)这两个信息就可以定位到一个实例类上。
  • ④Message:消息对象:
    <1>一旦获得 Session 对象,就可以继续创建要发送的消息。这由 Message 类来完成。因为 Message 是个抽象类,您必需用一个子类,多数情况下为 javax.mail.internet.MimeMessage。MimeMessage 是个能理解 MIME 类型和头的电子邮件消息,正如不同 RFC 中所定义的。虽然在某些头部域非 ASCII 字符也能被译码,但 Message 头只能被限制为用 US-ASCII 字符。
  • ⑤Address:地址:
    <1>一旦您创建了 Session 和 Message,并将内容填入消息后,就可以用 Address 确定信件地址了。和 Message 一样,Address 也是个抽象类。您用的是 javax.mail.internet.InternetAddress 类。
  • ⑥Authenticator:认证者
    <1>与 java.net 类一样,JavaMail API 也可以利用 Authenticator 通过用户名和密码访问受保护的资源。对于JavaMail API 来说,这些资源就是邮件服务器。JavaMail Authenticator 在 javax.mail 包中,而且它和 java.net 中同名的类 Authenticator 不同。两者并不共享同一个 Authenticator,因为JavaMail API 用于 Java 1.1,它没有 java.net 类别。
  • ⑦发送消息:
    <1>发送电子邮件消息这一过程包括获取一个会话,创建并填充一则消息,然后发送。得到 Session 时,经由设置传递的 Properties 对象中的 mail.smtp.host 属性,可以指定您的 SMTP 服务器:
  • ⑧消息的提取:
    <1>为读邮件,您获取一个会话,获取并连接一个用于邮箱的适宜的存储(store),打开适宜的文件夹,然后获取您的消息。同样,切记完成后关闭连接。

JavaMail和Jakarta Mail:

  • Jakarta Mail API提供了一个独立于平台和协议的框架来构建邮件,完成邮件接收与发送功能。它也包含在JavaEE平台中,也可以和Java SE平台一起使用。
  • Jakarta Mail的前生是JavaMail。JavaMail最后一个版本是于2018年8月发布,已经停止更新。新项目应该使用Jakarta Mail。
  • 现在很多邮箱默认关闭smtp,pop3,imap服务,需要在设置中手动开启。
    java项目实战应用知识概括_第9张图片
  • 如果邮箱是使用授权码,则需要生成授权码(代替下文中密码),这种方式更安全。
  • 注意Jakarta Mail引用的包名与JavaMail不同,
<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>jakarta.mail</artifactId>
    <version>{version}</version>
</dependency>

基于SSM的spring发送邮件的实现:

  • 导入jar包,首先我们需要在我们spring项目中添加以下两个jar包(我是使用的maven所以直接配置依赖信息)。

<dependency>
      <groupId>org.springframeworkgroupId>
      <artifactId>spring-context-supportartifactId>
      <version>5.0.0.RELEASEversion>
dependency>

<dependency>
      <groupId>com.sun.mailgroupId>
      <artifactId>javax.mailartifactId>
      <version>1.6.1version>
dependency>
  • mail.properties文件:
#服务器主机名 smtp.xx.com
mail.smtp.host=smtp.163.com
[email protected]
#密码/客户端授权码
mail.smtp.password=XXXXXXXXX
#编码字符
mail.smtp.defaultEncoding=utf-8
#是否进行用户名密码校验
mail.smtp.auth=true
#设置超时时间
mail.smtp.timeout=20000
  • javaMailSender和JavaMailSenderImpl是Spring官方提供的集成邮件服务的接口和实现类,以简单高效的设计著称,目前是Java后端发送邮件和集成邮件服务的主流工具。
  • 通过邮件信息类(MailVo) 来保存发送邮件时的邮件主题、邮件内容等信息 :
@Data
public class MailVo {
    private String id;//邮件id
    private String from;//邮件发送人
    private String to;//邮件接收人
    private String subject;//邮件主题
    private String text;//邮件内容
    private Date   sentDate;//发送时间
    private String cc; //抄送
    private String bcc; //密送
    private String status; //状态
    private String error; //报错信息
    @JsonIgnore
    private MultipartFile[] multipartFiles;//邮件附件
}

Spring Boot笔记之邮件:

  • 链接:SpringBoot发送邮件和附件
  • Spring Boot2.x集成了mail模块,在dependencies引入这个:
<dependency>
	<groupId>org.springframework.bootgroupId>
	<artifactId>spring-boot-starter-mailartifactId>
dependency>
  • application.yml配置:
spring:
	mail:
    	# 163
    	host: smtp.163.com
    	port:
    	username: [email protected]
    	password: ************
    	protocol: smtp
    	default-encoding: UTF-8
    	properties:
      		mail.smtp.auth: true
      		mail.smtp.starttls.enable: true
      		mail.smtp.starttls.required: true
      		mail.smtp.socketFactory.port: 465
      		mail.smtp.socketFactory.class: javax.net.ssl.SSLSocketFactory
      		mail.smtp.socketFactory.fallback: false

富文本与Markdown

富文本与纯文本:

  • 纯文本,只有文字,和基本的标点。
  • 富文本,可以有图,可以有各种特殊标点,分段等格式。
  • 前者如记事本,后者如word
  • 富文本格式是指用户在富文本框输入的类容,这些内容在保存的时候会将你操作的样式利用代码的形式保存到数据库,从数据库拿出数据的时候,这些代码又会重新转成样式。

Markdown与富文本:

  • Markdown是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容具有一定的格式。
    ①优点:有些格式很棒,比如常用到的引用。
    ②缺点:
    <1>虽然格式比纯文本丰富,但是输入还是稍显麻烦。
    <2>图片显示不直观。看整体效果必须**预览”。简书有一个毛病,有时候图片显示顺序并不按照你选择的顺序显示,而光看地址自己也分不清哪张是哪张。错了只能靠手工调,不停“预览—退出预览”,真的很悲剧。
  • 富文本:富文本格式(Rich Text Format, 一般简称为RTF)是由微软公司开发的跨平台文档格式。最大的特点是:所见即所得,你把格式调整成什么样子,就会直接显示出什么样的效果。这一点和words类似。

Java与富文本:

  • 富文本传给后台的就是拼接好的html 字符串,后台当成的字符串接收就行了。
  • 为什么要将富文本转成文本的格式发送给前端?
    ①富文本里面的内容是含有html标签的内容。比如一段话为"Hello CSDN",在富文本里面的内容是

    Hello CSDN

    ,如果富文本不转文本,那么在显示的时候数据加载会很慢,这样不利于效率的提高。
    ②提取富文本里面的图片,上传到OSS中再返回地址存到数据库中。

  • 代码:
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;

import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.parser.ParserDelegator;

public class Html2Text extends HTMLEditorKit.ParserCallback {

    private static Html2Text html2Text = new Html2Text();

    StringBuffer s;

    public Html2Text() {
    }

    public void parse(String str) throws IOException {

        InputStream iin = new ByteArrayInputStream(str.getBytes());
        Reader in = new InputStreamReader(iin);
        s = new StringBuffer();
        ParserDelegator delegator = new ParserDelegator();
        // the third parameter is TRUE to ignore charset directive
        delegator.parse(in, this, Boolean.TRUE);
        iin.close();
        in.close();
    }

    public void handleText(char[] text, int pos) {
        s.append(text);
    }

    public String getText() {
        return s.toString();
    }

    public static String getContent(String str) {
        try {
            html2Text.parse(str);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return html2Text.getText();
    }
}

Java调用第三方接口

外部接口和内部接口:

  • 外部接口:
    ①暴露在外部的接口(提供给第三方使用的接口),测试人员必须对外部接口做接口测试,覆盖各种正常、异常情况。
    ②例如京东调用微信支付接口。微信在提供这个接口给京东的时候,是需要进行测试通过的。
  • 内部接口:
    ①内部接口(供系统内部调用的接口),一般为了尽早的介入测试,所以一般接口开发完成测试人员就可以进行内部接口测试。但一些小公司都是不对内部接口进行测试的,直接在UI层测试即可。但一些大公司可能要求比较高,需要考虑安全问题,那么内部接口测试也是一定要测的。一些攻击者会绕过前端的验证直接对接口攻击,那么后端接口的验证也是必不可少的,这就是需要测试人员测试的原因。

Java调用第三方接口详解:

  • 业务需求:一般情况下都是后端提供接口,前端调用,解决需求,但是有的时候为了方便,复用别人的接口(网上的,公共的第三方接口(短信、天气等)),就出现了后端调用后端接口的情况。(类似JavaScript中的ajax一样获取数据,并对数据进行处理)
  • 开放平台:开放平台(Open Platform) 在软件行业和网络中,开放平台是指软件系统通过公开其应用程序编程接口(API)或函数(function)来使外部的程序可以增加该软件系统的功能或使用该软件系统的资源,而不需要更改该软件系统的源代码。在互联网时代,把网站的服务封装成一系列计算机易识别的数据接口开放出去,供第三方开发者使用,这种行为就叫做Open API,提供开放API的平台本身就被称为开放平台。
  • 在Java项目中调用第三方接口的方式有:
    ①通过JDK网络类Java.net.HttpURLConnection;
    ②通过common封装好的HttpClient;
    ③通过Apache封装好的CloseableHttpClient;
    ④通过SpringBoot-RestTemplate;
  • 第三方接口分类:
    需要下载SDK包并通过http调用,例如:阿里云OSS。链接:AliyunOSS
    直接通过http调用。
  • 链接:Java调用第三方接口(http总结)

短链接服务

简介:

  • 短链接我们或多或少都使用过,所谓短链接就是根据较长的原链接url生成一段较短的链接,访问短链接可以跳转到对应的原链接,这样做好处在于:
    ①url更加美观;
    ②便于保存和传播;
    ③某些网站内容发布有字数限制,短链接可以节约字数。
  • 短链接实现的原理非常简单,可以概括为:
    ①为每个原链接生成不重复的唯一短链接
    ②将原链接和对应短链接成对保存到数据库
    ③访问短链接时,web服务器将目标重定向到对应的原链接
  • 其核心思想:就是把生成的短网址与原网址在redis做k-v对应,当短网址k请求到来的时候取出原网址v直接重定向
  • 注意:为了防止短网址冲突,生成短网址的方式是采用获取原网址的md5方式。建议对短网址限时失效防止出现重复问题。
  • 链接:如何自己搭建短链接服务

Data URL

Data URL简介:

  • DataURL给了我们一种很巧妙的将图片“嵌入”到HTML中的方法。跟传统的用img标记将服务器上的图片引用到页面中的方式不一样,在Data URL协议中,图片被转换成base64编码的字符串形式,并存储在URL中,冠以mime-type。使用Data URL优化网站加载速度和执行效率。
  • Data URL基本原理:
    ①图片在网页中的使用方法通常是下面这种利用img标记的形式:这种方式中,img标记的src属性指定了一个远程服务器上的资源。当网页加载到浏览器中 时,浏览器会针对每个外部资源都向服务器发送一次拉取资源请求,占用网络资源。大多数的浏览器都有一个并发请求数不能超过4个的限制。这意味着,如果一个 网页里嵌入了过多的外部资源,这些请求会导致整个页面的加载延迟。
    ②而使用Data URL技术,图片数据以base64字符串格式嵌入到了页面中,与HTML成为一体,它的形式如下:
    java项目实战应用知识概括_第10张图片

为什么Data URL是个好东西?

  • 几乎所有的现代浏览器都支持Data URL格式,包括火狐浏览器,谷歌浏览器,Safari浏览器,opera浏览器。IE8也支持,但有部分限制,IE9完全支持。
  • Data URL能用在很多场合,跟传统的外部资源引用方式相比,它有如下独到的用处:
    ①当访问外部资源很麻烦或受限时(这个比较鸡肋)
    ②当图片是在服务器端用程序动态生成,每个访问用户显示的都不同时(场景较少)
    ③当图片的体积太小,占用一个HTTP会话不是很值得时(雪碧图可以出场了)
  • Data URL也有一些不适用的场合:
    ①Base64编码的数据体积通常是原数据的体积4/3,也就是Data URL形式的图片会比二进制格式的图片体积大1/3
    ②Data URL形式的图片不会被浏览器缓存,这意味着每次访问这样页面时都被下载一次。这是一个使用效率方面的问题——尤其当这个图片被整个网站大量使用的时候。
  • 然而,Data URL这些不利的地方完全可以避免或转化:
    ① 在CSS里使用Data URL:通过CSS样式文件。CSS中的url操作符是用来指定网页元素的背景图片的,而浏览器并不在意URL里写的是什么——只要能通过它获取需要的数据。所以,我们就有了可以将Data URL形式的图片存储在CSS样式表中的可能。而所有浏览器都会积极的缓存CSS文件来提高页面加载效率。
  • 链接:Data URL 基本介绍

埋点

埋点大概分成2种:

  • 业务埋点:
    ①这里埋点的含义就是:预先在用户可能操作的"点",埋下上报的代码,一旦用户发生了操作,我就上报该用户操作的详细信息
    ②一般是要产品或者运营提出需求,在哪里埋点,比如
    1.进入某个界面,客户端上报"xx用户进入了xx页面"
    2.离开时再上报"xx用户离开了xx页面"
    ③本质上是跟踪用户的行为,用户什么时候打开了应用,点击了哪些标题/功能入口/广告,逗留了多长时间,这就是所谓的大数据了,可以分析出用户对什么样的内容感兴趣,从而更精准的向用户推荐内容,
    最好就是用户每一个操作都能上报给后台,用户不操作,也会触发上报,比如,“进入了xx页面n秒钟没有操作”
    ④要说明的是,这种埋点和具体你用哪种开发语言无关
  • 监控埋点:
    ①这种埋点不是给产品和运营分析用户的,是让开发/运维对自己的程序有个更精准的认识
    ②比如:
    1.定时采集服务器的cpu负载,内存占用情况,io负载,java 的 gc 信息
    2.程序执行某个功能的耗时,进行远程调用时的耗时
    3.程序在一段时间内捕捉到了哪些异常
    4.在一段时间内,远程接口的平均响应时间,请求次数,成功返回次数,失败次数,超时次数
    5.等等
    ③这种埋点有助于开发、运维分析程序的性能问题,监控程序的健康程度,提早进行异常的告警
    ④这样的埋点称为metric,grafana就是一款很优秀的开源的metric监控,你只需要定时把埋点数据提交给它,可以查看各项metric的统计曲线,并设定告警规则,当某个metric达到告警阈值,可以通过邮件、短信、即时通信程序(IM)向你推送告警信息
    ⑤由于这样的埋点对业务代码有很严重的侵入,所以很多公司会开发通用的埋点框架,采用反射等方式进行运行监控

你可能感兴趣的:(JavaEE,java,hibernate,spring)