Compare commits
4 Commits
61cb1dec77
...
ddee3af2c1
Author | SHA1 | Date |
---|---|---|
|
ddee3af2c1 | |
|
423a8962bb | |
|
d546287891 | |
|
66449ed821 |
21
pom.xml
21
pom.xml
|
@ -48,6 +48,20 @@
|
|||
<version>0.9.5.5</version> <!-- 最新版本请在 Maven 仓库查看 -->
|
||||
</dependency>
|
||||
|
||||
<!-- Commons FileUpload -->
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
<version>1.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Commons IO -->
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.11.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
<!-- JSTL -->
|
||||
|
@ -65,6 +79,13 @@
|
|||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.10.1</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- JSP Implementation (optional, usually provided by your server) -->
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat</groupId>
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package example.controller;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Random;
|
||||
|
||||
@WebServlet("/captcha")
|
||||
public class CaptchaServlet extends HttpServlet {
|
||||
|
||||
// 处理生成验证码图片的请求
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
// 设置响应类型为图片
|
||||
response.setContentType("image/jpeg");
|
||||
|
||||
// 设置验证码内容
|
||||
String captchaText = generateCaptchaText();
|
||||
|
||||
// 将验证码存储到 session 中
|
||||
request.getSession().setAttribute("captcha", captchaText);
|
||||
|
||||
// 创建验证码图片
|
||||
BufferedImage image = new BufferedImage(100, 40, BufferedImage.TYPE_INT_RGB);
|
||||
Graphics2D graphics = image.createGraphics();
|
||||
graphics.setColor(Color.WHITE);
|
||||
graphics.fillRect(0, 0, 100, 40);
|
||||
graphics.setFont(new Font("Arial", Font.BOLD, 30));
|
||||
graphics.setColor(Color.BLACK);
|
||||
graphics.drawString(captchaText, 10, 30);
|
||||
|
||||
// 输出验证码图片
|
||||
OutputStream out = response.getOutputStream();
|
||||
javax.imageio.ImageIO.write(image, "JPEG", out);
|
||||
out.close();
|
||||
}
|
||||
|
||||
// 生成随机的验证码文本
|
||||
private String generateCaptchaText() {
|
||||
String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
StringBuilder captcha = new StringBuilder();
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int index = random.nextInt(characters.length());
|
||||
captcha.append(characters.charAt(index));
|
||||
}
|
||||
return captcha.toString();
|
||||
}
|
||||
|
||||
// 检查用户提交的验证码是否正确(忽略大小写)
|
||||
public static boolean validateCaptcha(HttpServletRequest request, String userInputCaptcha) {
|
||||
String sessionCaptcha = (String) request.getSession().getAttribute("captcha");
|
||||
if (sessionCaptcha == null) {
|
||||
return false; // 验证码已过期或不存在
|
||||
}
|
||||
return sessionCaptcha.equalsIgnoreCase(userInputCaptcha);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package example.controller;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet("/download")
|
||||
public class FileDownloadServlet extends HttpServlet {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// 设置文件上传路径(webapp/uploads)
|
||||
private static final String UPLOAD_DIRECTORY = "uploads";
|
||||
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
|
||||
// 动态解析 webapp/uploads 的路径
|
||||
String uploadPath = getServletContext().getRealPath("/") + UPLOAD_DIRECTORY;
|
||||
|
||||
// 获取请求的文件名
|
||||
String fileName = request.getParameter("file");
|
||||
if (fileName == null || fileName.isEmpty()) {
|
||||
response.getWriter().println("File parameter is missing");
|
||||
return;
|
||||
}
|
||||
|
||||
// 构造文件的完整路径
|
||||
File file = new File(uploadPath + File.separator + fileName);
|
||||
|
||||
// 检查文件是否存在
|
||||
if (!file.exists()) {
|
||||
response.getWriter().println("File not found: " + fileName);
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置响应的内容类型
|
||||
response.setContentType(getServletContext().getMimeType(file.getName()));
|
||||
response.setContentLength((int) file.length());
|
||||
response.setHeader("Content-Disposition", "inline; filename=\"" + fileName + "\"");
|
||||
|
||||
// 读取文件并写入到响应输出流
|
||||
try (FileInputStream fis = new FileInputStream(file);
|
||||
OutputStream os = response.getOutputStream()) {
|
||||
byte[] buffer = new byte[4096];
|
||||
int bytesRead;
|
||||
while ((bytesRead = fis.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package example.controller;
|
||||
|
||||
import example.model.Result;
|
||||
import example.model.User;
|
||||
import example.service.IUserService;
|
||||
import example.service.impl.UserServiceImpl;
|
||||
|
@ -18,21 +19,29 @@ public class LoginServlet extends HttpServlet {
|
|||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
resp.setContentType("text/html;charset=utf-8");
|
||||
resp.setContentType("application/json;charset=utf-8");
|
||||
req.setCharacterEncoding("utf-8");
|
||||
|
||||
String username = req.getParameter("username");
|
||||
String password = req.getParameter("password");
|
||||
String captcha = req.getParameter("captcha");
|
||||
|
||||
try {
|
||||
if (!captcha.equalsIgnoreCase((String) req.getSession().getAttribute("captcha"))) {
|
||||
resp.getWriter().write(toJson(Result.error("验证码错误")));
|
||||
return;
|
||||
}
|
||||
|
||||
User user = userService.login(username, password);
|
||||
if(user!=null){
|
||||
req.getSession().setAttribute("user",user);
|
||||
resp.sendRedirect("/computer?action=list");
|
||||
}else{
|
||||
req.getSession().setAttribute("msg","用户名或密码错误");
|
||||
resp.sendRedirect("/msg.jsp");
|
||||
if (user != null) {
|
||||
req.getSession().setAttribute("user", user);
|
||||
resp.getWriter().write(toJson(Result.success("登录成功")));
|
||||
} else {
|
||||
resp.getWriter().write(toJson(Result.error("用户名或密码错误")));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
e.printStackTrace();
|
||||
resp.getWriter().write(toJson(Result.error("系统错误,请稍后重试")));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,4 +49,10 @@ public class LoginServlet extends HttpServlet {
|
|||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
resp.sendRedirect("/login.jsp");
|
||||
}
|
||||
|
||||
private String toJson(Object object) {
|
||||
// 使用简单的 JSON 序列化方式,实际可以使用 Jackson 或 Gson 库
|
||||
return new com.google.gson.Gson().toJson(object);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
package example.controller;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.fileupload.FileItem;
|
||||
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
|
||||
import org.apache.commons.fileupload.servlet.ServletFileUpload;
|
||||
|
||||
@WebServlet("/UploadServlet")
|
||||
public class UploadServlet extends HttpServlet {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// 设置上传目录
|
||||
private static final String UPLOAD_DIRECTORY = "uploads";
|
||||
|
||||
// 上传配置
|
||||
private static final int MEMORY_THRESHOLD = 1024 * 1024 * 3; // 3MB
|
||||
private static final int MAX_FILE_SIZE = 1024 * 1024 * 40; // 40MB
|
||||
private static final int MAX_REQUEST_SIZE = 1024 * 1024 * 50; // 50MB
|
||||
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
|
||||
// 检查请求是否为多部分内容
|
||||
if (!ServletFileUpload.isMultipartContent(request)) {
|
||||
response.getWriter().println("Error: Form must have enctype=multipart/form-data.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 配置上传参数
|
||||
DiskFileItemFactory factory = new DiskFileItemFactory();
|
||||
factory.setSizeThreshold(MEMORY_THRESHOLD);
|
||||
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
|
||||
|
||||
ServletFileUpload upload = new ServletFileUpload(factory);
|
||||
upload.setFileSizeMax(MAX_FILE_SIZE);
|
||||
upload.setSizeMax(MAX_REQUEST_SIZE);
|
||||
|
||||
// 构造上传路径
|
||||
String uploadPath = getServletContext().getRealPath("") + File.separator + UPLOAD_DIRECTORY;
|
||||
|
||||
// 如果目录不存在,则创建
|
||||
File uploadDir = new File(uploadPath);
|
||||
if (!uploadDir.exists()) {
|
||||
uploadDir.mkdir();
|
||||
}
|
||||
|
||||
try {
|
||||
// 解析请求的内容
|
||||
@SuppressWarnings("unchecked")
|
||||
List<FileItem> formItems = upload.parseRequest(request);
|
||||
|
||||
if (formItems != null && formItems.size() > 0) {
|
||||
for (FileItem item : formItems) {
|
||||
// 处理非表单字段
|
||||
if (!item.isFormField()) {
|
||||
String fileName = new File(item.getName()).getName();
|
||||
String filePath = uploadPath + File.separator + fileName;
|
||||
File storeFile = new File(filePath);
|
||||
|
||||
// 保存文件到磁盘
|
||||
item.write(storeFile);
|
||||
|
||||
request.setAttribute("message", "文件上传成功: " + fileName);
|
||||
request.setAttribute("fileName",fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
request.setAttribute("message", "错误信息: " + ex.getMessage());
|
||||
}
|
||||
|
||||
// 转发到 JSP 显示消息
|
||||
getServletContext().getRequestDispatcher("/msg.jsp").forward(request, response);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package example.model;
|
||||
|
||||
public class Result<T> {
|
||||
private String status; // "success" 或 "error"
|
||||
private String message; // 消息内容
|
||||
private T data; // 附加数据
|
||||
|
||||
public Result(String status, String message, T data) {
|
||||
this.status = status;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Result(String status, String message) {
|
||||
this(status, message, null);
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public static <T> Result<T> success(String message, T data) {
|
||||
return new Result<>("success", message, data);
|
||||
}
|
||||
|
||||
public static <T> Result<T> success(String message) {
|
||||
return success(message, null);
|
||||
}
|
||||
|
||||
public static <T> Result<T> error(String message) {
|
||||
return new Result<>("error", message, null);
|
||||
}
|
||||
}
|
|
@ -28,6 +28,13 @@
|
|||
</c:if>
|
||||
</div>
|
||||
|
||||
<form action="UploadServlet" method="post" enctype="multipart/form-data">
|
||||
<label for="file">选择图片:</label>
|
||||
<input type="file" name="file" id="file" required>
|
||||
<button type="submit">上传</button>
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -1,23 +1,61 @@
|
|||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<script src="https://www.liyansheng.top/cdn/watermark.js"></script>
|
||||
</head>
|
||||
<head>
|
||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
// 绑定表单提交事件
|
||||
$('#loginForm').submit(function (event) {
|
||||
event.preventDefault(); // 阻止表单默认提交行为
|
||||
|
||||
<body>
|
||||
<h2>-电脑商城-用户登录</h2>
|
||||
<form action="login" method="post">
|
||||
<label for="username">用户名:</label>
|
||||
<input type="text" id="username" name="username" required><br><br>
|
||||
<label for="password">密码:</label>
|
||||
<input type="password" id="password" name="password" required><br><br>
|
||||
<button type="submit">登录</button>
|
||||
<a href="/register">没有账号?去注册</a>
|
||||
</form>
|
||||
<br>
|
||||
${requestScope.msg}
|
||||
</body>
|
||||
// 获取表单数据
|
||||
const formData = $(this).serialize();
|
||||
|
||||
</html>
|
||||
// 异步请求
|
||||
$.ajax({
|
||||
url: '/login',
|
||||
type: 'POST',
|
||||
data: formData,
|
||||
dataType: 'json',
|
||||
success: function (response) {
|
||||
if (response.status === 'success') {
|
||||
alert(response.message);
|
||||
window.location.href = '/computer?action=list'; // 跳转至主页
|
||||
} else {
|
||||
$('#message').text(response.message).css('color', 'red');
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
$('#message').text('请求失败,请稍后重试').css('color', 'red');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 刷新验证码
|
||||
$('#captchaImage').click(function () {
|
||||
$(this).attr('src', '/captcha?timestamp=' + new Date().getTime());
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>-电脑商城-用户登录</h2>
|
||||
<form id="loginForm">
|
||||
<label for="username">用户名:</label>
|
||||
<input type="text" id="username" name="username" required><br><br>
|
||||
<label for="password">密码:</label>
|
||||
<input type="password" id="password" name="password" required><br><br>
|
||||
<label for="captcha">验证码</label>
|
||||
<input type="text" id="captcha" name="captcha" required>
|
||||
<img id="captchaImage" src="/captcha" alt="验证码" style="cursor: pointer;" title="点击刷新验证码"><br><br>
|
||||
<button type="submit">登录</button>
|
||||
<a href="/register">没有账号?去注册</a>
|
||||
</form>
|
||||
<br>
|
||||
<p id="message"></p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
@ -9,6 +9,11 @@
|
|||
<body>
|
||||
<h2>提示:</h2>
|
||||
<h3>${sessionScope.msg}</h3>
|
||||
<h3>${message}</h3>
|
||||
<!-- 动态生成图片标签 -->
|
||||
<c:if test="${not empty fileName}">
|
||||
<img src="/download?file=/${fileName}" alt="Uploaded Image" style="max-width: 100%; height: auto;">
|
||||
</c:if>
|
||||
<button onclick="window.history.back();">返回</button>
|
||||
|
||||
</body>
|
||||
|
|
Reference in New Issue