From 24d0bfb74492b0db2a073830be36bddda79a1e46 Mon Sep 17 00:00:00 2001 From: rain <3363779424@qq.com> Date: Wed, 13 Aug 2025 11:13:27 +0800 Subject: [PATCH] =?UTF-8?q?=E2=80=9C=E6=8F=90=E4=BA=A4=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 38 ++ .idea/.gitignore | 8 + .idea/dataSources.xml | 30 + .idea/encodings.xml | 7 + .idea/misc.xml | 14 + .idea/uiDesigner.xml | 124 ++++ .idea/webContexts.xml | 10 + pom.xml | 239 ++++++++ src/main/java/cn/star/common/ApiResponse.java | 60 ++ .../cn/star/controller/UserController.java | 178 ++++++ src/main/java/cn/star/dao/UsersDao.java | 24 + src/main/java/cn/star/domian/Users.java | 45 ++ .../cn/star/interceptor/TokenInterceptor.java | 91 +++ .../java/cn/star/service/UsersService.java | 15 + .../star/service/impl/UsersServiceImpl.java | 38 ++ src/main/java/cn/star/test/MybatisTest.java | 61 ++ src/main/java/cn/star/test/SpringTest.java | 18 + src/main/java/cn/star/util/JwtUtil.java | 79 +++ src/main/java/cn/star/util/RedisUtil.java | 567 ++++++++++++++++++ src/main/resources/application-redis.xml | 66 ++ src/main/resources/jdbc.properties | 4 + src/main/resources/log4j.properties | 18 + src/main/resources/mybatis.xml | 23 + src/main/resources/redis.properties | 18 + src/main/resources/spring-mvc.xml | 41 ++ src/main/resources/spring.xml | 45 ++ src/main/webapp/WEB-INF/pages/Users.jsp | 18 + src/main/webapp/WEB-INF/pages/falselogin.jsp | 17 + src/main/webapp/WEB-INF/pages/success.jsp | 17 + .../webapp/WEB-INF/pages/successlogin.jsp | 17 + src/main/webapp/WEB-INF/web.xml | 47 ++ src/main/webapp/images | 0 src/main/webapp/index.jsp | 94 +++ src/main/webapp/static/css/styles.css | 7 + 34 files changed, 2078 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/dataSources.xml create mode 100644 .idea/encodings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/uiDesigner.xml create mode 100644 .idea/webContexts.xml create mode 100644 pom.xml create mode 100644 src/main/java/cn/star/common/ApiResponse.java create mode 100644 src/main/java/cn/star/controller/UserController.java create mode 100644 src/main/java/cn/star/dao/UsersDao.java create mode 100644 src/main/java/cn/star/domian/Users.java create mode 100644 src/main/java/cn/star/interceptor/TokenInterceptor.java create mode 100644 src/main/java/cn/star/service/UsersService.java create mode 100644 src/main/java/cn/star/service/impl/UsersServiceImpl.java create mode 100644 src/main/java/cn/star/test/MybatisTest.java create mode 100644 src/main/java/cn/star/test/SpringTest.java create mode 100644 src/main/java/cn/star/util/JwtUtil.java create mode 100644 src/main/java/cn/star/util/RedisUtil.java create mode 100644 src/main/resources/application-redis.xml create mode 100644 src/main/resources/jdbc.properties create mode 100644 src/main/resources/log4j.properties create mode 100644 src/main/resources/mybatis.xml create mode 100644 src/main/resources/redis.properties create mode 100644 src/main/resources/spring-mvc.xml create mode 100644 src/main/resources/spring.xml create mode 100644 src/main/webapp/WEB-INF/pages/Users.jsp create mode 100644 src/main/webapp/WEB-INF/pages/falselogin.jsp create mode 100644 src/main/webapp/WEB-INF/pages/success.jsp create mode 100644 src/main/webapp/WEB-INF/pages/successlogin.jsp create mode 100644 src/main/webapp/WEB-INF/web.xml create mode 100644 src/main/webapp/images create mode 100644 src/main/webapp/index.jsp create mode 100644 src/main/webapp/static/css/styles.css diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000..1e33fbb --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,30 @@ + + + + + mysql_aurora_aws + true + software.aws.rds.jdbc.mysql.Driver + jdbc:mysql:aws://localhost:3306 + + + + + + + $ProjectFileDir$ + + + redis + true + jdbc.RedisDriver + jdbc:redis://localhost:6379/0 + + + + + + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..4731638 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/webContexts.xml b/.idea/webContexts.xml new file mode 100644 index 0000000..f4124c7 --- /dev/null +++ b/.idea/webContexts.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..c0c32e3 --- /dev/null +++ b/pom.xml @@ -0,0 +1,239 @@ + + + + 4.0.0 + + com.xs + myssm + war + 1.0-SNAPSHOT + + myssm Maven Webapp + http://maven.apache.org + + + UTF-8 + 11 + 11 + 5.0.2.RELEASE + 1.6.6 + 1.2.12 + 8.0.33 + 3.4.5 + + + + + + + org.aspectj + aspectjweaver + 1.6.8 + + + + org.springframework + spring-aop + ${spring.version} + + + + org.springframework + spring-context + ${spring.version} + + + + org.springframework + spring-web + ${spring.version} + + + + + org.springframework + spring-webmvc + ${spring.version} + + + + org.springframework + spring-test + ${spring.version} + + + + org.springframework + spring-tx + ${spring.version} + + + + org.springframework + spring-jdbc + ${spring.version} + + + + org.springframework + spring-core + 5.3.27 + + + + mysql + mysql-connector-java + ${mysql.version} + + + + javax.servlet + servlet-api + 2.5 + provided + + + + javax.servlet.jsp + jsp-api + 2.0 + provided + + + + jstl + jstl + 1.2 + + + + + log4j + log4j + ${log4j.version} + + + + org.slf4j + slf4j-api + ${slf4j.version} + + + + org.slf4j + slf4j-log4j12 + ${slf4j.version} + + + + org.mybatis + mybatis + ${mybatis.version} + + + + org.mybatis + mybatis-spring + 1.3.0 + + + + c3p0 + c3p0 + 0.9.1.2 + jar + compile + + + junit + junit + 4.13.2 + compile + + + + javax.annotation + javax.annotation-api + 1.3.2 + + + + com.github.whvcse + easy-captcha + 1.6.2 + + + + redis.clients + jedis + 3.8.0 + + + org.springframework.data + spring-data-redis + 2.7.11 + + + + com.auth0 + java-jwt + 3.4.0 + + + + com.alibaba + fastjson + 1.2.76 + + + + myssm + + + + maven-clean-plugin + 3.1.0 + + + + maven-resources-plugin + 3.0.2 + + + maven-compiler-plugin + 3.8.0 + + + maven-surefire-plugin + 2.22.1 + + + maven-war-plugin + 3.2.2 + + + maven-install-plugin + 2.5.2 + + + maven-deploy-plugin + 2.8.2 + + + + + + org.apache.tomcat.maven + tomcat7-maven-plugin + 2.2 + + + 8080 + / + UTF-8 + + + + + diff --git a/src/main/java/cn/star/common/ApiResponse.java b/src/main/java/cn/star/common/ApiResponse.java new file mode 100644 index 0000000..bb9c2ad --- /dev/null +++ b/src/main/java/cn/star/common/ApiResponse.java @@ -0,0 +1,60 @@ +package cn.star.common; + +public class ApiResponse { + // 状态码:200表示成功,其他表示错误 + private int code; + // 响应消息:成功或错误描述 + private String message; + // 响应数据:成功时返回的数据 + private T data; + + // 无参构造方法(JSON序列化需要) + public ApiResponse() {} + + // 全参构造方法 + public ApiResponse(int code, String message, T data) { + this.code = code; + this.message = message; + this.data = data; + } + + // 静态方法:快速创建成功响应(带数据) + public static ApiResponse success(T data) { + return new ApiResponse<>(200, "操作成功", data); + } + + // 静态方法:快速创建成功响应(无数据) + public static ApiResponse success() { + return new ApiResponse<>(200, "操作成功", null); + } + + // 静态方法:快速创建错误响应 + public static ApiResponse error(int code, String message) { + return new ApiResponse<>(code, message, null); + } + + // getter和setter方法(JSON序列化需要) + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } +} diff --git a/src/main/java/cn/star/controller/UserController.java b/src/main/java/cn/star/controller/UserController.java new file mode 100644 index 0000000..a3516c3 --- /dev/null +++ b/src/main/java/cn/star/controller/UserController.java @@ -0,0 +1,178 @@ +package cn.star.controller; + +//创建用户控制层UserController类 + + +import cn.star.domian.Users; +import cn.star.service.UsersService; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + + +import javax.imageio.ImageIO; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.awt.*; +import java.awt.font.FontRenderContext; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import javax.servlet.ServletOutputStream; +import java.io.IOException; +import java.util.List; +import java.util.Random; + +@Controller +@RequestMapping("/users") +public class UserController { + @Autowired + private UsersService usersService; + + private static final Logger logger = LoggerFactory.getLogger(UserController.class); + + @RequestMapping("/findUsers") + /*public String findUsers() { + System.out.println("表现层:查询用户"); + //调用service对象得方法进行测试 + usersService.findUsers(); + return "Users"; + }*/ + public String findUsers(Model model) { + System.out.println("表现层:查询用户"); + List list = usersService.findUsers(); + model.addAttribute("list",list); + return "Users"; + } + + @RequestMapping("/insert") + public String insert(Users users) { + System.out.println("注册"); + usersService.insertUsers(users); + return "success"; + } + + @RequestMapping("/login") + public String login(HttpServletRequest request, HttpSession session, RedirectAttributes redirectAttributes) + { + //先获取请求参数-验证码、账号、密码 + String verifyCode = request.getParameter("verifyCode"); + String username = request.getParameter("username"); + String password = request.getParameter("password"); + + //获取session中存储的验证码 + String sessionVerifyCode = (String) session.getAttribute("verifyCodeValue"); + + //执行你的验证码校验 + if (!verifyCode.equals(sessionVerifyCode)) { + logger.info("登陆失败,验证码输入有误"); + redirectAttributes.addFlashAttribute("message", "验证码输入有误"); + return "falselogin"; + } + //验证用户名密码 + Users users = new Users(); + users.setUsername(username); + users.setPassword(password); + if(usersService.login(users)) { + session.setAttribute("users",users); + return "successlogin"; + } + else { + redirectAttributes.addFlashAttribute("message","用户名或密码错误"); + return "falselogin"; + } + + + +} + /*System.out.println("登录"); + if(usersService.login(users)) { + return "successlogin"; + } + else { + return "falselogin"; + }*/ + + + /* 获取校验码 */ + @RequestMapping("/getVerifyCode") + public void generate(HttpServletResponse response, HttpSession session) { + response.setContentType("image/jpeg");//保证浏览器正确解析图片 + ByteArrayOutputStream output = new ByteArrayOutputStream(); + String verifyCodeValue = drawImg(output); + // 将校验码保存到session中 + session.setAttribute("verifyCodeValue", verifyCodeValue); + + try { + ServletOutputStream out = response.getOutputStream(); + output.writeTo(out); + } catch (IOException e) { + logger.info("<--验证码前端写出.出现异常-->"); + e.printStackTrace(); + + } + } + + /* 绘制验证码 */ + private String drawImg(ByteArrayOutputStream output) { + String code = ""; + // 随机产生4个字符 + for (int i = 0; i < 4; i++) { + code += randomChar(); + } + int width = 70; + int height = 25; + BufferedImage bi = new BufferedImage(width, height, + BufferedImage.TYPE_3BYTE_BGR); + Font font = new Font("Times New Roman", Font.PLAIN, 20); + // 调用Graphics2D绘画验证码 + Graphics2D g = bi.createGraphics(); + g.setFont(font); + Color color = new Color(66, 2, 82); + g.setColor(color); + g.setBackground(new Color(226, 226, 240)); + g.clearRect(0, 0, width, height); + FontRenderContext context = g.getFontRenderContext(); + Rectangle2D bounds = font.getStringBounds(code, context); + double x = (width - bounds.getWidth()) / 2; + double y = (height - bounds.getHeight()) / 2; + double ascent = bounds.getY(); + double baseY = y - ascent; + g.drawString(code, (int) x, (int) baseY); + g.dispose(); + try { + ImageIO.write(bi, "jpg", output); + } catch (IOException e) { + e.printStackTrace(); + } + return code; + } + + /* 获取随机参数 */ + private char randomChar() { + Random r = new Random(); + String s = "ABCDEFGHJKLMNPRSTUVWXYZ0123456789"; + return s.charAt(r.nextInt(s.length())); + } + + /*@Resource + private RedisUtil redisUtil; + + @RequestMapping("/test") + public String testRedis() { + if(!redisUtil.hasKey("test01")) { + redisUtil.set("test01","测试redis"); + } + System.out.println(redisUtil.get("test01")); + return "success"; + }*/ + + +} diff --git a/src/main/java/cn/star/dao/UsersDao.java b/src/main/java/cn/star/dao/UsersDao.java new file mode 100644 index 0000000..f37f3bd --- /dev/null +++ b/src/main/java/cn/star/dao/UsersDao.java @@ -0,0 +1,24 @@ +package cn.star.dao; + +import cn.star.domian.Users; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Select; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository//注入dao数据 +//这里是创建一个数据访问层UserDao接口 +public interface UsersDao { + //查询所有用户 + @Select("select * from users") + public List findUsers(); + //用户注册 + @Insert("INSERT INTO USERS (username,password) VALUES(#{username},#{password})") + public void insertUsers(Users users); + //用户登录 + @Select("select * from users where username=#{username} and password=#{password}") + public Users login(Users users); + +} diff --git a/src/main/java/cn/star/domian/Users.java b/src/main/java/cn/star/domian/Users.java new file mode 100644 index 0000000..8eab617 --- /dev/null +++ b/src/main/java/cn/star/domian/Users.java @@ -0,0 +1,45 @@ +package cn.star.domian; + +import java.io.Serializable; + +public class Users implements Serializable { + private Integer id; + private String username; + private String password; + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + //这段代码都敲不明白 + @Override + public String toString(){ + return "Users{" + + "id=" + id + + ", username='" + username + '\'' + + ", password='" + password + '\'' + + '}'; + } +} diff --git a/src/main/java/cn/star/interceptor/TokenInterceptor.java b/src/main/java/cn/star/interceptor/TokenInterceptor.java new file mode 100644 index 0000000..d60b01c --- /dev/null +++ b/src/main/java/cn/star/interceptor/TokenInterceptor.java @@ -0,0 +1,91 @@ +/*package cn.star.interceptor; + +import cn.star.common.ApiResponse; +import cn.star.util.JwtUtil; +import com.alibaba.fastjson.JSONObject; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Map; + +public class TokenInterceptor implements HandlerInterceptor { + + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { + + // 只处理HandlerMethod类型的处理器(排除静态资源等) + if (!(handler instanceof HandlerMethod)) { + return true; + } + + System.out.println("执行方法之前执行这步操作"); + response.setCharacterEncoding("utf-8"); + + Cookie cookie = getCookieByName(request,"COOKIE_NAME"); + + if(null != cookie) { + boolean result = JwtUtil.verify(cookie.getValue()); + if(!result) { + response.sendRedirect(request.getContextPath() + "/login"); + return false; + } + return true; + } + else { + response.sendRedirect(request.getContextPath() + "/login"); + + return false; + } + } + + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) + throws Exception { + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {} + + //根据名字获取cookie + public static Cookie getCookieByName(HttpServletRequest request , String name) { + Map cookieMap = ReadCookieMap(request); + if (cookieMap.containsKey(name)) { + Cookie cookie = cookieMap.get(name); + return cookie; + } + else { + return null; + } + } + + private static Map ReadCookieMap(HttpServletRequest request) { + Map cookieMap = new HashMap(); + Cookie[] cookies = request.getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + cookieMap.put(cookie.getName(), cookie); + } + } + return cookieMap; + } + + private void responseMessage(HttpServletRequest request, HttpServletResponse response, PrintWriter out, ApiResponse apiResponse) + throws IOException + { + response.setContentType("text/html;charset=utf-8"); + out.print(JSONObject.toJSONString(apiResponse));//这个ApiResponse需要创建一个类然后调用 + out.flush(); + out.close(); + } + + + + + +}*/ diff --git a/src/main/java/cn/star/service/UsersService.java b/src/main/java/cn/star/service/UsersService.java new file mode 100644 index 0000000..fd5dcee --- /dev/null +++ b/src/main/java/cn/star/service/UsersService.java @@ -0,0 +1,15 @@ +package cn.star.service; + +import cn.star.domian.Users; + +import java.util.List; + +//创建一个业务层UsersService接口 +public interface UsersService { + //查询所有用户 + public List findUsers(); + //用户注册 + public void insertUsers(Users users); + //用户登录 + public boolean login(Users users); +} diff --git a/src/main/java/cn/star/service/impl/UsersServiceImpl.java b/src/main/java/cn/star/service/impl/UsersServiceImpl.java new file mode 100644 index 0000000..17693a6 --- /dev/null +++ b/src/main/java/cn/star/service/impl/UsersServiceImpl.java @@ -0,0 +1,38 @@ +package cn.star.service.impl; + +import cn.star.dao.UsersDao; +import cn.star.domian.Users; +import cn.star.service.UsersService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service("usersService")//把service交给IOC容器管理 +public class UsersServiceImpl implements UsersService { + @Autowired + private UsersDao usersDao;//注入dao得数据 + + @Override + public List findUsers() { + System.out.println("业务层:查询用户"); + return usersDao.findUsers();//改 + } + + @Override + public void insertUsers(Users users) { + System.out.println("业务层:用户注册"); + usersDao.insertUsers(users);//有修改 + } + + @Override + public boolean login(Users users) { + System.out.println("业务层:用户登录"); + if(usersDao.login(users) == null) { + return false; + } + else { + return true; + }//有修改 + } +} diff --git a/src/main/java/cn/star/test/MybatisTest.java b/src/main/java/cn/star/test/MybatisTest.java new file mode 100644 index 0000000..b7a1350 --- /dev/null +++ b/src/main/java/cn/star/test/MybatisTest.java @@ -0,0 +1,61 @@ +package cn.star.test; + +import cn.star.dao.UsersDao; +import cn.star.domian.Users; +import org.apache.ibatis.io.Resources; +import org.apache.ibatis.session.SqlSession; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.session.SqlSessionFactoryBuilder; +import org.junit.Test; + +import java.io.InputStream; +import java.util.List; + +//测试用户查询和注册,创建测试类 +public class MybatisTest { + + @Test + public void run1() throws Exception { + //加载配置文件 + InputStream in = Resources.getResourceAsStream("mybatis.xml"); + //创建sqlSessionFactory对象 + SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); + //创建SqlSession对象 + SqlSession session = factory.openSession(); + //获取代理对象 + UsersDao dao = session.getMapper(UsersDao.class); + //查询所有数据 + List list = dao.findUsers(); + for(Users users : list){ + System.out.println(users); + } + session.close(); + in.close();//关闭资源 + } + + @Test + public void run2() throws Exception { + Users users = new Users(); + users.setUsername("threestar"); + users.setPassword("789"); + + //加载配置文件 + InputStream in = Resources.getResourceAsStream("mybatis.xml"); + //创建SqlSessionFactory对象 + SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in); + //创建SqlSession对象 + SqlSession session = factory.openSession(); + //获取到代理对象 + UsersDao dao = session.getMapper(UsersDao.class); + + //保存 + dao.insertUsers(users); + + //提交事务 + session.commit(); + + //关闭资源 + session.close(); + in.close(); + } +} diff --git a/src/main/java/cn/star/test/SpringTest.java b/src/main/java/cn/star/test/SpringTest.java new file mode 100644 index 0000000..b301bee --- /dev/null +++ b/src/main/java/cn/star/test/SpringTest.java @@ -0,0 +1,18 @@ +package cn.star.test; + +import cn.star.service.UsersService; +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +public class SpringTest { + @Test + public void Test(){ + //加载配置文件 + ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring.xml"); + //获取对象 + UsersService us = (UsersService) ac.getBean("usersService"); + //调用方法 + us.findUsers(); + } +} \ No newline at end of file diff --git a/src/main/java/cn/star/util/JwtUtil.java b/src/main/java/cn/star/util/JwtUtil.java new file mode 100644 index 0000000..dd3b155 --- /dev/null +++ b/src/main/java/cn/star/util/JwtUtil.java @@ -0,0 +1,79 @@ +package cn.star.util; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.interfaces.DecodedJWT; + +import java.io.UnsupportedEncodingException; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import static java.lang.System.currentTimeMillis; + +public class JwtUtil { + + private static final long EXPIRE_TIME = 24 * 60 * 60 * 1000; //expire-到期时间 + + // token私匙 + private static final String TOKEN_SECRET = "f26e587c28064d0e855e72c0a6a0e618";//只是模拟自己设置的? + + //校验token是否正确 + public static boolean verify(String token) { + try { + Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET); + JWTVerifier verifier = JWT.require(algorithm).build(); + DecodedJWT jwt = verifier.verify(token); + return true; + } catch (Exception e) { + return false; + } + } + + //return token包含的用户名 + public static String getUsername(String token) { + try { + DecodedJWT jwt = JWT.decode(token); + return jwt.getClaim("username").asString(); + } catch (Exception e) { + return null; + } + } + + //获取登录用户id + public static String getUserId(String token) { + try { + DecodedJWT jwt = JWT.decode(token); + return jwt.getClaim("userId").asString(); + } catch (Exception e) { + return null; + } + } + + //生成签名,15min后过期 + public static String sign(String username,String userId) { + // 过期时间 + Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME); +// 私钥及加密算法 + Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET); +// 设置头部信息 + Map header = new HashMap<>(2); + header.put("typ", "JWT"); + header.put("alg", "HS256"); + // 附带username,userId信息,生成签名 + return JWT.create() + .withHeader(header) + .withClaim("loginName", username) + .withClaim("userId",userId) + .withExpiresAt(date) + .sign(algorithm); + } + + + + + + +} + diff --git a/src/main/java/cn/star/util/RedisUtil.java b/src/main/java/cn/star/util/RedisUtil.java new file mode 100644 index 0000000..b0eacaf --- /dev/null +++ b/src/main/java/cn/star/util/RedisUtil.java @@ -0,0 +1,567 @@ +package cn.star.util; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +@Component +public final class RedisUtil { + + @Autowired + private RedisTemplate redisTemplate; + + public void setEx(String key, String value, long timeout, TimeUnit unit) { + redisTemplate.opsForValue().set(key, value, timeout, unit); + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + if (time > 0) { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete(CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 递增 + * + * @param key 键 + * @param delta 要增加几(大于0) + * @return + */ + public long incr(String key, long delta) { + if (delta < 0) { + throw new RuntimeException("递增因子必须大于0"); + } + return redisTemplate.opsForValue().increment(key, delta); + } + + /** + * 递减 + * + * @param key 键 + * @param delta 要减少几(小于0) + * @return + */ + public long decr(String key, long delta) { + if (delta < 0) { + throw new RuntimeException("递减因子必须大于0"); + } + return redisTemplate.opsForValue().increment(key, -delta); + } + + // ================================Map================================= + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * hash递增 如果不存在,就会创建一个 并把新增后的值返回 + * + * @param key 键 + * @param item 项 + * @param by 要增加几(大于0) + * @return + */ + public double hincr(String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, by); + } + + /** + * hash递减 + * + * @param key 键 + * @param item 项 + * @param by 要减少记(小于0) + * @return + */ + public double hdecr(String key, String item, double by) { + return redisTemplate.opsForHash().increment(key, item, -by); + } + + // ============================set============================= + + /** + * 根据key获取Set中的所有值 + * + * @param key 键 + * @return + */ + public Set sGet(String key) { + try { + return redisTemplate.opsForSet().members(key); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 根据value从一个set中查询,是否存在 + * + * @param key 键 + * @param value 值 + * @return true 存在 false不存在 + */ + public boolean sHasKey(String key, Object value) { + try { + return redisTemplate.opsForSet().isMember(key, value); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将数据放入set缓存 + * + * @param key 键 + * @param values 值 可以是多个 + * @return 成功个数 + */ + public long sSet(String key, Object... values) { + try { + return redisTemplate.opsForSet().add(key, values); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 将set数据放入缓存 + * + * @param key 键 + * @param time 时间(秒) + * @param values 值 可以是多个 + * @return 成功个数 + */ + public long sSetAndTime(String key, long time, Object... values) { + try { + Long count = redisTemplate.opsForSet().add(key, values); + if (time > 0) + expire(key, time); + return count; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 获取set缓存的长度 + * + * @param key 键 + * @return + */ + public long sGetSetSize(String key) { + try { + return redisTemplate.opsForSet().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 移除值为value的 + * + * @param key 键 + * @param values 值 可以是多个 + * @return 移除的个数 + */ + public long setRemove(String key, Object... values) { + try { + Long count = redisTemplate.opsForSet().remove(key, values); + return count; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + // ===============================list================================= + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + + /** + * 通过索引 获取list中的值 + * + * @param key 键 + * @param index 索引 index>0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 + * @return + */ + public Object lGetIndex(String key, long index) { + try { + return redisTemplate.opsForList().index(key, index); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, Object value) { + try { + redisTemplate.opsForList().rightPush(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, Object value, long time) { + try { + redisTemplate.opsForList().rightPush(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据索引修改list中的某条数据 + * + * @param key 键 + * @param index 索引 + * @param value 值 + * @return + */ + public boolean lUpdateIndex(String key, long index, Object value) { + try { + redisTemplate.opsForList().set(key, index, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 移除N个值为value + * + * @param key 键 + * @param count 移除多少个 + * @param value 值 + * @return 移除的个数 + */ + public long lRemove(String key, long count, Object value) { + try { + Long remove = redisTemplate.opsForList().remove(key, count, value); + return remove; + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} \ No newline at end of file diff --git a/src/main/resources/application-redis.xml b/src/main/resources/application-redis.xml new file mode 100644 index 0000000..ecb701f --- /dev/null +++ b/src/main/resources/application-redis.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/jdbc.properties b/src/main/resources/jdbc.properties new file mode 100644 index 0000000..3cb4c41 --- /dev/null +++ b/src/main/resources/jdbc.properties @@ -0,0 +1,4 @@ +spring.datasource.jdbcUrl="jdbc:mysql:///myssm" +spring.datasource.user=root +spring.datasource.password=123456789chen +spring.datasource.driverClass=com.mysql.cj.jdbc.Driver \ No newline at end of file diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties new file mode 100644 index 0000000..bf6bf8d --- /dev/null +++ b/src/main/resources/log4j.properties @@ -0,0 +1,18 @@ +# Set root category priority to INFO and its only appender to CONSOLE. +#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal +log4j.rootCategory=info, CONSOLE, LOGFILE + +# Set the enterprise logger category to FATAL and its only appender to CONSOLE. +log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE + +# CONSOLE is set to be a ConsoleAppender using a PatternLayout. +log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender +log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout +log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n + +# LOGFILE is set to be a File appender using a PatternLayout. +log4j.appender.LOGFILE=org.apache.log4j.FileAppender +log4j.appender.LOGFILE.File=d:\axis.log +log4j.appender.LOGFILE.Append=true +log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout +log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n \ No newline at end of file diff --git a/src/main/resources/mybatis.xml b/src/main/resources/mybatis.xml new file mode 100644 index 0000000..97cf347 --- /dev/null +++ b/src/main/resources/mybatis.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/redis.properties b/src/main/resources/redis.properties new file mode 100644 index 0000000..35df0ad --- /dev/null +++ b/src/main/resources/redis.properties @@ -0,0 +1,18 @@ +redis.host=127.0.0.1 +redis.port=6397 +redis.password=123456 + +#????? +redis.maxIdle=300 +#??????????????????????????????????-1??????? +redis.maxWaitMillis=1000 +#????? ??8 +redis.maxTotal=500 +#????????????????????????????????????????? +redis.testOnBorrow=true +redis.testOnReturn=true +redis.testWhileIdle=true +redis.blockWhenExhausted=false +redis.numTestsPerEvictionRun=1024 +redis.timeBetweenEvictionRunsMillis=30000 +redis.minEvictableIdleTimeMillis=1800000 \ No newline at end of file diff --git a/src/main/resources/spring-mvc.xml b/src/main/resources/spring-mvc.xml new file mode 100644 index 0000000..9a7f56d --- /dev/null +++ b/src/main/resources/spring-mvc.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/spring.xml b/src/main/resources/spring.xml new file mode 100644 index 0000000..c114125 --- /dev/null +++ b/src/main/resources/spring.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/WEB-INF/pages/Users.jsp b/src/main/webapp/WEB-INF/pages/Users.jsp new file mode 100644 index 0000000..19f7449 --- /dev/null +++ b/src/main/webapp/WEB-INF/pages/Users.jsp @@ -0,0 +1,18 @@ +<%-- + Created by IntelliJ IDEA. + User: yuuuu + Date: 2025/8/11 + Time: 10:42 + To change this template use File | Settings | File Templates. +--%> +<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + 查询用户界面 + + +查询所有用户 +${list} + + diff --git a/src/main/webapp/WEB-INF/pages/falselogin.jsp b/src/main/webapp/WEB-INF/pages/falselogin.jsp new file mode 100644 index 0000000..37f13e3 --- /dev/null +++ b/src/main/webapp/WEB-INF/pages/falselogin.jsp @@ -0,0 +1,17 @@ +<%-- + Created by IntelliJ IDEA. + User: yuuuu + Date: 2025/8/11 + Time: 下午3:55 + To change this template use File | Settings | File Templates. +--%> +<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> + + + + 登陆失败 + + +登陆失败 + + diff --git a/src/main/webapp/WEB-INF/pages/success.jsp b/src/main/webapp/WEB-INF/pages/success.jsp new file mode 100644 index 0000000..2158cda --- /dev/null +++ b/src/main/webapp/WEB-INF/pages/success.jsp @@ -0,0 +1,17 @@ +<%-- + Created by IntelliJ IDEA. + User: yuuuu + Date: 2025/8/11 + Time: 下午3:54 + To change this template use File | Settings | File Templates. +--%> +<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> + + + + 注册成功 + + +注册成功 + + diff --git a/src/main/webapp/WEB-INF/pages/successlogin.jsp b/src/main/webapp/WEB-INF/pages/successlogin.jsp new file mode 100644 index 0000000..aa8005a --- /dev/null +++ b/src/main/webapp/WEB-INF/pages/successlogin.jsp @@ -0,0 +1,17 @@ +<%-- + Created by IntelliJ IDEA. + User: yuuuu + Date: 2025/8/11 + Time: 下午3:55 + To change this template use File | Settings | File Templates. +--%> +<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> + + + + 登陆成功 + + +登陆成功 + + diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..31067d4 --- /dev/null +++ b/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,47 @@ + + + + + + contextConfigLocation + classpath:spring.xml + + + characterEncodingFilter + org.springframework.web.filter.CharacterEncodingFilter + + encoding + UTF-8 + + + + + characterEncodingFilter + /* + + + + org.springframework.web.context.ContextCleanupListener + + + + + dispatcherServlet + org.springframework.web.servlet.DispatcherServlet + + + contextConfigLocation + classpath:spring-mvc.xml,classpath:spring.xml + + + 1 + + + + dispatcherServlet + / + + + \ No newline at end of file diff --git a/src/main/webapp/images b/src/main/webapp/images new file mode 100644 index 0000000..e69de29 diff --git a/src/main/webapp/index.jsp b/src/main/webapp/index.jsp new file mode 100644 index 0000000..5e28d3d --- /dev/null +++ b/src/main/webapp/index.jsp @@ -0,0 +1,94 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> + + + 主界面 + + + + +测试查询 + + + + + + 用户登录 + "> + 用户: + 密码: + + + + " width="110" height=24" id="verifyCodeImage" onclick="changeImage();"> + + + + + 注册 + + + + + + + + + + + + "> + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/webapp/static/css/styles.css b/src/main/webapp/static/css/styles.css new file mode 100644 index 0000000..7cb334d --- /dev/null +++ b/src/main/webapp/static/css/styles.css @@ -0,0 +1,7 @@ +a { + color: #f80d43; +} + +.center-text { + text-align: center; +} \ No newline at end of file