【JavaWeb学习笔记】19 - 网购家居项目开发(上)

2024-01-12 12:52

本文主要是介绍【JavaWeb学习笔记】19 - 网购家居项目开发(上),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、项目开发流程

程序框架图

项目具体分层方案

MVC

1、说明是MVC

MVC全称: Mode模型、View视图、Controller控制器。

MVC最早出现在JavaEE三层中的Web层,它可以有效的指导WEB层的代码如何有效分离,单独工作。

View视图:只负责数据和界面的显示,不接受任何与显示数据无关的代码,便于程序员和美工的分工(Vue/JSP/Thymeleaf/HTML)

Controller控制器:只负责接收请求,调用业务层的代码处理请求,然后派发页面,是一个"调度者"的角色(Servlet)

Model模型:将与业务逻辑相关的数据封装为具体的JavaBean类,其中不掺杂任何与数据处理相关的代码(JavaBean/Domain/Pojo)

2、MVC是一种思想

MVC的理念是将软件代码拆分成为组件,单独开发,组合使用(目的还是为了解耦合) ,也有很多落地的框架比如SpringMVC

二、实现1 正确加载静态页面

前端人员给的静态页面

三、实现功能02 会员注册前端JS校验

1.验证用户名:必须字母,数字下划线组成,并且长度为6到10位 => JQuery + 正则表达式

2.验证密码:必须由字母,数字下划线组成,并且长度为6到10位

3.邮箱格式验证:常规验证即可

