servlet+jsp+filter实现用户管理系统

flag = true;

break;

}

}

if (flag){

document.getElementById(“form”).submit();

}

}

}

}

接下来设置第一行的checkbox可以实现全选全不选,逻辑上只用保证所有的所有checkbox的checked属性与第一行相同即可

window.onload = function () {

// 第一行checkbox实现全选

document.getElementById(“firstCb”).onclick = function () {

var cbs = document.getElementsByName(“uid”);

for (var i = 0; i < cbs.length; i ++){

// 设置所有checkbox的状态与第一行相同

cbs[i].checked = this.checked;

}

}

}

7 分页查询功能


由于要实现分页查询,需要总记录数、总页码数、每一页的数据集合、当前的页码以及每一页显示的条目数等数据,所以最好用一个类的对象来保存这些数据,如下图所示

于是设计PageBean类来保存这些数据,相应的生成getter、setter及toString方法

package domin;

import java.util.List;

/**

  • 分页对象

*/

public class PageBean {

private int totalCount; // 总记录数

private int totalPage; // 总页码

private List list; // 每页数据

private int currentPage;// 当前页码

private int rows; // 每页显示记录数

public int getTotalCount() {

return totalCount;

}

public void setTotalCount(int totalCount) {

this.totalCount = totalCount;

}

public int getTotalPage() {

return totalPage;

}

public void setTotalPage(int totalPage) {

this.totalPage = totalPage;

}

public List getList() {

return list;

}

public void setList(List list) {

this.list = list;

}

public int getCurrentPage() {

return currentPage;

}

public void setCurrentPage(int currentPage) {

this.currentPage = currentPage;

}

public int getRows() {

return rows;

}

public void setRows(int rows) {

this.rows = rows;

}

@Override

public String toString() {

return “PageBean{” +

“totalCount=” + totalCount +

“, totalPage=” + totalPage +

“, list=” + list +

“, currentPage=” + currentPage +

“, rows=” + rows +

‘}’;

}

}

实际上,服务器端只需接收到页面传过来的当前页码及每页显示的条目数即可得到所有的PageBean类的属性,具体如上图所示

实现分页查询并显示的设计如下图所示:

查询用户信息时,会自动调用后台 FindUserByPageServlet.java 程序,完成以下四个步骤:

  1. 接受请求参数 currentPage, rows

  2. 调用service层的 findUserByPage(currentPage, rows) 方法获取分页查询结果(PageBean类的对象)

  3. 将该对象存入request域中

  4. 转发至页面list.jsp展示

基于以上步骤,FindUserByPageServlet.java 的主要代码如下:

@WebServlet(“/findUserByPageServlet”)

public class FindUserByPageServlet extends HttpServlet {

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// 获取参数

String currentPage = request.getParameter(“currentPage”);

String rows = request.getParameter(“rows”);

if (currentPage == null || “”.equals(currentPage)){

currentPage = “1”;

}

if (rows == null || “”.equals(rows)){

rows = “5”;

}

// 调用service查询

UserService service = new UserServiceImpl();

PageBean pb= service.findUserByPage(currentPage, rows);

// 将PageBean存入request

request.setAttribute(“pb”, pb);

// 转发到list.jsp

request.getRequestDispatcher(“/list.jsp”).forward(request, response);

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

this.doPost(request, response);

}

}

service层 UserServiceImpl.java 类定义findUserByPage(String _currentPage, String _rows)方法以供FindUserByPageServlet.java 调用,在这里要根据传入的当前页面和每页显示条目数来计算出其他所需要的值,具体分为以下七个步骤:

  1. 创建PageBean对象pb

  2. 设置pb的currentPage和rows属性

  3. 调用dao层的finTotalCount()方法查询总记录数totalCount

  4. 计算sql查询的起始数据位置 start = (currentPage - 1) * rows

  5. 调用dao层的findByPage(int start, int rows)方法查询用户集合

  6. 计算总页码,totalCount % rows 并向上取整

  7. 返回pb

基于以上步骤,UserServiceImpl.java 中添加方法代码如下:

@Override

