diff --git a/.gitignore b/.gitignore
index 82eca33..d99f4ff 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,4 +22,5 @@
/nbbuild/
/dist/
/nbdist/
-/.nb-gradle/
\ No newline at end of file
+/.nb-gradle/
+/classes/
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 0a3aa2a..968b4f9 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -10,7 +10,7 @@
-
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__junit_junit_4_7.xml b/.idea/libraries/Maven__junit_junit_4_7.xml
deleted file mode 100644
index 1c50f8b..0000000
--- a/.idea/libraries/Maven__junit_junit_4_7.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/EasyCaptcha.iml b/EasyCaptcha.iml
index f1dd1f9..4e0729f 100644
--- a/EasyCaptcha.iml
+++ b/EasyCaptcha.iml
@@ -1,16 +1,34 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
\ No newline at end of file
diff --git a/src/main/java/com/wf/captcha/base/Captcha.java b/src/main/java/com/wf/captcha/base/Captcha.java
index e9565e3..712c5a4 100644
--- a/src/main/java/com/wf/captcha/base/Captcha.java
+++ b/src/main/java/com/wf/captcha/base/Captcha.java
@@ -1,12 +1,11 @@
package com.wf.captcha.base;
+import com.wf.captcha.utils.FontsUtil;
+
import java.awt.*;
import java.awt.geom.CubicCurve2D;
import java.awt.geom.QuadCurve2D;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
+import java.io.*;
import java.util.Base64;
/**
@@ -275,7 +274,7 @@ public abstract class Captcha extends Randoms {
}
public void setFont(int font, int style, float size) throws IOException, FontFormatException {
- this.font = Font.createFont(Font.TRUETYPE_FONT, new File(getClass().getResource("/" + FONT_NAMES[font]).getFile())).deriveFont(style, size);
+ this.font = FontsUtil.getFont(FONT_NAMES[font], style, size);
}
public int getLen() {
diff --git a/src/main/java/com/wf/captcha/servlet/CaptchaServlet.java b/src/main/java/com/wf/captcha/servlet/CaptchaServlet.java
index e273a03..2117759 100644
--- a/src/main/java/com/wf/captcha/servlet/CaptchaServlet.java
+++ b/src/main/java/com/wf/captcha/servlet/CaptchaServlet.java
@@ -1,5 +1,6 @@
package com.wf.captcha.servlet;
+import java.awt.*;
import java.io.IOException;
import javax.servlet.ServletException;
@@ -7,6 +8,9 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import com.wf.captcha.GifCaptcha;
+import com.wf.captcha.SpecCaptcha;
+import com.wf.captcha.base.Captcha;
import com.wf.captcha.utils.CaptchaUtil;
/**
@@ -18,7 +22,16 @@ public class CaptchaServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
- CaptchaUtil.out(request, response);
+// SpecCaptcha captcha = new SpecCaptcha(130, 48, 6);
+ GifCaptcha captcha = new GifCaptcha(130, 48, 6);
+
+ // 设置内置字体
+ try {
+ captcha.setFont(Captcha.FONT_10);
+ } catch (FontFormatException e) {
+ e.printStackTrace();
+ }
+ CaptchaUtil.out(captcha, request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
diff --git a/src/main/java/com/wf/captcha/utils/FileUtil.java b/src/main/java/com/wf/captcha/utils/FileUtil.java
new file mode 100644
index 0000000..41900dc
--- /dev/null
+++ b/src/main/java/com/wf/captcha/utils/FileUtil.java
@@ -0,0 +1,107 @@
+package com.wf.captcha.utils;
+
+import java.io.*;
+import java.util.Objects;
+
+/**
+ * 文件操作工具类,此类源码从org.apache.commons.io.FileUtils中复制
+ *
+ * @author zrh 455741807@qq.com
+ * @date 2022-05-07
+ */
+public class FileUtil {
+ public static final int DEFAULT_BUFFER_SIZE = 8192;
+ public static final int EOF = -1;
+
+ /**
+ * 文件流复制
+ * @param inputStream
+ * @param file
+ * @throws IOException
+ */
+ public static void copyToFile(final InputStream inputStream, final File file) throws IOException {
+ try (OutputStream out = openOutputStream(file)) {
+ copy(inputStream, out);
+ }
+ }
+
+ public static FileOutputStream openOutputStream(final File file) throws IOException {
+ return openOutputStream(file, false);
+ }
+
+ public static FileOutputStream openOutputStream(final File file, final boolean append) throws IOException {
+ Objects.requireNonNull(file, "file");
+ if (file.exists()) {
+ requireFile(file, "file");
+ requireCanWrite(file, "file");
+ } else {
+ createParentDirectories(file);
+ }
+ return new FileOutputStream(file, append);
+ }
+
+ private static File requireFile(final File file, final String name) {
+ Objects.requireNonNull(file, name);
+ if (!file.isFile()) {
+ throw new IllegalArgumentException("Parameter '" + name + "' is not a file: " + file);
+ }
+ return file;
+ }
+
+ private static void requireCanWrite(final File file, final String name) {
+ Objects.requireNonNull(file, "file");
+ if (!file.canWrite()) {
+ throw new IllegalArgumentException("File parameter '" + name + " is not writable: '" + file + "'");
+ }
+ }
+
+ public static File createParentDirectories(final File file) throws IOException {
+ return mkdirs(getParentFile(file));
+ }
+
+ private static File mkdirs(final File directory) throws IOException {
+ if ((directory != null) && (!directory.mkdirs() && !directory.isDirectory())) {
+ throw new IOException("Cannot create directory '" + directory + "'.");
+ }
+ return directory;
+ }
+
+ private static File getParentFile(final File file) {
+ return file == null ? null : file.getParentFile();
+ }
+
+ public static int copy(final InputStream inputStream, final OutputStream outputStream) throws IOException {
+ final long count = copyLarge(inputStream, outputStream);
+ if (count > Integer.MAX_VALUE) {
+ return EOF;
+ }
+ return (int) count;
+ }
+
+ public static long copyLarge(final InputStream inputStream, final OutputStream outputStream)
+ throws IOException {
+ return copy(inputStream, outputStream, DEFAULT_BUFFER_SIZE);
+ }
+
+ public static long copy(final InputStream inputStream, final OutputStream outputStream, final int bufferSize)
+ throws IOException {
+ return copyLarge(inputStream, outputStream, byteArray(bufferSize));
+ }
+
+ public static long copyLarge(final InputStream inputStream, final OutputStream outputStream, final byte[] buffer)
+ throws IOException {
+ Objects.requireNonNull(inputStream, "inputStream");
+ Objects.requireNonNull(outputStream, "outputStream");
+ long count = 0;
+ int n;
+ while (EOF != (n = inputStream.read(buffer))) {
+ outputStream.write(buffer, 0, n);
+ count += n;
+ }
+ return count;
+ }
+
+ public static byte[] byteArray(final int size) {
+ return new byte[size];
+ }
+}
diff --git a/src/main/java/com/wf/captcha/utils/FontsUtil.java b/src/main/java/com/wf/captcha/utils/FontsUtil.java
new file mode 100644
index 0000000..29ae619
--- /dev/null
+++ b/src/main/java/com/wf/captcha/utils/FontsUtil.java
@@ -0,0 +1,75 @@
+package com.wf.captcha.utils;
+
+import sun.security.action.GetPropertyAction;
+
+import java.awt.*;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static java.security.AccessController.doPrivileged;
+
+/**
+ * 解决自定义字体读取时,产生.tmp临时文件耗磁盘的问题。
+ *
+ * 解决思路:
+ * Font类的createFont有个重载方法–>java.awt.Font#createFont(int, java.io.File),
+ * 不产生临时文件获取字体代码实现
+ *
+ * URL url = FontLoader.class.getResource("font/SourceHanSansCN-Regular.otf");
+ * String pathString = url.getFile();
+ * Font selfFont = Font.createFont(Font.TRUETYPE_FONT, new File(pathString));
+ *
+ * 上面的解决方案会导致另一个问题,字体文件在生产环境是在jar包里,部分操作系统环境下,直接读取读取不到,只能通过流的方式获取。
+ *
+ * 因此,本方案采用的办法是把jar包中的字体文件复制到java.io.tmpdir临时文件夹中
+ * ,再采用java.awt.Font#createFont(int, java.io.File)的方式产生字体,既解决了临时文件tmp消耗磁盘的问题,也解决了
+ * 部分操作系统下读不到文件的问题。
+ *
+ * @author zrh 455741807@qq.com
+ * @date 2022-05-07
+ *
+ */
+public class FontsUtil {
+ private static final Path tmpdir = Paths.get(doPrivileged(new GetPropertyAction("java.io.tmpdir")));
+
+ /**
+ * 手动复制字体文件到临时目录. 调用传文件的构造方法创建字体
+ * @param fontName 字体文件名称
+ * @return
+ */
+ public static Font getFont(String fontName, int style, float size) {
+ Font font = null;
+
+ File tempFontFile = new File(tmpdir.toUri().getPath() + fontName);
+ if(!tempFontFile.exists()){
+ //临时文件不存在
+ copyTempFontFile(fontName, tempFontFile);
+ }
+ if(tempFontFile.exists()) {
+ try {
+ font = Font.createFont(Font.TRUETYPE_FONT, tempFontFile).deriveFont(style, size);;
+ } catch (FontFormatException | IOException e) {
+ e.printStackTrace();
+ tempFontFile.delete();
+ }
+ }
+ return font;
+ }
+
+ /**
+ * 复制字体文件到临时文件目录
+ * @param fontName
+ * @param tempFontFile
+ */
+ private static synchronized void copyTempFontFile(String fontName, File tempFontFile){
+ try(InputStream is = FontsUtil.class.getResourceAsStream("/" + fontName)){
+ FileUtil.copyToFile(is, tempFontFile);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/web/WEB-INF/web.xml b/web/WEB-INF/web.xml
new file mode 100644
index 0000000..ebe475a
--- /dev/null
+++ b/web/WEB-INF/web.xml
@@ -0,0 +1,15 @@
+
+
+
+
+ CaptchaServlet
+ com.wf.captcha.servlet.CaptchaServlet
+
+
+ CaptchaServlet
+ /captcha
+
+
\ No newline at end of file
diff --git a/web/index.html b/web/index.html
new file mode 100644
index 0000000..607f9de
--- /dev/null
+++ b/web/index.html
@@ -0,0 +1,10 @@
+
+
+
+
+ 验证码测试
+
+
+
+
+
\ No newline at end of file