4.验证码:后面实现

    <script type="text/javascript" src = "../../script/jquery-3.6.0.min.js"></script><script>$(function () {//页面加载完成后执行function//绑定点击事件$("#sub-btn").click(function (){//获取输入的用户名 => 自己看前端给的页面var $userName = $("#username").val();// alert("usernameVal = " + $userName)//使用正则表达式进行验证var usernamePattern = /^\w{6,10}$/;if(!usernamePattern.test($userName)){//查看前端给的代码是否有错误提示信息// <span class="errorMsg"// style="float: right; font-weight: bold; font-size: 20pt; margin-left: 10px;"></span>//jquery的属性过滤器$("span[class = 'errorMsg']").text("用户格式不对 需要6-10字符");return false;//不提交 需要返回false 不返回false会导致页面跳转}var password = $("#password").val();var passwordPattern = /^\w{6,10}$/;if(!passwordPattern.test(password)){//jquery的基本过滤器$("span.errorMsg").text("密码格式不对 需要6-10字符");return false;}//验证两次密码是否正确var repwd = $("#repwd").val();if(repwd != password){$("span.errorMsg").text("输入的两次密码不同");return false;}var email = $("#email").val();var emailPattern = /^[\w-]+@([a-zA-Z]+\.)+[a-zA-Z]+$/;if(!emailPattern.test(email)){$("span[class = 'errorMsg']").text("电子邮件格式不对");return false;}//到这里就全部过关 => 我们暂时不提交$("span.errorMsg").text("验证通过");return false;})})</script>

四、实现功能03 - 会员注册后端

导入mhl使用的BasicDAO以及JDBCbyDruid 测试是否成功

BasicDAO

package com.yinhai.furns.dao;import com.yinhai.furns.utils.JDBCUtilsByDruid;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;/*** @author 韩顺平* @version 1.0* 开发BasicDAO , 是其他DAO的父类*/
public class BasicDAO<T> { //泛型指定具体类型private QueryRunner qr =  new QueryRunner();//开发通用的dml方法, 针对任意的表public int update(String sql, Object... parameters) {Connection connection = null;try {//这里从数据库连接池获取connection//老师说明: 每次从连接池中取出Connection , 不能保证是同一个//1.我们目前已经是从当前线程关联的ThreadLocal获取的connection//2.所以我们可以保证是同一个连接(在同一个线程/同一个请求)connection = JDBCUtilsByDruid.getConnection();int update = qr.update(connection, sql, parameters);return  update;} catch (SQLException e) {throw  new RuntimeException(e); //将编译异常->运行异常 ,抛出}}//返回多个对象(即查询的结果是多行), 针对任意表/**** @param sql sql 语句,可以有 ?* @param clazz 传入一个类的Class对象 比如 Actor.class* @param parameters 传入 ? 的具体的值,可以是多个* @return 根据Actor.class 返回对应的 ArrayList 集合*/public List<T> queryMulti(String sql, Class<T> clazz, Object... parameters) {Connection connection = null;try {connection = JDBCUtilsByDruid.getConnection();return qr.query(connection, sql, new BeanListHandler<T>(clazz), parameters);} catch (SQLException e) {throw  new RuntimeException(e); //将编译异常->运行异常 ,抛出}}//查询单行结果 的通用方法public T querySingle(String sql, Class<T> clazz, Object... parameters) {Connection connection = null;try {connection = JDBCUtilsByDruid.getConnection();return  qr.query(connection, sql, new BeanHandler<T>(clazz), parameters);} catch (SQLException e) {throw  new RuntimeException(e); //将编译异常->运行异常 ,抛出}}//查询单行单列的方法,即返回单值的方法public Object queryScalar(String sql, Object... parameters) {Connection connection = null;try {connection = JDBCUtilsByDruid.getConnection();return  qr.query(connection, sql, new ScalarHandler(), parameters);} catch (SQLException e) {throw  new RuntimeException(e); //将编译异常->运行异常 ,抛出} }}

JDBC工具类 

package com.yinhai.furns.utils;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;/*** @author 韩顺平* @version 1.0* 基于druid数据库连接池的工具类*/
public class JDBCUtilsByDruid {private static DataSource ds;//定义属性ThreadLocal, 这里存放一个Connectionprivate static ThreadLocal<Connection> threadLocalConn =new ThreadLocal<>();//在静态代码块完成 ds初始化static {Properties properties = new Properties();try {//因为我们是web项目,他的工作目录在out, 文件的加载,需要使用类加载器//找到我们的工作目录properties.load(JDBCUtilsByDruid.class.getClassLoader().getResourceAsStream("druid.properties"));//properties.load(new FileInputStream("src\\druid.properties"));ds = DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {e.printStackTrace();}}//编写getConnection方法//public static Connection getConnection() throws SQLException {//    return ds.getConnection();//}/*** 从ThreadLocal获取connection, 从而保证在同一个线程中,* 获取的是同一个Connection* @return* @throws SQLException*/public static Connection getConnection()  {Connection connection = threadLocalConn.get();if (connection == null) {//说明当前的threadLocalConn没有连接//就从数据库连接池中,取出一个连接放入, threadLocalConntry {connection = ds.getConnection();//将连接设置为手动提交, 即不要自动提交connection.setAutoCommit(false);} catch (SQLException throwables) {throwables.printStackTrace();}threadLocalConn.set(connection);}return connection;}/*** 提交事务, java基础 mysql事务+线程+过滤器机制+ThreadLocal*/public static  void commit() {Connection connection = threadLocalConn.get();if(connection != null) {//确保该连接是有效try {connection.commit();} catch (SQLException throwables) {throwables.printStackTrace();} finally {try {connection.close();//关闭连接} catch (SQLException throwables) {throwables.printStackTrace();}}}//老师说明//1. 当提交后,需要把connection从 threadLocalConn 清除掉//2. 不然,会造成 threadLocalConn 长时间持有该连接, 会影响效率//3. 也因为我们Tomcat底层使用的是线程池技术threadLocalConn.remove();}/*** 老师说明:  所谓回滚,是回滚/撤销和 connection管理的操作删掉,修改,添加*/public static  void rollback() {Connection connection = threadLocalConn.get();if(connection != null) {//保证当前的连接是有效try {connection.rollback();} catch (SQLException throwables) {throwables.printStackTrace();} finally {try {connection.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}threadLocalConn.remove();}//关闭连接, 老师再次强调: 在数据库连接池技术中,close 不是真的断掉连接//而是把使用的Connection对象放回连接池public static void close(ResultSet resultSet, Statement statement, Connection connection) {try {if (resultSet != null) {resultSet.close();}if (statement != null) {statement.close();}if (connection != null) {connection.close();}} catch (SQLException e) {throw new RuntimeException(e);}}
}

实现Member的功能 查询等

一个规范接口

package com.yinhai.furns.dao;import  com.yinhai.furns.javabean.Member;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
public interface MemberDAO {//小伙伴要自己分析,需要哪些方法//提供一个通过用户名返回对应的Memberpublic Member queryMemberByUsername(String username);//提供一个保存Member对象到数据库/表member表public int saveMember(Member member);/*** 根据用户名和密码返回Member* @param username 用户名* @param password 密码* @return 返回的对象,如果不存在,返回null**/public Member queryMemberByUsernameAndPassword(String username, String password);
}

实现Member的功能 查询 添加等 

package com.yinhai.furns.dao.impl;import com.yinhai.furns.dao.BasicDAO;
import com.yinhai.furns.dao.MemberDAO;import  com.yinhai.furns.javabean.Member;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
public class MemberDAOImpl extends BasicDAO<Member> implements MemberDAO {/*** 通过用户名返回对应的Member** @param username 用户名* @return 对应的Member, 如果没有该Member, 返回 null*/@Overridepublic Member queryMemberByUsername(String username) {//老师提示,sql 先在sqlyog 测试,然后再拿到程序中//这里可以提高我们的开发效率,减少不必要的bugString sql = "SELECT `id`,`username`,`password`,`email` FROM `member`\n" +"WHERE `username` = ?";return querySingle(sql, Member.class, username);}/*** 保存一个会员** @param member 传入Member对象* @return 返回-1 就是失败,返回其它的数字就是受影响的行数*/@Overridepublic int saveMember(Member member) {String sql = "INSERT INTO `member`(`username`,`password`,`email`) " +" VALUES(?,MD5(?), ?)";return update(sql, member.getUsername(),member.getPassword(), member.getEmail());}@Overridepublic Member queryMemberByUsernameAndPassword(String username, String password) {String sql = "SELECT `id`,`username`,`password`,`email` FROM `member` " +" WHERE `username`=? and `password`=md5(?)";return querySingle(sql, Member.class, username, password);}}

测试 

package com.yinhai.furns.test;import com.yinhai.furns.dao.MemberDAO;
import com.yinhai.furns.dao.impl.MemberDAOImpl;
import com.yinhai.furns.javabean.Member;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
public class MemberTest {public static void main(String[] args) {MemberDAO memberDAO = new MemberDAOImpl();if (memberDAO.queryMemberByUsername("admin") == null){System.out.println("null");}else {System.out.println("exist");}Member member = new Member(null,"jack","jack","135465@qq.com");if(memberDAO.saveMember(member) == 0){System.out.println("添加失败");}else{System.out.println("添加成功");}}
}

服务端 提供注册

package com.yinhai.furns.test;import com.yinhai.furns.javabean.Member;
import com.yinhai.furns.service.MemberService;
import com.yinhai.furns.service.impl.MemberServiceImpl;
import com.yinhai.furns.utils.JDBCUtilsByDruid;
import org.junit.jupiter.api.Test;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
public class MemberServiceTest {public static void main(String[] args) {MemberService memberService = new MemberServiceImpl();if (memberService.isExistsUsername("admin")){System.out.println("用户存在");}else{System.out.println("用户不存在");}}@Testpublic void test(){Member member = new Member(null, "tom", "tom", "643013242@qq.com");MemberService memberService = new MemberServiceImpl();boolean b = memberService.registerMember(member);if (b){System.out.println("注册成功");}else{System.out.println("注册失败");}JDBCUtilsByDruid.commit();}
}

 一个Servlet提供前后端交流

注册成功 请求转发到注册完成的页面

package com.yinhai.furns.web;import com.yinhai.furns.javabean.Member;
import com.yinhai.furns.service.MemberService;
import com.yinhai.furns.service.impl.MemberServiceImpl;
import com.yinhai.furns.utils.JDBCUtilsByDruid;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.io.IOException;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
@WebServlet(name = "RegisterServlet",urlPatterns = "/registerServlet")
public class RegisterServlet extends HttpServlet {private MemberService memberService = new MemberServiceImpl();protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username = request.getParameter("user-name");String password = request.getParameter("user-password");String email = request.getParameter("user-email");if(!memberService.isExistsUsername(username)){System.out.println(username + "用户可用" + password + email);Member member = new Member(null,username,password,email);if (memberService.registerMember(member)) {request.getRequestDispatcher("/views/member/register_ok.jsp").forward(request,response);JDBCUtilsByDruid.commit();}else {request.getRequestDispatcher("/views/member/login_ok.jsp").forward(request,response);}}else{// System.out.println("用户不存在 返回注册页面");request.getRequestDispatcher("/views/member/register_fail.jsp").forward(request,response);}}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}

五、实现功能04-会员登录

1.输入用户名、密码后提交

2.判断会员是否存在

3.会员存在(数据库),显示登录成功页面

在DAO类编写对数据库操作 也需要在父类以及接口内写该方法

public class MemberDAOImpl extends BasicDAO<Member> implements MemberDAO {@Overridepublic Member queryMemberByUsernameAndPassword(String username, String password) {String sql = "SELECT `id`,`username`,`password`,`email` FROM `member` " +" WHERE `username`=? and `password`=md5(?)";return querySingle(sql, Member.class, username, password);}}

 在Service调用该方法

public class MemberServiceImpl implements MemberService {@Overridepublic Member login(Member member) {//返回对象return memberDAO.queryMemberByUsernameAndPassword(member.getUsername(), member.getPassword());}
}

LoginServlet 用于验证前端

package com.yinhai.furns.web;import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;
import com.yinhai.furns.javabean.Member;
import com.yinhai.furns.service.MemberService;
import com.yinhai.furns.service.impl.MemberServiceImpl;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.io.IOException;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
@WebServlet(name = "LoginServlet",urlPatterns = "/loginServlet")
public class LoginServlet extends HttpServlet {private MemberService memberService = new MemberServiceImpl();protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username = request.getParameter("user-name");String password = request.getParameter("user-password");if (!memberService.isExistsUsername(username)){System.out.println("不存在 请重新登录");request.getRequestDispatcher("/views/member/login.html").forward(request,response);return;}if(memberService.login(new Member(null,username,password,null)) == null){System.out.println("密码错误 重新登录");request.getRequestDispatcher("/views/member/login.html").forward(request,response);return;}System.out.println("登录成功");request.getRequestDispatcher("/views/member/login_ok.jsp").forward(request,response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}

六、实现功能05 - 登录错误提示 表单回显

在LoginServlet内添加回显以及消息提示

@WebServlet(name = "LoginServlet",urlPatterns = "/loginServlet")
public class LoginServlet extends HttpServlet {private MemberService memberService = new MemberServiceImpl();protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username = request.getParameter("user-name");String password = request.getParameter("user-password");if (!memberService.isExistsUsername(username)){System.out.println("用户名或者密码错误");request.setAttribute("msg","用户名或者密码错误");request.setAttribute("user-name",username);request.getRequestDispatcher("/views/member/login.jsp").forward(request,response);return;}if(memberService.login(new Member(null,username,password,null)) == null){System.out.println("密码错误 重新登录");request.setAttribute("msg","密码错误 重新登录");request.setAttribute("user-name",username);request.getRequestDispatcher("/views/member/login.jsp").forward(request,response);return;}System.out.println("登录成功");request.getRequestDispatcher("/views/member/login_ok.jsp").forward(request,response);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request,response);}
}

将前段页面改为jsp 并使用EL表达式

                        <div id="lg1" class="tab-pane active"><div class="login-form-container"><div class="login-register-form"><span style="float: right; font-weight: bold; font-size: 20pt; margin-left: 10px;">${msg}</span>

 添加动态显示用户名

在对应的地方使用el表达式即可

七、实现功能06 - 合并servlet

1.使用if else解决

使用switch - case进行判断 

package com.yinhai.furns.web;import com.yinhai.furns.javabean.Member;
import com.yinhai.furns.service.MemberService;
import com.yinhai.furns.service.impl.MemberServiceImpl;
import com.yinhai.furns.utils.JDBCUtilsByDruid;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.io.IOException;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
@WebServlet(name = "MemberServlet", urlPatterns = "/memberServlet")
public class MemberServlet extends HttpServlet {private MemberService memberService = new MemberServiceImpl();protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username = request.getParameter("user-name");String password = request.getParameter("user-password");String email = request.getParameter("user-email");String action = request.getParameter("action");System.out.println(action);switch (action) {case "login":if (!memberService.isExistsUsername(username)) {System.out.println("用户不存在");request.setAttribute("msg", "用户不存在");request.getRequestDispatcher("/views/member/login.jsp").forward(request, response);return;}if (memberService.login(new Member(null, username, password, null)) == null) {System.out.println("密码错误 重新登录");request.setAttribute("msg", "密码错误 重新登录");request.setAttribute("username", username);request.getRequestDispatcher("/views/member/login.jsp").forward(request, response);return;}System.out.println("登录成功");request.getRequestDispatcher("/views/member/login_ok.jsp").forward(request, response);break;case "register":if (!memberService.isExistsUsername(username)) {System.out.println(username + "用户可用" + password + email);Member member = new Member(null, username, password, email);if (memberService.registerMember(member)) {request.getRequestDispatcher("/views/member/register_ok.jsp").forward(request, response);JDBCUtilsByDruid.commit();} else {request.getRequestDispatcher("/views/member/register_fail.jsp").forward(request, response);}} else {System.out.println("用户存在 无法注册");request.setAttribute("msg", "用户存在 无法注册");request.getRequestDispatcher("/views/member/login.jsp").forward(request, response);}break;}}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);}
}

2.反射 +  模版设计 + 动态绑定

package com.yinhai.furns.web;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.io.IOException;
import java.lang.reflect.Method;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
public abstract class BasicServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//解决接收到的数据中文乱码问题request.setCharacterEncoding("utf-8");//System.out.println("BasicServlet doPost()");//获取到action的值//老韩提示:如果我们使用了模板模式+反射+动态绑定,要满足action的value 和 方法名一致!!!String action = request.getParameter("action");//System.out.println("action=" + action);//使用反射,获取当前对象的方法//老韩解读//1.this 就是请求的Servlet//2.declaredMethod 方法对象就是当前请求的servlet对应的"action名字" 的方法, 该方法对象(declaredMethod)//  是变化的,根据用户请求//3.使用模板模式+反射+动态机制===> 简化多个 if--else if---..try {Method declaredMethod =this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);System.out.println("declaredMethod=" + declaredMethod);//使用方法对象,进行反射调用declaredMethod.invoke(this, request, response);} catch (Exception e) {//java基础->异常机制//将发生的异常,继续throw//老师心得体会: 异常机制是可以参与业务逻辑throw new RuntimeException(e);}}}

然后子类servlet继承该Servlet 随后只写login以及register方法即可

package com.yinhai.furns.web;import com.yinhai.furns.javabean.Member;
import com.yinhai.furns.service.MemberService;
import com.yinhai.furns.service.impl.MemberServiceImpl;
import com.yinhai.furns.utils.JDBCUtilsByDruid;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.io.IOException;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
@WebServlet(name = "MemberServlet", urlPatterns = "/memberServlet")
public class MemberServlet extends BasicServlet {private MemberService memberService = new MemberServiceImpl();/*** 处理会员的注册** @param request* @param response* @throws ServletException* @throws IOException*/protected void register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("======MemberServlet register()========");//接收用户注册信息-> 一定要去看前端页面字段..//用户名String username = request.getParameter("user-name");String password = request.getParameter("user-password");String email = request.getParameter("user-email");//获取用户提交验证码String code = request.getParameter("code");//从session中获取到验证码// String token = (String) request.getSession().getAttribute(KAPTCHA_SESSION_KEY);//立即删除session验证码->防止该验证码被重复使用// request.getSession().removeAttribute(KAPTCHA_SESSION_KEY);//如果token为空,并且和用户提交的验证码一致,就继续// if (token != null && token.equalsIgnoreCase(code)) {//判断这个用户名是不是可用if (!memberService.isExistsUsername(username)) {//注册//System.out.println("用户名 " + username + " 不存在, 可以注册");//构建一个Member对象Member member = new Member(null, username, password, email);if (memberService.registerMember(member)) {//请求转发request.getRequestDispatcher("/views/member/register_ok.jsp").forward(request, response);} else {//请求转发request.getRequestDispatcher("/views/member/register_fail.jsp").forward(request, response);}} else {//返回注册页面//后面可以加入提示信息...request.getRequestDispatcher("/views/member/login.jsp").forward(request, response);}// } else { //验证码不正确//     request.setAttribute("msg", "验证码不正确~");//     //如果前端需要回显某些数据//     request.setAttribute("username", username);//     request.setAttribute("email", email);//     //带回一个信息 要显示到注册选项页//     request.setAttribute("active", "register");//     request.getRequestDispatcher("/views/member/login.jsp").forward(request, response);// }}/*** 处理会员登录** @param request* @param response* @throws ServletException* @throws IOException*/protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {System.out.println("======MemberServlet login()========");//System.out.println("LoginServlet 被调用..");//老韩说明:如果在登录页面, 用户没有输入内容,就直接提交,后台接收到的是""String username = request.getParameter("user-name");String password = request.getParameter("user-password");Member member = memberService.login(new Member(null, username, password, null));if (member == null) { //用户没有在DB//System.out.println(member + " 登录失败...");//把登录错误信息,放入到request域 => 如果忘了,可以看servlet / jsprequest.setAttribute("msg", "用户名或者密码错误");request.setAttribute("username", username);//页面转发request.getRequestDispatcher("/views/member/login.jsp").forward(request, response);} else { //用户在DB//System.out.println(member + " 登录成功~...");//将得到member对象放入到sessionrequest.getSession().setAttribute("member", member);//老师做了一个简单处理if ("admin".equals(member.getUsername())) {request.getRequestDispatcher("/views/manage/manage_menu.jsp").forward(request, response);} else {request.getRequestDispatcher("/views/member/login_ok.jsp").forward(request, response);}}}
}

八、功能07 - 后台管理家具

创建furn表

package com.yinhai.furns.web;import com.yinhai.furns.dao.BasicDAO;
import com.yinhai.furns.javabean.Furn;
import com.yinhai.furns.service.FurnService;
import com.yinhai.furns.service.impl.FurnServiceImpl;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.io.IOException;
import java.util.List;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com*/
@WebServlet(name = "FurnServlet",urlPatterns = "/manager/furnServlet")
public class FurnServlet extends BasicServlet {private FurnService furnService = new FurnServiceImpl();/*** 这里我们使用前面的模板设计模式+反射+动态绑定来的调用到list方法** @param req* @param resp* @throws ServletException* @throws IOException*/protected void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("FurnServlet list方法被调...");List<Furn> furns = furnService.queryFurns();//把furns集合放入到request域req.setAttribute("furns", furns);for (Furn furn : furns) {System.out.println(furn);}//请求转发req.getRequestDispatcher("/views/manage/furn_manage.jsp").forward(req, resp);}
}

通过jstl标签取出并输出 

                            <c:forEach items="${requestScope.furns}" var="furn"><tr><td class="product-thumbnail"><a href="#"><img class="img-responsive ml-3" src="${furn.imgPath}"alt=""/></a></td><td class="product-name"><a href="#">${furn.name}</a></td><td class="product-name"><a href="#">${furn.maker}</a></td><td class="product-price-cart"><span class="amount">${furn.price}</span></td><td class="product-quantity">${furn.sales}</td><td class="product-quantity">${furn.stock}</tr>

编写admin的DAO

public class AdminDAOImpl extends BasicDAO implements AdminDAO {@Overridepublic int saveAdmin(Admin admin) {String sql = "INSERT INTO `admin`(`username`,`password`) " +"VALUES(?,MD5(?))";return update(sql, admin.getUsername(),admin.getPassword());}@Overridepublic Admin queryAdminByUsernameAndPassword(String username, String password) {String sql = "SELECT `id`,`username`,`password` FROM `admin` " +" WHERE `username`=? and `password`=md5(?)";return (Admin) querySingle(sql, Admin.class,username,password);}}

编写对应的和前端交互的servlet

@WebServlet(name = "AdminServlet",urlPatterns = "/adminServlet")
public class AdminServlet extends BasicServlet {private AdminService adminService = new AdminServiceImpl();protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String username = request.getParameter("username");String password = request.getParameter("password");Admin admin = new Admin(null, username, password);if(adminService.login(admin) == null){System.out.println("管理员不存在");request.getRequestDispatcher("/views/manage/manage_login.jsp").forward(request,response);return;}request.getRequestDispatcher("/views/manage/manage_menu.jsp").forward(request,response);}
}

九、功能08 - 后台管理 添加家具

@WebServlet(name = "FurnServlet",urlPatterns = "/manage/furnServlet")
public class FurnServlet extends BasicServlet {private FurnService furnService = new FurnServiceImpl();protected  void add(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {//获取家居信息String uname = request.getParameter("name");String maker = request.getParameter("maker");String price = request.getParameter("price");String sales = request.getParameter("sales");String stock = request.getParameter("stock");String defaultPath = "assets/images/product-image/default.jpg";Furn furn = new Furn(null, uname, maker, new BigDecimal(price), new Integer(sales), new Integer(stock), defaultPath);System.out.println(furn);furnService.addFurn(furn);request.getRequestDispatcher("/manage/furnServlet?action=list").forward(request, response);}
public class FurnServiceImpl implements FurnService {private FurnDAO furnDAO = new FurnDAOImpl();//定义属性FurnDAO对象/*** 返回家居信息* @return*/@Overridepublic List<Furn> queryFurns() {return furnDAO.queryFurns();}@Overridepublic int addFurn(Furn furn) {return furnDAO.addFurn(furn);}
}
public class FurnDAOImpl extends BasicDAO implements FurnDAO {@Overridepublic int addFurn(Furn furn) {String sql = "INSERT INTO furn(`id`,`name`,maker,price,sales,stock,img_path)\n" +"\tVALUES(NULL,?,?,?,?,?,?)";return update(sql,furn.getName(),furn.getMaker(),furn.getPrice(),furn.getSales(),furn.getStock(),furn.getImgPath());}
}

细节 解决中文乱码问题 在BasicDAO上设置request response的文本格式

细节 解决表重复提交问题 使用重定向即可

细节 后端验证添加家具的合法性

 //我们可以对获取的到数据, 进行一个校验//1. 使用java的正则表达式来验证 sales是一个正整数//2. 如果没有通过校验,则直接返回furn_add.jsp -> request.setAttribute("mes","xx")//3. 这里可以直接进行转换//try {//    int i = Integer.parseInt(sales);//}catch (NumberFormatException e) {//    //System.out.println("转换异常...");//    req.setAttribute("mes", "销量数据格式不对...");//    //返回到furn_add.jsp//    req.getRequestDispatcher("/views/manage/furn_add.jsp")//            .forward(req, resp);//    return;//}//String stock = req.getParameter("stock");//图片的路径 imgPath 使用默认即可//Furn furn = null;//try {//    furn = new Furn(null, name, maker, new BigDecimal(price),//            new Integer(sales), new Integer(stock), "assets/images/product-image/default.jpg");//} catch (NumberFormatException e) {//    req.setAttribute("mes", "添加数据格式不对...");//    //返回到furn_add.jsp//    req.getRequestDispatcher("/views/manage/furn_add.jsp")//            .forward(req, resp);//    return;//}//后面我们会学习SpringMVC -> 专门的用于数据校验的规则/框架 JSR303... Hibernate Validator

细节 使用工具类DataUtils 完成自动封装JavaBean

1. BeanUtils工具类,它可以一次性的把所有请求的参数注入到JavaBean中。

2. BeanUtils工具类,经常用于把Map中的值注入到JavaBean中,或者是对象属性值的拷贝操作

3. BeanUtils不是Jdk的类,需要导入需要的jar包: commons-beanutils-1.8.0.jar

commons-logging-1.1.1.jar

//使用BeanUtils完成javabean对象的自动封装.//// Furn furn = new Furn();// try {//    //讲 req.getParameterMap() 数据封装到furn 对象//    //使用反射将数据封装, 有一个前提就是表单提交的数据字段名//    //<input name="maker" style="width: 90%" type="text" value=""/>//    //需要和封装的Javabean的属性名一致//    BeanUtils.populate(furn, request.getParameterMap());// } catch (Exception e) {//    e.printStackTrace();// }// 自动将提交的数据,封装到Furn对象Furn furn =DataUtils.copyParamToBean(request.getParameterMap(), new Furn());System.out.println(furn);furnService.addFurn(furn);
public class DataUtils {//将方法,封装到静态方法,方便使用public static <T> T copyParamToBean(Map value, T bean) {try {BeanUtils.populate(bean, value);} catch (Exception e) {e.printStackTrace();}return bean;}}

在构造javabean的时候在Furn内赋予一个默认值 给这个类自动装入

十、功能09 后台管理 删除家具

前端对x图标进行绑定事件 弹出是否删除该名字的家具

Servlet增加功能

@WebServlet(name = "FurnServlet",urlPatterns = "/manage/furnServlet")
public class FurnServlet extends BasicServlet {
protected void del(HttpServletRequest request,HttpServletResponse response){int id = DataUtils.parseInt(request.getParameter("id"), 0);System.out.println(furnService.deleteFurnById(id));}
}

Service增加功能

    public int deleteFurnById(int id) {return furnDAO.deleteFurnById(id);}

DAO类增加功能 

public class FurnDAOImpl extends BasicDAO implements FurnDAO {public int deleteFurnById(int id) {String sql = "DELETE FROM furn WHERE id = ?";return update(sql,id);}
}

十一、功能实现 10 后台管理 修改家具

查询对应的id的家具

protected void showFurn(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {int id = DataUtils.parseInt(request.getParameter("id"),0);Furn furn = furnService.queryFurnById(id);System.out.println(furn);request.setAttribute("furn",furn);//请求转发request.getRequestDispatcher("/views/manage/furn_update.jsp").forward(request,response);}

以上完成回显操作 下一步做修改的操作

  @Overridepublic int updateFurn(Furn furn) {String sql = "UPDATE furn SET `name` = ? , `maker` = ? , `price` = ? , sales = ?" +" , stock = ? , `img_path` = ?" +" WHERE id = ?";return update(sql,furn.getName(),furn.getMaker(),furn.getPrice(),furn.getSales(),furn.getStock(),furn.getImgPath(),furn.getId());}

前端页面也调整 使用jstl标签拿出

十二、功能实现11 分页显示

将分页作为一个Bean模型 

package com.yinhai.furns.javabean;import java.util.List;/*** @author 银小海* @version 1.0* @email yinhai14@qq.com* 一个分页的数据模型 包含了分页的各种信息*/
//用一个泛型 分页模型对应的数据类型是不确定的
public class Page<T> {//每页显示多少条记录可以在其他地方也用到 建议置为常量//ctrl + shift + u 切换大小写public static final Integer PAGE_SIZE = 3;//表示显示当前页private  Integer pageNo;//每页显示多少记录private  Integer pageSize = PAGE_SIZE;//表示共有多少页private Integer pageTotalCount;//表示的是共有多少条记录 通过totalRow和pageSize计算得到pageTotalCountprivate Integer totalRow;//表示当前页要显示的数据private List<T> items;//分页导航的字符串private String url;public Integer getPageNo() {return pageNo;}public void setPageNo(Integer pageNo) {this.pageNo = pageNo;}public Integer getPageSize() {return pageSize;}public void setPageSize(Integer pageSize) {this.pageSize = pageSize;}public Integer getPageTotalCount() {return pageTotalCount;}public void setPageTotalCount(Integer pageTotalCount) {this.pageTotalCount = pageTotalCount;}public Integer getTotalRow() {return totalRow;}public void setTotalRow(Integer totalRow) {this.totalRow = totalRow;}public List<T> getItems() {return items;}public void setItems(List<T> items) {this.items = items;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}
}

分析 page的那些属性可以从数据库获取 就把对应的属性交给DAO赋值

@Overridepublic int getTotalRow() {String sql = "SELECT COUNT(*) FROM furn";// return (int) queryScalar(sql); => 会报转换异常return ((Number) queryScalar(sql)).intValue();}@Overridepublic List<Furn> getPageItems(int begin, int pageSize) {String sql = "SELECT `id`,`name`,maker,price,sales,stock,img_path imgPath\n" +" FROM furn ";return null;}

其他的交给Service处理

public class FurnServiceImpl implements FurnService {@Overridepublic Page<Furn> page(int pageNo, int pageSize) {Page<Furn> page = new Page<>();page.setPageNo(pageNo);page.setPageSize(pageSize);int totalRow = furnDAO.getTotalRow();page.setTotalRow(totalRow);//pageTotalCount最大页数 需要通过算法计算得到int pageTotalCount = totalRow / pageSize;if(totalRow % pageSize > 0){pageTotalCount += 1;}page.setPageTotalCount(pageTotalCount);//private List<T> items//计算begin//private List<T> items//老师开始计算begin-> 小小算法//验证: pageNo = 1 pageSize = 3 => begin =0//验证: pageNo = 3 pageSize = 2 => begin =4//OK => 但是注意这里隐藏一个坑, 现在你看不到, 后面会暴露int begin = (pageNo - 1) * pageSize;List<Furn> pageItems = furnDAO.getPageItems(begin, pageSize);page.setItems(pageItems);//还差一个url => 分页导航,先放一放return page;}
}

Servlet调用 

protected void page(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {int pageNo = DataUtils.parseInt(req.getParameter("pageNo"), 1);int pageSize = DataUtils.parseInt(req.getParameter("pageSize"), Page.PAGE_SIZE);//调用service方法, 获取Page对象Page<Furn> page = furnService.page(pageNo, pageSize);//将page放入到request域req.setAttribute("page", page);//请求转发到furn_manage.jspreq.getRequestDispatcher("/views/manage/furn_manage.jsp").forward(req, resp);}

 

十三、功能实现 12 - 分页导航

<!--  Pagination Area Start 分页导航条 --><div class="pro-pagination-style text-center mb-md-30px mb-lm-30px mt-6" data-aos="fade-up"><ul><%--如果当前页 > 1 , 就显示上一页--%><c:if test="${requestScope.page.pageNo > 1}"><li><a href="manage/furnServlet?action=page&pageNo=${requestScope.page.pageNo - 1}">上一页</a></li></c:if><%--<li><a class="active" href="#">3</a></li>--%><%--<li><a href="#">4</a></li>--%><%--<li><a href="#">5</a></li>--%><%--    显示所有的分页数, 先容易,再困难老师思路: 先确定开始页数 begin 第1页再确定结束页数 end 第pageTotalCount页学生困惑:如果页数很多,怎么办? => 算法最多显示5页[这个规则可以由程序员决定.]希望,小伙伴自己先想一想...=> 后面老师分析1. 如果总页数<=5, 就全部显示2. 如果总页数>5, 按照如下规则显示(这个规则是程序员/业务来确定):2.1 如果当前页是前3页, 就显示1-52.2 如果当前页是后3页, 就显示最后5页2.3 如果当前页是中间页, 就显示 当前页前2页, 当前页 , 当前页后两页这里的关键就是要根据不同的情况来初始化begin, end--%><c:choose><%--如果总页数<=5, 就全部显示--%><c:when test="${requestScope.page.pageTotalCount <=5 }"><c:set var="begin" value="1"/><c:set var="end" value="${requestScope.page.pageTotalCount}"/></c:when><%--如果总页数>5--%><c:when test="${requestScope.page.pageTotalCount > 5}"><c:choose><%--如果当前页是前3页, 就显示1-5--%><c:when test="${requestScope.page.pageNo <= 3}"><c:set var="begin" value="1"/><c:set var="end" value="5"/></c:when><%--如果当前页是后3页, 就显示最后5页--%><c:when test="${requestScope.page.pageNo > requestScope.page.pageTotalCount - 3}"><c:set var="begin" value="${requestScope.page.pageTotalCount - 4}"/><c:set var="end" value="${requestScope.page.pageTotalCount}"/></c:when><%--如果当前页是中间页, 就显示 当前页前2页, 当前页 , 当前页后两页--%><c:otherwise><c:set var="begin" value="${requestScope.page.pageNo - 2}"/><c:set var="end" value="${requestScope.page.pageNo + 2}"/></c:otherwise></c:choose></c:when></c:choose><c:forEach begin="${begin}" end="${end}" var="i"><%--如果i是当前页, 就使用class="active" 修饰--%><c:if test="${i == requestScope.page.pageNo}"><li><a class="active" href="manage/furnServlet?action=page&pageNo=${i}">${i}</a></li></c:if><c:if test="${i != requestScope.page.pageNo}"><li><a href="manage/furnServlet?action=page&pageNo=${i}">${i}</a></li></c:if></c:forEach><%--如果当前页 < 总页数 , 就显示下一页--%><c:if test="${requestScope.page.pageNo < requestScope.page.pageTotalCount}"><li><a href="manage/furnServlet?action=page&pageNo=${requestScope.page.pageNo + 1}">下一页</a></li></c:if><li><a href="#">共 ${requestScope.page.pageTotalCount} 页</a></li></ul></div><!--  Pagination Area End -->

进行修改 删除 添加 家具之后 能够回显到原来操作所在的页面

修改一步步转发 到最后重定向到page页面

这几个都这么做都在修改请求转发地址上完成

@WebServlet(name = "FurnServlet", urlPatterns = "/manage/furnServlet")
public class FurnServlet extends BasicServlet {protected void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取家居信息// String uname = request.getParameter("name");// String maker = request.getParameter("maker");// String price = request.getParameter("price");// String sales = request.getParameter("sales");////// String stock = request.getParameter("stock");// String defaultPath = "assets/images/product-image/default.jpg";// Furn furn = new Furn(null, uname, maker, new BigDecimal(price), new Integer(sales), new Integer(stock), defaultPath);//我们可以对获取的到数据, 进行一个校验//1. 使用java的正则表达式来验证 sales是一个正整数//2. 如果没有通过校验,则直接返回furn_add.jsp -> request.setAttribute("mes","xx")//3. 这里可以直接进行转换//try {//    int i = Integer.parseInt(sales);//}catch (NumberFormatException e) {//    //System.out.println("转换异常...");//    req.setAttribute("mes", "销量数据格式不对...");//    //返回到furn_add.jsp//    req.getRequestDispatcher("/views/manage/furn_add.jsp")//            .forward(req, resp);//    return;//}//String stock = req.getParameter("stock");//图片的路径 imgPath 使用默认即可//Furn furn = null;//try {//    furn = new Furn(null, name, maker, new BigDecimal(price),//            new Integer(sales), new Integer(stock), "assets/images/product-image/default.jpg");//} catch (NumberFormatException e) {//    req.setAttribute("mes", "添加数据格式不对...");//    //返回到furn_add.jsp//    req.getRequestDispatcher("/views/manage/furn_add.jsp")//            .forward(req, resp);//    return;//}//后面我们会学习SpringMVC -> 专门的用于数据校验的规则/框架 JSR303... Hibernate Validator//这里我们使用第二种方式, 完成将前端提交的数据, 封装成Furn的Javabean对象//使用BeanUtils完成javabean对象的自动封装.//// Furn furn = new Furn();// try {//    //讲 req.getParameterMap() 数据封装到furn 对象//    //使用反射将数据封装, 有一个前提就是表单提交的数据字段名//    //<input name="maker" style="width: 90%" type="text" value=""/>//    //需要和封装的Javabean的属性名一致//    BeanUtils.populate(furn, request.getParameterMap());// } catch (Exception e) {//    e.printStackTrace();// }// 自动将提交的数据,封装到Furn对象Furn furn =DataUtils.copyParamToBean(request.getParameterMap(), new Furn());System.out.println(furn);furnService.addFurn(furn);//老师说明: 因为这里使用请求转发, 当用户刷新页面时, 会重新发出一次添加请求// request.getRequestDispatcher("/manage/furnServlet?action=list")//        .forward(request, response);//就会造成数据重复提交: 解决方案使用 重定向即可.//因为重定向实际是让浏览器重新发请求, 所以我们回送的url , 是一个完整url// response.sendRedirect(request.getContextPath() + "/manage/furnServlet?action=list");//以分页的方式显示response.sendRedirect(request.getContextPath()+ "/manage/furnServlet?action=page&pageNo=" + request.getParameter("pageNo"));}protected void del(HttpServletRequest request, HttpServletResponse response) throws IOException {int id = DataUtils.parseInt(request.getParameter("id"), 0);System.out.println(furnService.deleteFurnById(id));response.sendRedirect(request.getContextPath()+ "/manage/furnServlet?action=page&pageNo=" + request.getParameter("pageNo"));}protected void showFurn(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {int id = DataUtils.parseInt(request.getParameter("id"), 0);Furn furn = furnService.queryFurnById(id);System.out.println(furn);request.setAttribute("furn", furn);//再把获取到的showPage再传回去// request.setAttribute("pageNo",request.getParameter("pageNo"));// 如果是在同一个作用域request内的请求是不需要再转发的 在下个页面可以用param.pageNo获取//请求转发request.getRequestDispatcher("/views/manage/furn_update.jsp").forward(request, response);}protected void update(HttpServletRequest request, HttpServletResponse response) throws IOException {Furn furn = DataUtils.copyParamToBean(request.getParameterMap(), new Furn());System.out.println("update" + furn);System.out.println(furnService.updateFurn(furn));//请求重定向// response.sendRedirect(request.getContextPath() + "/manage/furnServlet?action=list");//这里考虑分页转发System.out.println(request.getContextPath()+ "/manage/furnServlet?action=page&pageNo=" + request.getParameter("pageNo"));response.sendRedirect(request.getContextPath()+ "/manage/furnServlet?action=page&pageNo=" + request.getParameter("pageNo"));}protected void page(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {int pageNo = DataUtils.parseInt(req.getParameter("pageNo"), 1);int pageSize = DataUtils.parseInt(req.getParameter("pageSize"), Page.PAGE_SIZE);//调用service方法, 获取Page对象Page<Furn> page = furnService.page(pageNo, pageSize);if(page.getItems().size() == 0){page = furnService.page(page.getPageTotalCount(), pageSize);}//将page放入到request域req.setAttribute("page", page);//请求转发到furn_manage.jspreq.getRequestDispatcher("/views/manage/furn_manage.jsp").forward(req, resp);}}

十四、功能实现13 - 首页分页

这篇关于【JavaWeb学习笔记】19 - 网购家居项目开发(上)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/597933

相关文章

springboot健康检查监控全过程

《springboot健康检查监控全过程》文章介绍了SpringBoot如何使用Actuator和Micrometer进行健康检查和监控,通过配置和自定义健康指示器,开发者可以实时监控应用组件的状态,... 目录1. 引言重要性2. 配置Spring Boot ActuatorSpring Boot Act

使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)

《使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)》在现代软件开发中,处理JSON数据是一项非常常见的任务,无论是从API接口获取数据,还是将数据存储为JSON格式,解析... 目录1. 背景介绍1.1 jsON简介1.2 实际案例2. 准备工作2.1 环境搭建2.1.1 添加

Java实现任务管理器性能网络监控数据的方法详解

《Java实现任务管理器性能网络监控数据的方法详解》在现代操作系统中,任务管理器是一个非常重要的工具,用于监控和管理计算机的运行状态,包括CPU使用率、内存占用等,对于开发者和系统管理员来说,了解这些... 目录引言一、背景知识二、准备工作1. Maven依赖2. Gradle依赖三、代码实现四、代码详解五

java如何分布式锁实现和选型

《java如何分布式锁实现和选型》文章介绍了分布式锁的重要性以及在分布式系统中常见的问题和需求,它详细阐述了如何使用分布式锁来确保数据的一致性和系统的高可用性,文章还提供了基于数据库、Redis和Zo... 目录引言:分布式锁的重要性与分布式系统中的常见问题和需求分布式锁的重要性分布式系统中常见的问题和需求

SpringBoot基于MyBatis-Plus实现Lambda Query查询的示例代码

《SpringBoot基于MyBatis-Plus实现LambdaQuery查询的示例代码》MyBatis-Plus是MyBatis的增强工具,简化了数据库操作,并提高了开发效率,它提供了多种查询方... 目录引言基础环境配置依赖配置(Maven)application.yml 配置表结构设计demo_st

在Ubuntu上部署SpringBoot应用的操作步骤

《在Ubuntu上部署SpringBoot应用的操作步骤》随着云计算和容器化技术的普及,Linux服务器已成为部署Web应用程序的主流平台之一,Java作为一种跨平台的编程语言,具有广泛的应用场景,本... 目录一、部署准备二、安装 Java 环境1. 安装 JDK2. 验证 Java 安装三、安装 mys

Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单

《Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单》:本文主要介绍Springboot的ThreadPoolTaskScheduler线... 目录ThreadPoolTaskScheduler线程池实现15分钟不操作自动取消订单概要1,创建订单后

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要

SpringCloud集成AlloyDB的示例代码

《SpringCloud集成AlloyDB的示例代码》AlloyDB是GoogleCloud提供的一种高度可扩展、强性能的关系型数据库服务,它兼容PostgreSQL,并提供了更快的查询性能... 目录1.AlloyDBjavascript是什么?AlloyDB 的工作原理2.搭建测试环境3.代码工程1.