public PageBean findUserByPage(String _currentPage, String _rows) {

int currentPage = Integer.parseInt(_currentPage);

int rows = Integer.parseInt(_rows);

// 创建PageBean对象

PageBean pb = new PageBean();

// 查询总记录数

int totalCount = dao.finTotalCount();

pb.setTotalCount(totalCount);

// 计算总页码

int totalPage = (totalCount % rows) == 0 ? (totalCount/rows) : (totalCount/rows) + 1;

pb.setTotalPage(totalPage);

// 设置参数

if (currentPage > totalPage)

currentPage = totalPage;

if (currentPage <= 0)

currentPage = 1;

pb.setCurrentPage(currentPage);

pb.setRows(rows);

// 调用dao查询List集合

int start = (currentPage - 1) * rows;

List list = dao.findByPage(start, rows);

pb.setList(list);

return pb;

}

该方法调用了dao层 UserDaoImpl.java 中查询数据库总数据数的finTotalCount()方法:

@Override

public int finTotalCount() {

String sql = “select count(*) from user”;

return template.queryForObject(sql, Integer.class);

}

还调用了dao层按照页面可展示用户数查询的findByPage(int start, int rows)方法:

@Override

public List findByPage(int start, int rows) {

String sql = “select * from user limit ? , ?”;

return template.query(sql, new BeanPropertyRowMapper<>(User.class), start, rows);

}

改造显示页面list.jsp

首先将循环取出每一条用户数据按行展示的jstl语句中foreach的items参数修改

items=“${pb.list}”

动态显示总记录数

p b . t o t a l C o u n t 条记录,共 {pb.totalCount}条记录,共 pb.totalCount条记录,共{pb.totalPage}页

动态修改导航栏个数,高亮当前页面,并绑定servlet

<c:forEach begin=“1” end=“${pb.totalPage}” var=“i”>

