# layui-admin **Repository Path**: GuiJiLive/layui-admin ## Basic Information - **Project Name**: layui-admin - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 4 - **Created**: 2021-12-16 - **Last Updated**: 2021-12-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 一、数据表 ```mysql -- 创建数据库 create database productdb ; -- 进入数据库 use productdb ; -- 创建数据表 create table product ( product_id varchar(50) primary key not null , --产品ID product_name varchar(50) not null , --产品名称 product_price float not null , --产品库存 product_count int not null default 1 , --产品类型 product_image varchar(100) null default 'default.jpg' , --产品图片 product_desc varchar(200) default '暂无描述' --描述 ) -- 添加测试数据 -- insert into 表名(字段1,字段2,...) values (值1,值2,...) -- 查询数据 select * from product ; -- 删除数据 -- delete from 表名 where 条件 -- 修改数据 --update 表名 set 字段1=值,字段2=值,... where 条件 -- 查询数据 --select 字段1,字段2,.. from 表名 where 条件 -- 4、初始化数据 insert into product values ('101','米家智能插座WIFI版',39.5,1,'101.png','101..') ; insert into product values ('102','德尔玛多功能蒸汽清洁机',59.5,2,'102.png','102..') ; insert into product values ('103','90分框体旅行箱',200,3,'103.png','103..') ; insert into product values ('104','米家两六冰箱160L',1999.5,3,'104.png','104..') ; insert into product values ('105','流浪地球CN171运兵车',199.5,1,'105.png','105..') ; create table users ( id int identity(1,1) primary key , username varchar(50) unique not null , password char(32) not null , name varchar(50) , level varchar(10) default '会员' , image varchar(50) default 'default.jpg', sex char(2) default '男' , phone varchar(20) , address varchar(100) , zipcode varchar(10) , email varchar(50) , register_time datetime default getdate(), status int default 1 ) insert into users(username,name,password,phone,level) values ('zing','张三','123456','13417747371','会员') insert into users(username,name,password,phone,level) values ('lisi001','李四','123456','13417747371','会员') insert into users(username,name,password,phone,level) values ('xiaosi002','王五','123456','13417747371','会员') insert into users(username,name,password,phone,level) values ('yan003','赵六','123456','13417747371','会员') insert into users(username,name,password,phone,level) values ('wang004','田七','123456','13417747371','管理员') insert into users(username,name,password,phone,level) values ('liang005','王八','123456','13417747371','管理员') insert into users(username,name,password,phone,level) values ('admin','孙九','123456','13417747371','超级管理员') ``` # 二、登录 ## 1、登录 ```js layui.use(['layer', 'jquery'], function () { var layer = layui.layer; var $ = layui.jquery; // 绑定登录按钮 $('#loginBtn').on('click', function () { login(); }); // 绑定密码框 $('#LAY-user-login-password').on('keydown', function (e) { if (e.keyCode == 13) { login(); } }) // 登陆 function login() { if ($("#LAY-user-login-username").val() == '' || $("#LAY-user-login-password").val() == '') { layer.msg("请输入用户名或密码"); return false; } var params = $("#loginForm").serialize(); $.ajax({ url: 'http://localhost:8080/layui/api/login', type: 'post', data: params, success: function (res) { if (res.code == 200) { // 把 token 令牌字符串,保存在本地浏览器中 // 便于下次请求时,读取token,并发送回给服务器 localStorage.setItem("token", res.data); // 跳转页面 location.href = "admin.html" return; } layer.msg(res.msg); } }); } }); ``` ## 2、后台主页 ### 1)页面结构 ```html
``` ### 2)选项卡功能实现 ```js layui.use(['element', 'jquery', 'layer'], function () { var element = layui.element; var layer = layui.layer; var $ = layui.jquery; // 菜单按钮 $('.subMenu').on('click', function () { var tabTitle = $(this).text(); var tabId = $(this).prop("id"); var pageUrl = $(this).children('a').data('url'); if ($('.layui-tab-title li[lay-id="' + tabId + '"]').length == 0) { element.tabAdd('demo', { title: tabTitle, content: '', id: tabId }); } element.tabChange('demo', tabId); }); }); ``` # 三、用户管理 ## 1、查询表单 ### 1)页面结构 ```html
``` ### 2)JS实现——下拉列表框加载用户角色 ```js layui.use(['jquery', 'table', 'layer', 'form'], function () { var $ = layui.jquery; var table = layui.table; var layer = layui.layer; var form = layui.form; //加载用户角色 $.ajax({ url: 'http://localhost:8080/layui/api/level', type: 'get', beforeSend: function (xhr) { let token = localStorage.getItem("token"); // 使用请求头的方式传递 xhr.setRequestHeader("Authorization", "Bearer " + token) }, success: function (res) { if (res.code == 401) { location.href = "index.html"; return; } if (res.code == 200) { $.each(res.data, function (index, level) { $('#level').append(''); }); form.render('select'); } } }); }); ``` ## 2、数据查询 ### 1)页面结构 ```html
``` ### 2)数据查询——开启分页 ```js // 动态加载表格数据 table.render({ elem: '#table' , id: 'tableReload' , headers: { Authorization: "Bearer " + localStorage.getItem("token") } , url: 'http://localhost:8080/layui/api/user/list' , title: '用户列表' , cols: [[ { field: 'username', title: '帐号', width: '20%' } , { field: 'name', title: '姓名', width: '15%' } , { field: 'sex', title: '性别', width: '10%' } , { field: 'level', title: '角色', width: '8%' } , { field: 'registerTime', title: '注册时间', width: '10%', templet: function (res) { return layui.util.toDateString(res.registerTime, 'yyyy-MM-dd'); } } , { field: 'status', title: '状态', width: '5%', templet: function (res) { if (res.status == 1) { return '正常'; } else { return '禁用'; } } } , { fixed: 'right', title: '操作', toolbar: '#optionBar' } ]] , page: true , limit: 2 , parseData: function (res) { console.log("page>>>", res); return { "code": res.code == 200 ? 0 : res.code, //解析接口状态 "msg": res.msg, //解析提示文本 "count": res.count, //解析数据长度 "data": res.data //解析数据列表 }; } }); ``` ## 3、多条件查询 ```js // 查询并重新加载表格 var active = { reload: function () { //执行重载 table.reload('tableReload', { page: { curr: 1 // 重新从第 1 页开始 } , where: { username: $('#username').val(), level: $('#level').val() } }); } }; // 绑定查询按钮 $('#selectBtn').on('click', function () { var type = $(this).data('type'); active[type] ? active[type].call(this) : ''; }); ``` ## 4、删除数据 ```js //监听table行工具事件 table.on('tool(table)', function (obj) { let currentRow = obj.data; let layuiEvent = obj.event; if (layuiEvent === 'del') { layer.confirm('是否确认删除此条目?', function (index) { $.ajax({ url: 'http://localhost:8080/layui/api/user/del', type: 'POST', beforeSend: function (xhr) { xhr.setRequestHeader("Authorization", "Bearer " + localStorage.getItem("token")) }, data: { 'id': currentRow.id }, success: function (data) { if (data.code == 200) { // 删除当前行 // obj.del(); // 重载表格数据 table.reload('tableReload', { page: { curr: 1 } }); // 关闭确认框 layer.close(index); } else { layer.msg(data.msg); } } }); }); } }); ``` ## 5、修改数据 ### 1)页面结构 ```html ``` ### 2)JS实现 ```js // 接上 if (layuiEvent === 'show') { // 1.显示原数据 $('#update-username').val(currentRow.username); if (currentRow.sex == '男') { $("#update-sex1").prop("checked", true); } else { $("#update-sex2").prop("checked", true); } $('#update-phone').val(currentRow.phone); $('#update-address').val(currentRow.address); $('#update-zipcode').val(currentRow.zipCode); $('#update-level').find("option").each(function () { // 判断需要对那个选项进行回显 if (this.value == currentRow.level) { // 进行回显 $(this).prop("selected", "selected"); // 重新渲染 form.render('select'); } }); // 2.重新渲染表单 form.render(); // 3.打开修改表单 layer.open({ type: 1, title: '修改', area: ['50%', '30em'], resize: false, content: $("#updateContainer"), btn: ['确认', '取消'], btn1: function (index) { // 4.验证数据的合法性 if ($('#update-phone').val() == '') { layer.msg("手机不能为空"); $('#update-phone').focus(); return false; } // ... // 5.修改数据 $.ajax({ url: 'http://localhost:8080/layui/api/user/update', type: 'post', data: $('#updateForm').serialize(), dataType: 'json', beforeSend: function (xhr) { // 使用请求头的方式传递 xhr.setRequestHeader("Authorization", "Bearer " + localStorage.getItem("token")) }, success: function (data) { if (data.code == 200) { // 重载表格 table.reload('tableReload', { page: { curr: 1 } }); // 关闭层 layer.close(index); } else { layer.msg(data.msg); } } }); } ``` # 四、实体对象 ```java public class Product { private String id ; private String name ; private double price ; private int count ; private String image ; private String desc ; ... } ``` ```java public class User { private int id ; private String username ; private String password ; private String name ; private String level ; private String image ; private String sex ; private String phone ; private String address ; private String zipCode ; private String email ; private Date registerTime ; private int status ; ... } ``` # 五、工具类 ## 1、DBUtil ```java package org.zing.utils; /** * @author zqx * @date 2021-12-12 */ import java.sql.*; public class DBUtil { /** * 帐号 */ private static final String USERNAME = "root"; /** * 密码 */ private static final String PASSWORD = "root"; /** * 连接地址(服务器+数据库) */ private static final String URL = "jdbc:mysql://localhost:3306/productdb?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai"; /** * 驱动程序 : JDBC接口的实现 ,由数据库厂商提供 */ private static final String DRIVER = "com.mysql.cj.jdbc.Driver"; // 静态代码块 : 加载驱动程序 static { // 第二:加载驱动程序 try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { System.out.println("加载驱动程序失败"); e.printStackTrace(); } } /** * 返回连接对象 - 建立连接数据库的桥梁 */ public static Connection getConnection() { // 第三:连接数据库,并返回连接对象 Connection conn = null; try { conn = DriverManager.getConnection(URL, USERNAME, PASSWORD); } catch (SQLException e) { System.out.println("获取连接对象失败"); e.printStackTrace(); } return conn; } /** * 关闭数据库对象,释放资源 * * @param rs * @param stmt * @param conn */ public static void close(Connection conn,Statement stmt, ResultSet rs) { if (rs != null) { try { rs.close(); } catch (SQLException e) { System.out.println("关闭结果集对象失败"); e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { System.out.println("关闭语句对象失败"); e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (SQLException e) { System.out.println("关闭连接失败"); e.printStackTrace(); } } } /** * 定义主方法,测试是否连接成功 * @param args */ public static void main(String[] args) { System.out.println(DBUtil.getConnection()); } } ``` ## 2、GsonUtil ```java package org.zing.utils; /** * @author zqx * @date 2021-12-12 */ import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import java.util.Map; public class GsonUtil { /** * 把Json字符串,转换为Map集合 * * @param jsonData JSON字符串 * @return */ public static Map parseMap(String jsonData){ // 创建Gson对象 Gson gson = new Gson(); // 转换 Map map = gson.fromJson(jsonData, new TypeToken>() {}.getType()); // 返回结果 return map; } } ``` ## 3、JwtUtil ```java package org.zing.utils; /** * @author zqx * @date 2021-12-12 */ import cn.hutool.core.date.DateUtil; import io.jsonwebtoken.*; import java.util.Date; import java.util.Map; import java.util.UUID; public class JwtUtil { /** * 密钥,用于signature(签名)部分解密 -- 暗语(口令) -- 盐值 */ private static final String KEY = "112233abc" ; /** * 签发者 */ private static final String ISS = "edu.nf"; /** * 创建 Jwt 令牌字符串 * @param claims 签署内容 * @param ttl 设置过期时间,单位毫秒 - 1 * 24 * 60 * 60 * 1000 * @return */ public static String createToken(Map claims, long ttl) { JwtBuilder builder = Jwts.builder() // 获取签名秘钥,并采用HS256算法对JWT进行的签名 .signWith(SignatureAlgorithm.HS256,KEY) //jwt唯一标识 .setId(UUID.randomUUID().toString()) //设置需要签署的内容 .setClaims(claims) //设置发证人 .setIssuer(ISS) //主题 .setSubject("JWT_AUTH") //签名时间 .setIssuedAt(new Date()); // 过期时间 if(ttl >= 0){ builder.setExpiration(getExpDate(ttl)); } return builder.compact(); } /** * 创建token过期时间 * @param ttl * @return */ private static Date getExpDate(long ttl){ Date expDate = DateUtil.date(System.currentTimeMillis() + ttl); return expDate; } /** * 验证Token是否正确 */ public static void verify(String token){ try { Jwts.parser().setSigningKey(KEY).parseClaimsJws(token); } catch (SecurityException e) { throw new RuntimeException("Invalid JWT signature."); } catch (MalformedJwtException e) { throw new RuntimeException("Invalid JWT token."); } catch (ExpiredJwtException e) { throw new RuntimeException("JWT令牌字符串过期."); } catch (UnsupportedJwtException e) { throw new RuntimeException("Unsupported JWT."); } catch (IllegalArgumentException e) { throw new RuntimeException("JWT token compact of handler are invalid."); } } /** * 获取payload的内容 * @param token * @param name * @param type * @param * @return */ public static T getPayload(String token,String name,Class type) { return Jwts.parser() .setSigningKey(KEY) .parseClaimsJws(token) .getBody() .get(name, type); } } ``` # 六、过滤器 ## 1、CrosFilter ```java package org.zing.filters; /** * @author zqx * @date 2021-12-12 */ import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebFilter("/api/*") public class CrosFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // 1.向下转型 HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; // 2.跨域处理 // 允许所有的域名 response.setHeader("Access-Control-Allow-Origin", "*"); // 允许请求所有的方法 response.setHeader("Access-Control-Allow-Methods", "*"); // 允许请求头信息字段(Authorization) response.setHeader("Access-Control-Allow-Headers", "Authorization,Origin,X-Requested-With,Content-Type,Accept," + "content-Type,origin,x-requested-with,content-type,accept,authorization,token,id,X-Custom-Header,X-Cookie,Connection,User-Agent,Cookie,*"); // 3.放行 filterChain.doFilter(request,response); } @Override public void destroy() { } } ``` ## 2、EncodingFilter ```java package org.zing.filters; /** * @author zqx * @date 2021-12-12 */ import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebFilter("/*") public class EncodingFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // 1.向下转型 HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; // 2.设置编码 request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); // 3.放行 filterChain.doFilter(request,response); } @Override public void destroy() { } } ``` ## 3、ZAuthFilter ```java package org.zing.filters; /** * @author zqx * @date 2021-12-12 */ import com.alibaba.fastjson.JSON; import org.zing.utils.JwtUtil; import org.zing.vo.ResultVO; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; @WebFilter("/api/*") public class ZAuthFilter implements Filter { private static final String LOGIN = "login" ; private static final String OPTIONS = "options" ; private static final String TOKEN_HEADER = "Authorization" ; private static final String TOKEN_PREFIX = "Bearer "; @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { // 1.向下转型 HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; // 2.获取请求方式 -- 对预检请求进行放行 String method = request.getMethod(); if(OPTIONS.equalsIgnoreCase(method)) { filterChain.doFilter(request, response); return ; } // 3.获取客户端请求的URI地址,对于实现登录的Servlet 进行放行 String requestURI = request.getRequestURI(); if(requestURI.endsWith(LOGIN)) { filterChain.doFilter(request, response); return; } // 4.获取客户端发送过来 JWT 令牌字符串 String token = request.getHeader(TOKEN_HEADER); String jwt = token.replace(TOKEN_PREFIX, ""); if(jwt==null || "".equals(jwt)) { responseView(response,"请先登录") ; return ; } // 5.验证token try { JwtUtil.verify(jwt); String username = JwtUtil.getPayload(jwt, "username", String.class); if(username==null || "".equals(username)) { responseView(response,"解析token失败") ; return; } // 验证成功,放行 filterChain.doFilter(request, response); } catch (Exception e) { responseView(response,"会话已失效") ; } } private void responseView(HttpServletResponse response, String message) throws IOException { ResultVO vo = new ResultVO(); vo.setCode(401); vo.setMsg(message); response.setContentType("application/json;charset=utf-8"); String json = JSON.toJSONString(vo); PrintWriter out = response.getWriter(); out.print(json) ; out.flush(); out.close(); } @Override public void destroy() { } } ``` # 七、DAO ## 1、用户 ```java package org.zing.dao.impl; import org.zing.dao.UserDao; import org.zing.entity.User; import org.zing.utils.DBUtil; import org.zing.vo.PageVO; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * @author zqx * @date 2021-12-12 */ public class UserDaoImpl implements UserDao { @Override public User selectUser(String username) { User user = null ; //第一:定义操作数据库的SQL语句 String sql = "SELECT ID,USERNAME,PASSWORD,NAME,LEVEL,IMAGE,SEX,PHONE,ADDRESS,ZIPCODE,EMAIL,REGISTER_TIME,STATUS FROM USERS WHERE USERNAME=?" ; //第二:获取连接对象 Connection conn = DBUtil.getConnection(); //第三:使用连接对象,获取语句对象(PreparedStatement),并预编译SQL语句 PreparedStatement pstmt = null ; ResultSet rst = null ; try { pstmt= conn.prepareStatement(sql); //第四:设置数据 //语法:语句对象.setXxx(问号占位符索引,数据) ; pstmt.setString(1,username); //第五:执行SQL语句,并接收返回结果 //语句对象.executeUpdate() -> 增,删,改 -> 返回的是受影响的记录数 //语句对象.executeQuery() -> 查 -> 返回的是结果集(ResultSet) rst = pstmt.executeQuery() ; //第六:对结果进行处理 //遍历结构集各行各列的数据,封装到相关的实体对象或集合 //判断有没有数据:结果集对象.next() //获取结果集的数据: //结果集对象.getXxx(查询数据的索引) ; //结果集对象.getXxx(查询数据的字段名称) ; while(rst.next()) { // 1.读取数据 int id = rst.getInt(1) ; String password = rst.getString(3) ; String name = rst.getString(4) ; String level = rst.getString(5) ; String image = rst.getString(6) ; String sex = rst.getString(7) ; String phone = rst.getString(8) ; String address = rst.getString(9) ; String zipCode = rst.getString(10) ; String email = rst.getString(11) ; Date regTime = rst.getTimestamp(12) ; int status = rst.getInt(13) ; // 2.创建实体对象 user = new User() ; //3.封装数据 user.setId(id); user.setUsername(username); user.setPassword(password); user.setName(name); user.setLevel(level); user.setImage(image); user.setSex(sex); user.setPhone(phone); user.setAddress(address); user.setZipCode(zipCode); user.setEmail(email); user.setRegisterTime(regTime); user.setStatus(status); } } catch (SQLException e) { e.printStackTrace(); } finally { // 第七:关闭对象 DBUtil.close(conn,pstmt,null); } return user; } @Override public List queryUser(User user) { List list = new ArrayList() ; // 第一:定义操作数据库的SQL语句,动态添加条件 StringBuilder sql =new StringBuilder("SELECT ID,USERNAME,PASSWORD,NAME,LEVEL,IMAGE,SEX,PHONE,ADDRESS,ZIPCODE,EMAIL,REGISTER_TIME,STATUS FROM USERS WHERE 1=1"); // 1.定义集合,用于存储SQL语句的参数值 List params = new ArrayList(); // 2.拼接SQL语句 if(user!=null && user.getUsername()!=null) { sql.append(" AND USERNAME LIKE ?") ; params.add("%" + user.getUsername() + "%") ; } if(user!=null && user.getLevel()!=null) { sql.append(" AND `LEVEL` = ?") ; params.add(user.getLevel()) ; } if(user!=null && user.getPhone()!=null) { sql.append(" AND PHONE = ?") ; params.add(user.getPhone()) ; } //第二:获取连接对象 Connection conn = DBUtil.getConnection(); //第三:使用连接对象,获取语句对象(PreparedStatement),并预编译SQL语句 PreparedStatement pstmt = null ; ResultSet rst = null ; try { pstmt= conn.prepareStatement(sql.toString()); //第四:设置数据 //语法:语句对象.setXxx(问号占位符索引,数据) ; //遍历集合,填充参数值 for(int i=0;i 增,删,改 -> 返回的是受影响的记录数 //语句对象.executeQuery() -> 查 -> 返回的是结果集(ResultSet) rst = pstmt.executeQuery() ; //第六:对结果进行处理 //遍历结构集各行各列的数据,封装到相关的实体对象或集合 //判断有没有数据:结果集对象.next() //获取结果集的数据: //结果集对象.getXxx(查询数据的索引) ; //结果集对象.getXxx(查询数据的字段名称) ; while(rst.next()) { // 1.读取数据 int id = rst.getInt(1) ; String username = rst.getString(2) ; String password = rst.getString(3) ; String name = rst.getString(4) ; String level = rst.getString(5) ; String image = rst.getString(6) ; String sex = rst.getString(7) ; String phone = rst.getString(8) ; String address = rst.getString(9) ; String zipCode = rst.getString(10) ; String email = rst.getString(11) ; Date regTime = rst.getTimestamp(12) ; int status = rst.getInt(13) ; // 2.创建实体对象 User u = new User() ; //3.封装数据 u.setId(id); u.setUsername(username); u.setPassword(password); u.setName(name); u.setLevel(level); u.setImage(image); u.setSex(sex); u.setPhone(phone); u.setAddress(address); u.setZipCode(zipCode); u.setEmail(email); u.setRegisterTime(regTime); u.setStatus(status); list.add(u) ; } } catch (SQLException e) { e.printStackTrace(); } finally { // 第七:关闭对象 DBUtil.close(conn,pstmt,rst); } return list; } @Override public Long queryUserByPageCount(User user,Integer page,Integer limit) { Long count = 0L; // 第一:定义操作数据库的SQL语句,动态添加条件 StringBuilder sql =new StringBuilder("select count(id) from users where 1=1"); // 1.定义集合,用于存储SQL语句的参数值 List params = new ArrayList(); // 2.拼接SQL语句 if(user!=null && user.getUsername()!=null && !"".equals(user.getUsername().trim())) { sql.append(" and username like ?") ; params.add("%" + user.getUsername() + "%") ; } if(user!=null && user.getLevel()!=null && !"".equals(user.getLevel().trim())) { sql.append(" and `level` = ?") ; params.add(user.getLevel()) ; } // if(user!=null && user.getPhone()!=null) { // sql.append(" and phone = ?") ; // params.add(user.getPhone()) ; // } System.out.println(sql.toString()); //第二:获取连接对象 Connection conn = DBUtil.getConnection(); //第三:使用连接对象,获取语句对象(PreparedStatement),并预编译SQL语句 PreparedStatement pstmt = null ; ResultSet rst = null ; try { pstmt= conn.prepareStatement(sql.toString()); //第四:设置数据 //语法:语句对象.setXxx(问号占位符索引,数据) ; //遍历集合,填充参数值 for(int i=0;i 增,删,改 -> 返回的是受影响的记录数 //语句对象.executeQuery() -> 查 -> 返回的是结果集(ResultSet) rst = pstmt.executeQuery() ; //第六:对结果进行处理 //遍历结构集各行各列的数据,封装到相关的实体对象或集合 //判断有没有数据:结果集对象.next() //获取结果集的数据: //结果集对象.getXxx(查询数据的索引) ; //结果集对象.getXxx(查询数据的字段名称) ; if(rst.next()) { count = rst.getLong(1) ; } } catch (SQLException e) { e.printStackTrace(); } finally { // 第七:关闭对象 DBUtil.close(conn,pstmt,rst); } return count; } @Override public List queryUserByPage(User user,Integer page,Integer limit) { List list = new ArrayList() ; // 第一:定义操作数据库的SQL语句,动态添加条件 StringBuilder sql =new StringBuilder("select id,username,password,name,level,image,sex,phone,address,zipcode,email,register_time,status from users where 1=1"); // 1.定义集合,用于存储SQL语句的参数值 List params = new ArrayList(); // 2.拼接SQL语句 if(user!=null && user.getUsername()!=null && !"".equals(user.getUsername())) { sql.append(" and username like ?") ; params.add("%" + user.getUsername() + "%") ; } if(user!=null && user.getLevel()!=null && !"".equals(user.getLevel())) { sql.append(" and `level` = ?") ; params.add(user.getLevel()) ; } // if(user!=null && user.getPhone()!=null) { // sql.append(" and phone = ?") ; // params.add(user.getPhone()) ; // } sql.append(" limit ?,?") ; params.add((page-1)*limit) ; params.add(limit) ; //第二:获取连接对象 Connection conn = DBUtil.getConnection(); //第三:使用连接对象,获取语句对象(PreparedStatement),并预编译SQL语句 PreparedStatement pstmt = null ; ResultSet rst = null ; try { pstmt= conn.prepareStatement(sql.toString()); //第四:设置数据 //语法:语句对象.setXxx(问号占位符索引,数据) ; //遍历集合,填充参数值 for(int i=0;i 增,删,改 -> 返回的是受影响的记录数 //语句对象.executeQuery() -> 查 -> 返回的是结果集(ResultSet) rst = pstmt.executeQuery() ; //第六:对结果进行处理 //遍历结构集各行各列的数据,封装到相关的实体对象或集合 //判断有没有数据:结果集对象.next() //获取结果集的数据: //结果集对象.getXxx(查询数据的索引) ; //结果集对象.getXxx(查询数据的字段名称) ; while(rst.next()) { // 1.读取数据 int id = rst.getInt(1) ; String username = rst.getString(2) ; String password = rst.getString(3) ; String name = rst.getString(4) ; String level = rst.getString(5) ; String image = rst.getString(6) ; String sex = rst.getString(7) ; String phone = rst.getString(8) ; String address = rst.getString(9) ; String zipCode = rst.getString(10) ; String email = rst.getString(11) ; Date regTime = rst.getTimestamp(12) ; int status = rst.getInt(13) ; // 2.创建实体对象 User u = new User() ; //3.封装数据 u.setId(id); u.setUsername(username); u.setPassword(password); u.setName(name); u.setLevel(level); u.setImage(image); u.setSex(sex); u.setPhone(phone); u.setAddress(address); u.setZipCode(zipCode); u.setEmail(email); u.setRegisterTime(regTime); u.setStatus(status); list.add(u) ; } } catch (SQLException e) { e.printStackTrace(); } finally { // 第七:关闭对象 DBUtil.close(conn,pstmt,rst); } return list; } @Override public int delete(int id) { int r = 0 ; //第一:定义操作数据库的SQL语句 String sql = "delete from users where id=?" ; //第二:获取连接对象 Connection conn = DBUtil.getConnection(); //第三:使用连接对象,获取语句对象(PreparedStatement),并预编译SQL语句 PreparedStatement pstmt = null ; try { pstmt= conn.prepareStatement(sql); //第四:设置数据 //语法:语句对象.setXxx(问号占位符索引,数据) ; pstmt.setInt(1,id); //第五:执行SQL语句,并接收返回结果 //语句对象.executeUpdate() -> 增,删,改 -> 返回的是受影响的记录数 //语句对象.executeQuery() -> 查 -> 返回的是结果集(ResultSet) r = pstmt.executeUpdate() ; //第六:对结果进行处理 //遍历结构集各行各列的数据,封装到相关的实体对象或集合 //判断有没有数据:结果集对象.next() //获取结果集的数据: //结果集对象.getXxx(查询数据的索引) ; //结果集对象.getXxx(查询数据的字段名称) ; } catch (SQLException e) { e.printStackTrace(); } finally { // 第七:关闭对象 DBUtil.close(conn,pstmt,null); } // 返回受影响行数 return r; } @Override public int update(User user) { int r = 0 ; //第一:定义操作数据库的SQL语句 String sql = "update users set name=?,image=?,sex=?,phone=?,address=?,zipCode=? where id=?" ; //第二:获取连接对象 Connection conn = DBUtil.getConnection(); //第三:使用连接对象,获取语句对象(PreparedStatement),并预编译SQL语句 PreparedStatement pstmt = null ; try { pstmt= conn.prepareStatement(sql); //第四:设置数据 //语法:语句对象.setXxx(问号占位符索引,数据) ; pstmt.setString(1,user.getName()); pstmt.setString(2,user.getImage()); pstmt.setString(3,user.getSex()); pstmt.setString(4,user.getPhone()); pstmt.setString(5,user.getAddress()); pstmt.setString(6,user.getZipCode()); pstmt.setInt(7,user.getId()); //第五:执行SQL语句,并接收返回结果 //语句对象.executeUpdate() -> 增,删,改 -> 返回的是受影响的记录数 //语句对象.executeQuery() -> 查 -> 返回的是结果集(ResultSet) r = pstmt.executeUpdate() ; //第六:对结果进行处理 //遍历结构集各行各列的数据,封装到相关的实体对象或集合 //判断有没有数据:结果集对象.next() //获取结果集的数据: //结果集对象.getXxx(查询数据的索引) ; //结果集对象.getXxx(查询数据的字段名称) ; } catch (SQLException e) { e.printStackTrace(); } finally { // 第七:关闭对象 DBUtil.close(conn,pstmt,null); } // 返回受影响行数 return r; } } ``` ```mssql select * from ( select *, row_number() over(order by a.id asc) as rownumber from 表名 as a where 条件 ) as b where rownumber between (当前页数-1)*每页记录数+1 and 当前页数 * 每页记录数 select id,username,password,name,level,image,sex,phone,address,zipcode,email,register_time,status,rownumber from ( select id,username,password,name,level,image,sex,phone,address,zipcode,email,register_time,status, row_number() over(order by u.id asc) as rownumber from users as u ) as t where 1=1 and rownumber between 1 and 2 ``` ## 2、产品 ```java package org.zing.dao.impl; import org.zing.dao.ProductDao; import org.zing.entity.Product; import org.zing.utils.DBUtil; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; /** * @author zqx * @date 2021-12-12 */ public class ProductDaoImpl implements ProductDao { @Override public List selectAll() { List list = new ArrayList<>() ; //第一:定义操作数据库的SQL语句 ctrl + shift + u String sql = "select product_id,product_name,product_price,product_count,product_image,product_desc from product" ; //第二:获取连接对象 Connection conn = DBUtil.getConnection(); //第三:使用连接对象,获取语句对象(PreparedStatement),并预编译SQL语句 PreparedStatement pstmt = null ; ResultSet rst = null ; try { pstmt= conn.prepareStatement(sql); //第四:设置数据 //语法:语句对象.setXxx(问号占位符索引,数据) ; //第五:执行SQL语句,并接收返回结果 //语句对象.executeUpdate() -> 增,删,改 -> 返回的是受影响的记录数 //语句对象.executeQuery() -> 查 -> 返回的是结果集(ResultSet) rst = pstmt.executeQuery() ; //第六:对结果进行处理 //遍历结构集各行各列的数据,封装到相关的实体对象或集合 //判断有没有数据:结果集对象.next() //获取结果集的数据: //结果集对象.getXxx(查询数据的索引) ; //结果集对象.getXxx(查询数据的字段名称) ; while(rst.next()) { // 1.读取数据 String productId = rst.getString(1) ; String productName = rst.getString(2) ; double productPrice = rst.getDouble(3) ; int productCount = rst.getInt(4) ; String productImage = rst.getString(5) ; String productDesc = rst.getString(6) ; // 2.创建实体对象 Product product = new Product() ; //3.封装数据 product.setId(productId); product.setName(productName); product.setPrice(productPrice); product.setCount(productCount); product.setImage(productImage); product.setDesc(productDesc); //4.把实体对象添加到List集合中 list.add(product) ; } } catch (SQLException e) { e.printStackTrace(); } finally { // 第七:关闭对象 DBUtil.close(conn,pstmt,rst); } // 返回集合对象 return list; } @Override public int insert(Product product) { int r = 0 ; // 第一:定义操作数据库的SQL语句 // ctrl + shift + u String sql = "insert into product(product_id,product_name,product_price,product_count,product_image,product_desc) values (?,?,?,?,?,?)" ; //第二:获取连接对象 Connection conn = DBUtil.getConnection(); //第三:使用连接对象,获取语句对象(PreparedStatement),并预编译SQL语句 PreparedStatement pstmt = null ; try { pstmt= conn.prepareStatement(sql); //第四:设置数据 //语法:语句对象.setXxx(问号占位符索引,数据) ; pstmt.setString(1,product.getId()); pstmt.setString(2,product.getName()); pstmt.setDouble(3,product.getPrice()); pstmt.setInt(4,product.getCount()); pstmt.setString(5,product.getImage()); pstmt.setString(6,product.getDesc()); //第五:执行SQL语句,并接收返回结果 //语句对象.executeUpdate() -> 增,删,改 -> 返回的是受影响的记录数 //语句对象.executeQuery() -> 查 -> 返回的是结果集(ResultSet) r = pstmt.executeUpdate() ; //第六:对结果进行处理 //遍历结构集各行各列的数据,封装到相关的实体对象或集合 //判断有没有数据:结果集对象.next() //获取结果集的数据: //结果集对象.getXxx(查询数据的索引) ; //结果集对象.getXxx(查询数据的字段名称) ; } catch (SQLException e) { e.printStackTrace(); } finally { // 第七:关闭对象 DBUtil.close(conn,pstmt,null); } // 返回受影响行数 return r; } @Override public int delete(String id) { int r = 0 ; //第一:定义操作数据库的SQL语句 String sql = "delete from product where product_id=?" ; //第二:获取连接对象 Connection conn = DBUtil.getConnection(); //第三:使用连接对象,获取语句对象(PreparedStatement),并预编译SQL语句 PreparedStatement pstmt = null ; try { pstmt= conn.prepareStatement(sql); //第四:设置数据 //语法:语句对象.setXxx(问号占位符索引,数据) ; pstmt.setString(1,id); //第五:执行SQL语句,并接收返回结果 //语句对象.executeUpdate() -> 增,删,改 -> 返回的是受影响的记录数 //语句对象.executeQuery() -> 查 -> 返回的是结果集(ResultSet) r = pstmt.executeUpdate() ; //第六:对结果进行处理 //遍历结构集各行各列的数据,封装到相关的实体对象或集合 //判断有没有数据:结果集对象.next() //获取结果集的数据: //结果集对象.getXxx(查询数据的索引) ; //结果集对象.getXxx(查询数据的字段名称) ; } catch (SQLException e) { e.printStackTrace(); } finally { // 第七:关闭对象 DBUtil.close(conn,pstmt,null); } // 返回受影响行数 return r; } @Override public int update(Product product) { int r = 0 ; //第一:定义操作数据库的SQL语句 String sql = "update product set product_name=?,product_price=?,product_count=?,product_desc=?,product_image=? where product_id=?" ; //第二:获取连接对象 Connection conn = DBUtil.getConnection(); //第三:使用连接对象,获取语句对象(PreparedStatement),并预编译SQL语句 PreparedStatement pstmt = null ; try { pstmt= conn.prepareStatement(sql); //第四:设置数据 //语法:语句对象.setXxx(问号占位符索引,数据) ; pstmt.setString(1,product.getName()); pstmt.setDouble(2,product.getPrice()); pstmt.setInt(3,product.getCount()); pstmt.setString(4,product.getDesc()); pstmt.setString(5,product.getImage()); pstmt.setString(6,product.getId()); //第五:执行SQL语句,并接收返回结果 //语句对象.executeUpdate() -> 增,删,改 -> 返回的是受影响的记录数 //语句对象.executeQuery() -> 查 -> 返回的是结果集(ResultSet) r = pstmt.executeUpdate() ; //第六:对结果进行处理 //遍历结构集各行各列的数据,封装到相关的实体对象或集合 //判断有没有数据:结果集对象.next() //获取结果集的数据: //结果集对象.getXxx(查询数据的索引) ; //结果集对象.getXxx(查询数据的字段名称) ; } catch (SQLException e) { e.printStackTrace(); } finally { // 第七:关闭对象 DBUtil.close(conn,pstmt,null); } // 返回受影响行数 return r; } @Override public int updateCount(String id, int count) { int r = 0 ; //第一:定义操作数据库的SQL语句 String sql = "update product set product_count=? where product_id=?" ; //第二:获取连接对象 Connection conn = DBUtil.getConnection(); //第三:使用连接对象,获取语句对象(PreparedStatement),并预编译SQL语句 PreparedStatement pstmt = null ; try { pstmt= conn.prepareStatement(sql); //第四:设置数据 //语法:语句对象.setXxx(问号占位符索引,数据) ; pstmt.setInt(1,count); pstmt.setString(2,id); //第五:执行SQL语句,并接收返回结果 //语句对象.executeUpdate() -> 增,删,改 -> 返回的是受影响的记录数 //语句对象.executeQuery() -> 查 -> 返回的是结果集(ResultSet) r = pstmt.executeUpdate() ; //第六:对结果进行处理 //遍历结构集各行各列的数据,封装到相关的实体对象或集合 //判断有没有数据:结果集对象.next() //获取结果集的数据: //结果集对象.getXxx(查询数据的索引) ; //结果集对象.getXxx(查询数据的字段名称) ; } catch (SQLException e) { e.printStackTrace(); } finally { // 第七:关闭对象 DBUtil.close(conn,pstmt,null); } // 返回受影响行数 return r; } } ``` # 八、VO对象 ## 1、ResultVO ```java package org.zing.vo; /** * @author zqx * @date 2021-12-12 */ public class ResultVO { /** * 消息代码,默认200 */ private int code = 200; /** * 客户端消息 */ private String msg = ""; /** * 返回客户端具体的数据结果 */ private Object data; public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public Object getData() { return data; } public void setData(Object data) { this.data = data; } } ``` ## 2、PageVO ```java package org.zing.vo; /** * @author zqx * @date 2021-12-14 */ public class PageVO extends ResultVO{ /** * 总记录数 */ private Long count ; public Long getCount() { return count; } public void setCount(Long count) { this.count = count; } } ``` # 九、Servlet ## 1、BaseServlet ```java package org.zing.servlet; import com.alibaba.fastjson.JSON; import org.zing.vo.PageVO; import org.zing.vo.ResultVO; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * @author zqx * @date 2021-12-12 */ public class BaseServlet extends HttpServlet { public ResultVO successJson(Object value) { ResultVO resultVo = new ResultVO(); resultVo.setData(value); return resultVo; } public ResultVO successJson(Object value, int code, String msg) { ResultVO resultVo = new ResultVO(); resultVo.setData(value); resultVo.setCode(code); resultVo.setMsg(msg); return resultVo; } public ResultVO successJson() { return new ResultVO(); } public ResultVO errorJson() { ResultVO resultVo = new ResultVO(); resultVo.setCode(500); resultVo.setMsg("系统繁忙,请稍后再试!"); return resultVo; } public ResultVO errorJson(int code, String msg) { ResultVO resultVo = new ResultVO(); resultVo.setCode(code); resultVo.setMsg(msg); return resultVo; } public ResultVO errorJson(String msg) { ResultVO resultVo = new ResultVO(); resultVo.setCode(500); resultVo.setMsg(msg); return resultVo; } /** * 响应 JSON 字符串 到客户端浏览中 * @param resp * @param resultVO 响应数据 * @throws IOException */ public void print(HttpServletResponse resp, ResultVO resultVO) throws IOException { resp.setCharacterEncoding("UTF-8"); resp.setContentType("application/json;charset=UTF-8"); PrintWriter out = resp.getWriter(); out.print(JSON.toJSONString(resultVO)); out.flush(); out.close(); } protected PageVO pageVO(Long count, Object data){ PageVO vo = new PageVO(); vo.setCode(0); vo.setCount(count); vo.setData(data); return vo; } } ``` ## 2、登录 ```java package org.zing.servlet; import org.zing.dao.UserDao; import org.zing.dao.impl.UserDaoImpl; import org.zing.entity.User; import org.zing.utils.JwtUtil; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.HashMap; import java.util.Map; /** * @author zqx * @date 2021-12-12 */ @WebServlet("/api/login") public class LoginServlet extends BaseServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 第一:获取页面发送过来的商品信息(合法性验证[略]) String username = req.getParameter("username") ; String password = req.getParameter("password") ; // 第二:创建实体对象,并封装数据 // 第三:创建DAO对象,实现数据添加操作 UserDao userDao = new UserDaoImpl() ; User user = userDao.selectUser(username); // 第四:响应结果 if(user!=null && password!=null && password.equals(user.getPassword())) { // 定义一个Map对象,用于封装相关的令牌 Map map = new HashMap<>(); // 封装数据 -- 客户端浏览器只保留帐号名(用户ID)即可 map.put("username", username); // 创建Token,设置有效时间为5分钟 String token = JwtUtil.createToken(map, 5 * 60 * 1000); // 响应客户端 print(resp, successJson(token)); return; } print(resp, errorJson(401, "错误的帐号或密码")); } } ``` ## 2、获取角色 ```java package org.zing.servlet; import org.zing.dao.UserDao; import org.zing.dao.impl.UserDaoImpl; import org.zing.entity.User; import org.zing.utils.JwtUtil; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * @author zqx * @date 2021-12-12 */ @WebServlet("/api/level") public class LevelServlet extends BaseServlet { private static final String TOKEN_HEADER = "Authorization"; private static final String TOKEN_PREFIX = "Bearer "; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { List list = new ArrayList<>() ; list.add("会员"); list.add("管理员"); list.add("超级管理员"); // 响应客户端 print(resp, successJson(list)); } } ``` ## 3、获取登录用户信息 ```java package org.zing.servlet; import org.zing.dao.UserDao; import org.zing.dao.impl.UserDaoImpl; import org.zing.entity.User; import org.zing.utils.JwtUtil; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.HashMap; import java.util.Map; /** * @author zqx * @date 2021-12-12 */ @WebServlet("/api/admin") public class AdminServlet extends BaseServlet { private static final String TOKEN_HEADER = "Authorization"; private static final String TOKEN_PREFIX = "Bearer "; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 获取客户端发送过来的token String token = req.getHeader(TOKEN_HEADER); String jwt = token.replace(TOKEN_PREFIX, ""); // 获取payload信息 String username = JwtUtil.getPayload(jwt, "username", String.class); // 查询当前登录用户信息 UserDao userDao = new UserDaoImpl(); User user = userDao.selectUser(username); // 响应客户端 print(resp, successJson(user)); } } ``` ## 4、用户列表 ```java package org.zing.servlet; import org.zing.dao.UserDao; import org.zing.dao.impl.UserDaoImpl; import org.zing.entity.User; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; /** * @author zqx * @date 2021-12-12 */ @WebServlet("/api/user/list") public class UserListServlet extends BaseServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Integer page = Integer.parseInt(req.getParameter("page")); Integer limit = Integer.parseInt(req.getParameter("limit")); String username = req.getParameter("username"); String level = req.getParameter("level"); User user = new User() ; user.setUsername(username); user.setLevel(level); UserDao userDao = new UserDaoImpl(); List list = userDao.queryUserByPage(user,page,limit); Long count = userDao.queryUserByPageCount(user, page, limit); print(resp, pageVO(count,list)); } } ```