<c:if test=“${pb.currentPage == i}”>

  • ${i}
  • </c:if>

    <c:if test=“${pb.currentPage != i}”>

  • ${i}
  • </c:if>

    </c:forEach>

    添加导航栏向左符号《 和 向右符号 》功能

    <c:if test=“${pb.currentPage == 1}”>

  • </c:if>

    <c:if test=“${pb.currentPage != 1}”>

  • </c:if>

    «

    <c:if test=“${pb.currentPage == pb.totalPage}”>

  • </c:if>

    <c:if test=“${pb.currentPage != pb.totalPage}”>

  • </c:if>

    »

    完成分页查询后将 UpdateUserServlet.java 和 AddUserServlet.java 和 DelSelectedServlet.java 和delUserServlet.java 的重定向目标换成分页查询的servlet

    8 复杂条件查询


    由于根据条件查询所得的结果也要分页展示,所以仍需借助PageBean对象,如下图所示:

    当用户点击查询按钮时,会传过来一个表单,这里表单一共有姓名、地址、email三个属性,但有可能用户只输入其中的几个,所以sql语句要动态的生成,如上图所示,如果用户输入了姓名和地址,那么查询总的条目数的模糊查询sql语句变为:

    select count(*) from user where name like ? and address like ?;

    同理,分页查询的sql语句为:

    select * from user where name like ? and address like ? limit ?, ?;

    改造list.jsp

    给查询部分的表单添加action和method,action传入分页的servlet

    注意表单中的input标签必须加上name属性,否则数据到不了服务器。

    为了查询条件的回显,将查询输入框的value进行设置

    分页导航在点击左右按钮或数字按钮是,要把可能存在的条件查询的条件name=KaTeX parse error: Undefined control sequence: \[ at position 16: {condition.name\̲[̲0\]}&address={condition.address[0]}&email=${condition.eamil[0]} 也加上

  • ${i}
  • 改造FindUserByPageServlet.java

    添加获取条件查询的参数condition,condition如果为空,则表示默认查询,没有设置查询条件

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    // 获取参数

    String currentPage = request.getParameter(“currentPage”);

    String rows = request.getParameter(“rows”);

    if (currentPage == null || “”.equals(currentPage)){

    currentPage = “1”;

    }

    if (rows == null || “”.equals(rows)){

    rows = “5”;

    }

    // 获取条件查询的参数

    Map<String, String[]> condition = request.getParameterMap();

    // 调用service查询

    UserService service = new UserServiceImpl();

    PageBean pb= service.findUserByPage(currentPage, rows, condition);

    // 将PageBean存入request

    request.setAttribute(“pb”, pb);

    request.setAttribute(“condition”, condition); // 储存查询条件,用于回显

    // 转发到list.jsp

    request.getRequestDispatcher(“/list.jsp”).forward(request, response);

    }

    改造UserServiceImpl.java

    其中的findUserByPage方法添加一个参数map,表示条件查询的条件,在方法里面调用UserDaoImpl类的操作数据库方法时,也多传入一个map参数

    @Override

    public PageBean findUserByPage(String _currentPage, String _rows, Map<String, String[]> condition) {

    int currentPage = Integer.parseInt(_currentPage);

    int rows = Integer.parseInt(_rows);

    // 创建PageBean对象

    PageBean pb = new PageBean();

    // 查询总记录数

    int totalCount = dao.finTotalCount(condition);

    pb.setTotalCount(totalCount);

    // 计算总页码

    int totalPage = (totalCount % rows) == 0 ? (totalCount/rows) : (totalCount/rows) + 1;

    pb.setTotalPage(totalPage);

    // 设置参数

    if (currentPage <= 0)

    currentPage = 1;

    if (currentPage > totalPage)

    currentPage = totalPage;

    pb.setCurrentPage(currentPage);

    pb.setRows(rows);

    // 调用dao查询List集合

    int start = (currentPage - 1) * rows;

    List list = dao.findByPage(start, rows, condition);

    pb.setList(list);

    return pb;

    }

    改造UserDaoImpl.java

    动态生成sql语句,注意要排除分页条件参数 “currentPage” 和 “rows”

    @Override

    public int finTotalCount(Map<String, String[]> condition) {

    // 定义模板sql

    String sql = “select count(*) from user where 1=1”;

    StringBuilder sb = new StringBuilder(sql);

    // 遍历map

    Set keySet = condition.keySet();

    // 参数的集合

    List params = new ArrayList<>();

    for (String key : keySet) {

    // 排除分页条件参数

    if (“currentPage”.equals(key) || “rows”.equals(key))

    continue;

    String value = condition.get(key)[0];

    if (value != null && !“”.equals(value)){

    // 有值

    sb.append(" and “+ key +” like ? ");

    params.add(“%” + value + “%”); // 存储sql语句中 ? 的值

    }

    }

    System.out.println(sb.toString());

    System.out.println(params);

    return template.queryForObject(sb.toString(), Integer.class,params.toArray());

    }

    findByPage(int start, int rows, Map condition)方法的实现类似于上面的实现,在这里没有将重复代码提取出一个单独的方法,大家可以自己完成一下

    @Override

    public List findByPage(int start, int rows, Map<String, String[]> condition) {

    String sql = "select * from user where 1 = 1 ";

    StringBuilder sb = new StringBuilder(sql);

    // 遍历map

    Set keySet = condition.keySet();

    // 参数的集合

    List params = new ArrayList<>();

    for (String key : keySet) {

    // 排除分页条件参数

    if (“currentPage”.equals(key) || “rows”.equals(key))

    continue;

    String value = condition.get(key)[0];

    if (value != null && !“”.equals(value)){

    // 有值

    sb.append(" and “+ key +” like ? ");

    params.add(“%” + value + “%”); // 存储sql语句中 ? 的值

    }

    }

    // 添加分页查询

    sb.append(" limit ?,? ");

    // 添加分页查询参数值

    params.add(start);

    params.add(rows);

    sql = sb.toString();

    System.out.println(sql);

    System.out.println(params);

    return template.query(sql, new BeanPropertyRowMapper<>(User.class), params.toArray());

    }

    9 登录功能


    login.jsp页面

    将表单的action设置为对应servlet程序的目录

    验证码图片的src设置为对应servlet程序的目录

    在javascript中定义刷新验证码的函数

    function refreshCode() {

    // 获取验证码图片对象

    var vcode = document.getElementById(“vcode”);

    // 设置src属性 加上时间戳

    vcode.src = “${pageContext.request.contextPath}/checkCodeServlet?time=” + new Date().getTime();

    }

    验证码自动生成程序 CheckCodeServlet.java,网上有很多实例代码,这里只将其贴在这里

    package web.servlet;

    import java.awt.Color;

    import java.awt.Font;

    import java.awt.Graphics;

    import java.awt.image.BufferedImage;

    import java.io.IOException;

    import java.util.Random;

    import javax.imageio.ImageIO;

    import javax.servlet.ServletException;

    import javax.servlet.annotation.WebServlet;

    import javax.servlet.http.HttpServlet;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

    /**

    • 验证码

    */

    @WebServlet(“/checkCodeServlet”)

    public class CheckCodeServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {

    //服务器通知浏览器不要缓存

    response.setHeader(“pragma”,“no-cache”);

    response.setHeader(“cache-control”,“no-cache”);

    response.setHeader(“expires”,“0”);

    //在内存中创建一个长80,宽30的图片,默认黑色背景

    //参数一:长

    //参数二:宽

    //参数三:颜色

    int width = 80;

    int height = 30;

    BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);

    //获取画笔

    Graphics g = image.getGraphics();

    //设置画笔颜色为灰色

    g.setColor(Color.GRAY);

    //填充图片

    g.fillRect(0,0, width,height);

    //产生4个随机验证码,12Ey

    String checkCode = getCheckCode();

    //将验证码放入HttpSession中

    request.getSession().setAttribute(“CHECKCODE_SERVER”,checkCode);

    //设置画笔颜色为黄色

    g.setColor(Color.YELLOW);

    //设置字体的小大

    g.setFont(new Font(“黑体”,Font.BOLD,24));

    //向图片上写入验证码

    g.drawString(checkCode,15,25);

    //将内存中的图片输出到浏览器

    //参数一:图片对象

    //参数二:图片的格式,如PNG,JPG,GIF

    //参数三:图片输出到哪里去

    ImageIO.write(image,“PNG”,response.getOutputStream());

    }

    /**

    • 产生4位随机字符串

    */

    private String getCheckCode() {

    String base = “0123456789ABCDEFGabcdefg”;

    int size = base.length();

    Random r = new Random();

    StringBuffer sb = new StringBuffer();

    for(int i=1;i<=4;i++){

    //产生0到size-1的随机值

    int index = r.nextInt(size);

    //在base字符串中获取下标为index的字符

    char c = base.charAt(index);

    //将c放入到StringBuffer中去

    sb.append©;

    }

    return sb.toString();

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    this.doGet(request,response);

    }

    }

    当用户点击登陆按钮时,自动跳转到后台 LoginServlet.java 程序, 完成以下几个步骤:

    1. 设置编码为"utf-8",防止中文乱码问题

    2. 获取用户输入的登陆数据map 及 输入的验证码

    3. 验证码校验

    4. 若校验成功则根据 map 封装用户,并调用service层的login(User user)方法查询是否登陆成功

    5. 若登陆成功则返回主页 index.jsp,失败返回登录页面 login.jsp

    基于以上步骤,LoginServlet.java 程序的主要代码如下:

    @WebServlet(“/loginServlet”)

    public class LoginServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    // 设置编码

    request.setCharacterEncoding(“utf-8”);

    // 获取数据

    String verifycode = request.getParameter(“verifycode”);

    Map<String, String[]> map = request.getParameterMap();

    // 封装User对象

    User user = new User();

    try {

    BeanUtils.populate(user, map);

    } catch (IllegalAccessException e) {

    e.printStackTrace();

    } catch (InvocationTargetException e) {

    e.printStackTrace();

    }

    // 验证码校验

    HttpSession session = request.getSession();

    String checkcode_server = (String) session.getAttribute(“CHECKCODE_SERVER”);

    session.removeAttribute(“CHECKCODE_SERVER”);

    if (! checkcode_server.equalsIgnoreCase(verifycode)){

    request.setAttribute(“login_msg”, “验证码错误”);

    request.getRequestDispatcher(“/login.jsp”).forward(request, response);

    return;

    }

    // 调用service查询

    UserService service = new UserServiceImpl();

    User loginUser = service.login(user);

    // 判断是否成功

    if (loginUser != null){

    // 登陆成功

    session.setAttribute(“user”, loginUser);

    response.sendRedirect(request.getContextPath() + “/index.jsp”);

    }else {

    request.setAttribute(“login_msg”, “用户名或密码错误”);

    request.getRequestDispatcher(“/login.jsp”).forward(request, response);

    }

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    this.doPost(request, response);

    }

    }

    service层 UserServiceImpl.java 类定义login(User user)方法以供 LoginServlet.java 调用:

    @Override

    public User login(User user){

    return dao.findUserByUsernameAndPassword(user.getUsername(), user.getPassword());

    }

    该方法调用了dao层的findUserByUsernameAndPassword(String username, String password)判断能否根据用户名和密码找到该用户,如果无法找到即返回null

    public User findUserByUsernameAndPassword(String username, String password){

    try{

    String sql = “select * from user where username = ? and password = ?”;

    User user = template.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), username, password);

    return user;

    }catch (Exception e){

    e.printStackTrace();

    return null;

    }

    }

    10 添加过滤器进行登录验证


    为了保证只有在登录的条件下才可以访问各个资源,需要添加 Filter 来进行验证,验证主要分为以下两步骤:

    1. 访问的是否是与登录相关的资源
    • 是,则直接放行

    • 否,则判断其是否登录

    2. 判断是否已经登陆(Session中是否有User)

    • 是,则放行

    • 否,则跳转至登录页面

    基于以上步骤,编写Filter代码如下:

    package web.filter;

    import javax.servlet.*;

    import javax.servlet.annotation.WebFilter;

    import javax.servlet.http.HttpServlet;

    import javax.servlet.http.HttpServletRequest;

    import java.io.IOException;

    /**

    • 登录验证的过滤器

    */

    @WebFilter(“/*”)

    public class LoginFilter implements Filter {

    public void destroy() {

    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

    // 强制转换

    HttpServletRequest request = (HttpServletRequest) req;

    // 获取资源请求路径

    String uri = request.getRequestURI();

    // 判断是否包含登录相关资源路径

    // 要注意放行掉 css/js/图片/验证码等

    if (uri.contains(“/login.jsp”) || uri.contains(“/loginServlet”) || uri.contains(“/css/”) || uri.contains(“/js/”) || uri.contains(“/fonts/”) || uri.contains(“/checkCodeServlet”)){

    chain.doFilter(req, resp);

    }else {

    // 验证用户是否登陆

    Object user = request.getSession().getAttribute(“user”);

    if (user != null){

    // 登陆了,放行

    chain.doFilter(req, resp);

    }else {

    request.setAttribute(“login_msg”, “您尚未登陆,请登录”);

    request.getRequestDispatcher(“login.jsp”).forward(request, resp);

    }

    }

    }

    public void init(FilterConfig config) throws ServletException {

    }

    }

    注意与登陆有关的资源不只是相应的.jsp页面和servlet,还有相关的css,js,字体,验证码等资源。

    11 过滤敏感词汇


    有些时候,用户可能会输入一些敏感词汇,我们需要将其和谐掉,然而request没有setAttribute的方法,所以可以使用代理的方式,创建一个新的request代理,增强网页中getParameter()方法,如果做了敏感词汇的河蟹,则放行新的request代理,否则,放行原先的request。

    package web.filter;

    import javax.servlet.*;

    import javax.servlet.annotation.WebFilter;

    import java.io.BufferedReader;

    import java.io.FileReader;

    import java.io.IOException;

    import java.lang.reflect.InvocationHandler;

    import java.lang.reflect.Method;

    import java.lang.reflect.Proxy;

    import java.util.ArrayList;

    import java.util.List;

    /**

    • 敏感词汇过滤器

    */

    @WebFilter(“/*”)

    public class SensitiveWordsFilter implements Filter {

    public void destroy() {

    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

    //1.创建代理对象,增强getParameter方法

    ServletRequest proxy_req = (ServletRequest)Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {

    @Override

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

    自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

    深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

    因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

    既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

    由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

    如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

    img

    总结

    总的来说,面试是有套路的,一面基础,二面架构,三面个人。

    最后,小编这里收集整理了一些资料,其中包括面试题(含答案)、书籍、视频等。希望也能帮助想进大厂的朋友

    三面蚂蚁金服成功拿到offer后,他说他累了

    三面蚂蚁金服成功拿到offer后,他说他累了

    《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
    st;

    /**

    • 敏感词汇过滤器

    */

    @WebFilter(“/*”)

    public class SensitiveWordsFilter implements Filter {

    public void destroy() {

    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

    //1.创建代理对象,增强getParameter方法

    ServletRequest proxy_req = (ServletRequest)Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {

    @Override

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

    自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

    深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

    因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。[外链图片转存中…(img-LLrvPQoa-1712665385240)]

    [外链图片转存中…(img-qw8qtJXL-1712665385241)]

    [外链图片转存中…(img-eMB26WUz-1712665385241)]

    既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

    由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

    如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

    img

    总结

    总的来说,面试是有套路的,一面基础,二面架构,三面个人。

    最后,小编这里收集整理了一些资料,其中包括面试题(含答案)、书籍、视频等。希望也能帮助想进大厂的朋友

    [外链图片转存中…(img-GSa4jP1K-1712665385242)]

    [外链图片转存中…(img-LQe3MRbF-1712665385242)]

    《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 11
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值