JavaWeb项目——如何处理管理员登录和退出——笔记

一、知识点 



1、@WebServlet注解的使用

@WebServlet注解是Servlet 3.0引入的一个特性,它允许开发者在Servlet类上使用注解来声明Servlet的一些属性,从而避免在web.xml文件中进行配置。这种方式简化了Servlet的配置过程,使得代码更加简洁,易于理解和维护。

1)示例代码

使用@WebServlet注解非常简单,只需要在Servlet类上方添加注解,并指定URL模式。例如,要映射到/login.do的URL,可以这样写:

@WebServlet(urlPatterns = {"/login"})

public class LoginServlet extends HttpServlet {

// ... 类的实现

}

这个注解告诉Servlet容器,当请求到达/login.do时,应该使用LoginServlet类来处理该请求。

2)重要注意事项

在使用**@WebServlet**注解时,有几个重要的注意点需要遵守:

  1. 确保在web.xml中设置metadata-complete="false",这样Servlet容器才会扫描注解。

  2. 如果使用了注解方式,就不应该再在web.xml中对同一个Servlet进行配置。

  3. 在注解的URL模式中,不要忘记前面的斜杠/

2、销毁session时,removeAttribute()和invalidate()有何区别?

        做我们在用户登陆功能时,用户退出时用到的是session.invalidate()

        而在比对验证码时,用到的是session.removeAttribute("某个名字")

invalidate时销毁,作废的意思。

1)二者比较

session.removeAttribute("")   用于清空session中某个特定的属性值

session.livadate()                     则是清除当前整个session

1、removeAttribute()      就是从session删除指定名称的绑定对象,也就是说调用此方法后再调用getAttribute(Stringname)时,不能获取指定名称的绑定对象,但是session还存在。

2、invalidate()            就是销毁此session对象,session对象中绑定的那些对象值也都不存在了。

session.invalidate()是销毁跟用户关联session,例如有的用户强制关闭浏览器,而跟踪用户的信息的session还存在,可是用户已经离开了。

虽然session 生命周期浏览默认时间30分,但是在30分钟内别的用户还可以访问到前一个用户的页面,需销毁用户的session。

session.removeAttribute()移除session中的某项属性。

==>在用户登陆中,用户退出时执行的是  request.getSession().removeAttribute("userSession");

session被销毁了,注销用户,可以使session失效。

==>验证验证码时,获取到session中的验证码后,用的是removeAttribute

是清空当前session中指定的属性,下个request中的sessionID是不变的

也就是说,session还是原来的session
                        
(参考链接:https://blog.csdn.net/u012471009/article/details/79702145)

3、什么是三层架构?

1)分析

        我们往往使用一个Dao接口隐藏持久化操作的细节,业务对象不需要了解底层的数据库持久化知识。使得业务逻辑与持久化逻辑分离,业务逻辑通常关系的是应用程序的核心流程和业务规则,持久化逻辑关注的是如何访问和操作持久化数据。

        表示层:        JSP/Servlet

        业务逻辑层: 业务规则

        持久化层:     主要包装持久化的逻辑

分层主要目的是为了好管理,能更好的适应需求的变换,能够更好的进行人员分工。

如图所示:

2)通俗理解为什么要使用三层架构:

假如你要开一家奶茶店,用开奶茶店的过程来类比三层架构会很容易理解。整个三层架构就像是店里不同分工的工作人员,共同协作完成顾客购买奶茶的任务。

表现层 (UI 层,User Interface)

        这一层就好比奶茶店的前台工作人员。顾客走进店里,和前台交流,告诉前台自己想要什么口味的奶茶,要大杯还是小杯,加不加珍珠、椰果等配料。前台工作人员把顾客的这些要求记录下来,然后将做好的奶茶递给顾客,让顾客看到并拿到最终的产品。在软件系统里,表现层就是用户能直接看到和操作的部分,比如手机 APP 的界面、电脑网页的页面等,负责接收用户的输入,比如点击按钮、填写信息,再把系统处理后的结果展示给用户,像显示查询到的信息、操作的反馈等。

业务逻辑层(BLL 层,Business Logic Layer)

        相当于奶茶店的制作团队负责人。当前台工作人员把顾客的需求传达过来后,制作团队负责人要根据店里的配方和流程来安排制作。比如顾客要一杯波霸奶茶,负责人要确定珍珠的量、奶茶的配比,还要考虑店里的原料库存够不够,如果不够要及时补货等。在软件系统中,业务逻辑层接收表现层传递过来的用户请求,按照设定好的业务规则进行处理。比如在一个电商系统中,计算商品折扣、判断用户的订单是否符合优惠条件、处理退货退款等逻辑,都是业务逻辑层的工作。它会调用数据访问层获取或保存数据,再把处理结果返回给表现层。

数据访问层(DAL 层,Data Access Layer)

        就像是奶茶店的仓库管理员。制作团队需要原料时,仓库管理员负责从仓库中取出相应的原料给他们;当采购了新的原料回来,仓库管理员要把原料妥善存放到仓库里。在软件系统中,数据访问层主要负责和数据库打交道。当业务逻辑层需要获取数据,比如查询用户信息、商品信息时,数据访问层就从数据库中把数据取出来;当业务逻辑层需要保存数据,比如新用户注册信息、新订单信息时,数据访问层就把这些数据存入数据库。它为业务逻辑层提供了数据访问的功能,让业务逻辑层不用关心具体怎么连接数据库、怎么执行 SQL 语句等细节。

        通过这种三层架构的分工,整个系统就像奶茶店一样,各个部分各司其职,既方便维护和管理,也能更高效地满足用户的需求。

3)dao层和service层的区别和联系

        在常见的三层架构中,DAO(Data Access Object,数据访问对象)层和 Service(业务逻辑)层是两个重要的组成部分。

职责区别:

        DAO 层:这一层主要负责与数据库进行交互,就像图书馆里专门管理藏书仓库的工作人员。它的任务是执行对数据库的增、删、改、查操作。比如在图书馆管理系统中,当需要添加一本新书的信息到系统中,DAO 层会执行向数据库插入新数据的操作;如果要查询某本图书的借阅记录,DAO 层会从数据库中查询相关数据并返回。它不关心这些数据在业务上的具体用途,只专注于如何准确地从数据库获取数据或者将数据保存到数据库。

        Service 层:它更像是图书馆的借阅服务台工作人员,负责处理业务逻辑。比如在图书馆管理系统中,当读者要借阅一本书时,Service 层会先调用 DAO 层查询这本书当前是否在库、读者是否有超期未还的书籍等情况,然后根据这些条件判断是否允许借阅。如果允许,再调用 DAO 层更新书籍的借阅状态和读者的借阅记录。Service 层会综合考虑多个因素和业务规则,将不同的 DAO 层操作组合起来,以完成一个完整的业务功能。

依赖关系

        Service 层依赖于 DAO 层。Service 层在处理业务逻辑的过程中,需要获取或保存数据时,会调用 DAO 层提供的方法。就像借阅服务台工作人员在处理借阅业务时,需要从管理藏书仓库的工作人员那里获取书籍状态和读者借阅记录等信息。而 DAO 层并不依赖 Service 层,它只专注于数据库操作,为上层提供数据访问服务。

设计目的区别

        DAO 层的设计目的是为了实现数据访问的封装,使得数据库操作与业务逻辑分离,提高数据访问的可维护性和可复用性。比如,当数据库从 MySQL 换成 Oracle 时,只需要修改 DAO 层的代码,而不影响业务逻辑。Service 层的设计目的是为了实现业务逻辑的封装,将复杂的业务流程进行抽象和组织,提高业务逻辑的可扩展性和可维护性。例如,当图书馆新增一种借阅规则时,只需要在 Service 层修改相应的业务逻辑代码即可。

        综上所述,DAO 层和 Service 层在三层架构中相互协作,DAO 层为 Service 层提供数据支持,Service 层利用 DAO 层完成业务逻辑处理,共同保证系统的正常运行。

 

二、模拟管理员登录和退出 小demo 

1、login界面代码

<%--
  Created by IntelliJ IDEA.
  User: 34524
  Date: 2024/8/11
  Time: 21:40
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!doctype html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.min.css"/>
    <script src="${pageContext.request.contextPath}/js/bootstrap.bundle.min.js"></script>
    <script src="${pageContext.request.contextPath}/js/jquery-3.7.1.min.js"></script>
    <title>Login</title>
    <link rel="icon" href="${pageContext.request.contextPath}/img/favicon.ico" sizes="16X16"/>
    <style type="text/css">
        body {
            background-image: url("${pageContext.request.contextPath}/img/login.jpg");
            background-repeat: no-repeat;
            background-size: cover;
        }

        #loginform {
            border: 2px solid gray;
            padding: 20px;
            border-radius: 10px;
            animation-name: rain;
            animation-duration: 600s;
            animation-direction: alternate;
            animation-timing-function: linear;
            animation-iteration-count: infinite;
        }

        #loginform:hover {
            transition: 0.7s;
            border: 2px solid white;
        }
        @keyframes rain {
            0%{box-shadow: 0px 0px 25px gold;}
            10%{box-shadow: 0px 0px 25px lime;}
            20%{box-shadow: 0px 0px 25px deepskyblue;}
            30%{box-shadow: 0px 0px 25px blue;}
            40%{box-shadow: 0px 0px 25px purple;}
            50%{box-shadow: 0px 0px 25px deeppink;}
            60%{box-shadow: 0px 0px 25px purple;}
            7%{box-shadow: 0px 0px 25px blue;}
            80%{box-shadow: 0px 0px 25px deepskyblue;}
            90%{box-shadow: 0px 0px 25px lime;}
            100%{box-shadow: 0px 0px 25px gold;}
        }
    </style>
</head>

<body>
<div class="container-fluid">

    <div class="row">

        <div class="col-7 pt-5">
            <div class="row">
                <div class="col-1"></div>
                <div class="col-3">
                    <a href="${pageContext.request.contextPath}/index.jsp">
                        <img src="${pageContext.request.contextPath}/img/"/>
                    </a>
                </div>
                <div class="col-8">
                    <p style="padding-top: 200px;color: white; font-size: 3em;">用美图分享快乐!</p>
                </div>
            </div>
        </div>

        <div class="col-3 pt-5 mt-5">
            <form method="post" action="${pageContext.request.contextPath}/login" id="loginform">
                <h2 class="text-center text-light">欢迎登录</h2>
                <div class="form-group mb-2">
                    <label for="username" class="text-white">用户名</label>
                    <input type="text" class="form-control" name="username" id="username" value="${cookie.yhm.value}" aria-describedby="usernameHelp">
                    <small id="usernameHelp" class="form-text text-light"></small>
                </div>
                <div class="form-group mb-3">
                    <label for="password" class="text-white">Password</label>
                    <input type="password" class="form-control" id="password" name="password" aria-describedby="passwordHelp">
                    <small id="passwordHelp" class="form-text text-light"></small>
                </div>
                <div class="form-group form-check mb-2">
                    <input type="checkbox" class="form-check-input" id="Check1" name="remember" value="1">
                    <label class="form-check-label text-warning" for="Check1">记住用户名</label>
                </div>
                <div class="form-group form-check mb-2">
                    <input type="checkbox" class="form-check-input" id="Check2" >
                    <label class="form-check-label text-warning" for="Check2">管理员登录</label>
                </div>
                <div class="row mb-4">
                    <div class="col-8">
                        <input type="text" class="form-control" placeholder="填写验证码" name="captcha" id="captcha">
                    </div>
                    
                    <div class="col-4">
                        <!-- TODO:验证码一般是个图片!!!! 也可以是纯文字 -->
                        <%--<button class="btn btn-info" style="letter-spacing: 0.5em;">45TE</button>--%>
                        <img id="captchaImg" src="${pageContext.request.contextPath}/captcha" width="100px" height="40px"/>
                        <!-- 每一次点击的时候,改变路径   用JS-->
                    </div>
                    
                </div>
                <div class="row mb-2">
                    <div class="col-4">
                        <button type="submit" class="btn btn-primary btn-block">登录</button>
                    </div>
                    <div class="col-4">
                        <a class="btn btn-warning btn-block" href="${pageContext.request.contextPath}/register.jsp">去注册</a>
                    </div>
                    <div class="col-4">
                        <a class="btn btn-secondary btn-block" href="${pageContext.request.contextPath}/index.jsp">返回首页</a>
                    </div>
                </div>
            </form>
        </div>

        <div class="col-2"></div>
    </div>
</div>

<!-- 界面:这是一个toast
     功能:弹窗,弹出一个弹框,表示你成功登陆了或者是失败登陆了
     用法:
     <small></small>里边写的是弹出的表示时间的信息
     <div></div>后边一个div表示的是弹框里边的文字内容
     <div></div>的class里边可以改变toast出现的位置
     如何触发toast事件:
     要求:  会用就行,主要是知道这么一个东西,知道在哪里可以改变它的样式
-->

<div class="toast-container position-fixed top-0 end-0 p-3">
    <div id="liveToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
        <div class="toast-header">
            <img src="${pageContext.request.contextPath}/img/favicon.ico" class="rounded me-2" alt="...">
            <strong class="me-auto">Illey练习</strong>
            <small>现在</small>
            <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
        </div>
        <!-- 思路和作用:这里我们应该判断一下,然后再来写div里边的文本数据
            其实根本不需要判断,由于你登陆成功或者失败,你肯定得告诉给程序里边得其他对象,所以会把失败信息放到一个作用域里边
            直接取这个作用域里边的文本,再来判断这个toast显示不显示就行了
            <--------取作用域的文本时,使用javascript
        -->
        <div class="toast-body">
            ${param.m==8?"重新登陆":" "}
            ${requestScope.msg}${param.t==0?"已安全退出":''}
            ${param.t==9?"注册成功请登录!":" "}
        </div>
    </div>
</div>

<!-- 要实现功能:
     判断toast-body里边的text文本究竟是不是存在,然后再判断是否显示toast
     入参:无入参
     方法体:1.用$()占位符获取toast-body
            2.使用text()函数,获得里边的文本变量
            3.判断文本内容是否为空或者大于0,如果里边有文本,说明就是登陆失败
            4.先获取livetoast对象
            5.然后再通过 new bootstrap.toast 来获取相应的toast变量
            6.最后用那个toast的show方法,呈现toast的形式和内容
-->
<script>
    /* 两个都弹了,说明没有问题*/
    $(function(){
        /*$(".可以识别的  没问题 ")*/
        let text=$(".toast-body").text();
        if (text!=null && text.length>0) {
            let toastLiveExample = document.getElementById("liveToast");
            /* 大小写 写错了 livetoast liveToast */
            let toast = new bootstrap.Toast(toastLiveExample);
            toast.show();
        }
        let old =$("#captchaImg").attr("src");
        //每当点击图片时,修改 src路径  浏览器就会发出新的请求
        $("#captchaImg").click(function () {
            let n=Math.random();
            $("#captchaImg").attr("src",old+"?n="+n);
            /*console.log($("#captchaImg").attr("src"))*/
        })

        }
    )

    $("#Check2").change(function(){
        if($("#Check2").prop("checked")){
            $("#loginform").attr("action","${pageContext.request.contextPath}/login2");
        }else{
            $("#loginform").attr("action","${pageContext.request.contextPath}/login");
        }
    })
</script>

</body>
</html>
登录界面展示: 

在这里的登录我是利用了JavaScript让提交的时候action随之改变

勾选管理员登录之前:

 

勾选管理员登录之后:

 2、/login2  的servlet代码处理

 

package com.illley.controller;

import com.illley.bean.Manager;
import com.illley.service.ManagerService;
import com.illley.service.impl.ManagerServiceImpl;
import org.springframework.dao.EmptyResultDataAccessException;

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 javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet(urlPatterns = {"/login2"})
public class Login2Controller extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //get 处理  退出
        HttpSession session = req.getSession();
        //就是要把session会话里边的manager的attribute使他失效
        //然后再转发页面
        session.removeAttribute("manager");
        session.invalidate();
        resp.sendRedirect(req.getContextPath()+"/login.jsp?t=0");

    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //什么管理员显示什么页面   所以还要查询管理员的角色  而且每一个角色对应一个资源动作  有多表关联
        //管理员表  角色表  操作资源  角色和资源   多对多
        String username =req.getParameter("username");
        String password =req.getParameter("password");
        //管理员登陆
        ManagerService ms =new ManagerServiceImpl();
        try {
            Manager success = ms.login(username,password);
            //System.out.println(success);   //这里打印到控制台就中文乱码,然后登录到管理员界面也都是乱码
            //打印没问题  就应该把它放到会话域中
            HttpSession session = req.getSession();
            session.setAttribute("manager",success);
            resp.sendRedirect(req.getContextPath()+"/main.jsp");   //当前项目下的  main.jp页面
        } catch (EmptyResultDataAccessException e) {
            //System.out.println("用户名和密码错误");
            req.setAttribute("msg","用户名或密码错误");
            req.getRequestDispatcher("/login.jsp").forward(req, resp);
        }
    }


}

其实大家要学习的就是doPost和doGet里边是如何处理用户登录和退出的就可以了。

 3、其他操作代码

        之后还有如何连接数据库,然后利用sql语句进行查找判断该账户是不是在管理员里边,还有javaBean的构建,这里就不详细展示了,等我把这个javaWeb项目学完,会开源这个项目的,大概春节前后左右吧。

三、处理中文乱码问题

其实是我的两个管理员展示页面最前面忘了加这么一句话

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

这样最后展示的页面就是正常的中文 

如图所示:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/956235.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringMVC (1)

目录 1. 什么是Spring Web MVC 1.1 MVC的定义 1.2 什么是Spring MVC 1.3 Spring Boot 1.3.1 创建一个Spring Boot项目 1.3.2 Spring Boot和Spring MVC之间的关系 2. 学习Spring MVC 2.1 SpringBoot 启动类 2.2 建立连接 1. 什么是Spring Web MVC 1.1 MVC的定义 MVC 是…

4. LwIP_网络数据包管理

概述 协议栈的本质&#xff1a; TCP/IP协议栈的实现&#xff0c;本质上就是对数据包的管理。在LwIP中&#xff0c;定义了一个pbuf结构体对数据包进行管理。 pbuf管理数据包的步骤&#xff1a; 1、用户产生要传输的数据 2、用户在内存堆/内存池中申请一个pbuf结构体 3、将…

鸿蒙动态路由实现方案

背景 随着CSDN 鸿蒙APP 业务功能的增加&#xff0c;以及为了与iOS、Android 端统一页面跳转路由&#xff0c;以及动态下发路由链接&#xff0c;路由重定向等功能。鸿蒙动态路由方案的实现迫在眉睫。 实现方案 鸿蒙版本动态路由的实现原理&#xff0c;类似于 iOS与Android的实…

登录认证(1):登录的基本逻辑及实现思路

登录 在当今的大部分网站、应用、游戏中&#xff0c;为了确保资源的安全性和隐私保护&#xff0c;通常需要用户先进行身份验证&#xff08;即登录&#xff09;&#xff0c;然后才能使用特定的功能和服务。这样的做法不仅增加了系统安全性&#xff0c;还能够根据用户的偏好提供…

音乐播放器实现:前端HTML,CSS,JavaScript综合大项目

音乐播放器实现:前端HTML&#xff0c;CSS&#xff0c;JavaScript综合大项目 项目概述项目视图效果一、侧边栏相关代码&#xff08;一&#xff09;HTML代码&#xff08;二&#xff09;css代码 二、登录页面&#xff08;一&#xff09;HTML代码&#xff08;二&#xff09;css代码…

【js进阶】设计模式之单例模式的几种声明方式

单例模式&#xff0c;简言之就是一个类无论实例化多少次&#xff0c;最终都是同一个对象 原生js的几个辅助方式的实现 手写forEch,map,filter Array.prototype.MyForEach function (callback) {for (let i 0; i < this.length; i) {callback(this[i], i, this);} };con…

git系列之revert回滚

1. Git 使用cherry-pick“摘樱桃” step 1&#xff1a; 本地切到远程分支&#xff0c;对齐要对齐的base分支&#xff0c;举例子 localmap git pull git reset --hard localmap 对应的commit idstep 2&#xff1a; 执行cherry-pick命令 git cherry-pick abc123这样就会将远程…

【Web】2025西湖论剑·中国杭州网络安全安全技能大赛题解(全)

目录 Rank-l Rank-U sqli or not Rank-l username存在报错回显&#xff0c;发现可以打SSTI 本地起一个服务&#xff0c;折半查找fuzz黑名单&#xff0c;不断扔给fenjing去迭代改payload from flask import Flask, request, render_template_stringapp Flask(__name__)app…

Android系统开发(十四):跨进程通讯的隐形之手AIDL

引言 你是否曾在 Android 开发中为进程间通讯&#xff08;IPC&#xff09;头疼不已&#xff1f;如果是&#xff0c;那么 AIDL 就是你的救星&#xff01;它不仅让跨进程数据传输变得高效&#xff0c;而且还解决了异构环境的兼容性问题。本篇文章将带你深入了解 AIDL&#xff0c…

string类的常用接口及模拟实现

目录 基础知识 常用接口 1>常见构造 2>容量操作 3>访问及遍历操作 1.迭代器 2.反向迭代器 3.范围for 4.auto 4>修改操作 5>非成员函数 其它接口 模拟实现 string.h string.cpp swap() 基础知识 string是一个管理字符的类&#xff0c;定义在std命…

Linux——多线程的控制

Linux——线程的慨念及控制-CSDN博客 文章目录 目录 文章目录 前言 一、线程函数的认识 1、基本函数的回顾 1、线程的创建pthread_create 2、线程阻塞pthread_join 3、线程退出pthread_exit 2、线程的分离pthread_detach 3、互斥锁初始化函数&#xff1a;pthread_mutex_init 4、…

计算机网络 (49)网络安全问题概述

前言 计算机网络安全问题是一个复杂且多维的领域&#xff0c;它涉及到网络系统的硬件、软件以及数据的安全保护&#xff0c;确保这些元素不因偶然的或恶意的原因而遭到破坏、更改或泄露。 一、计算机网络安全的定义 计算机网络安全是指利用网络管理控制和技术措施&#xff0c;保…

TCP状态转移图详解

状态 描述 LISTEN represents waiting for a connection request from any remote TCP and port. SYN-SENT represents waiting for a matching connection request after having sent a connection request. SYN-RECEIVED represents waiting for a confirming connect…

VUE学习笔记(入门)5__vue指令v-html

v-html是用来解析字符串标签 示例 <!doctype html> <html lang"en"> <head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>Document<…

【论文投稿】探秘计算机视觉算法:开启智能视觉新时代

目录 引言 一、计算机视觉算法基石&#xff1a;图像基础与预处理 二、特征提取&#xff1a;视觉信息的精华萃取 三、目标检测&#xff1a;从图像中精准定位目标 四、图像分类&#xff1a;识别图像所属类别 五、语义分割&#xff1a;理解图像的像素级语义 六、计算机视觉…

【Java数据结构】Java对象的比较

元素的比较 基本类型比较 在Java中基本类型比较可以直接比较大小 &#xff0c;返回一个布尔类型&#xff08;true或者false&#xff09;。 int a 10; int b 20; System.out.println(a>b); System.out.println(ab); System.out.println(a<b);对象比较的问题 对象的比…

《自动驾驶与机器人中的SLAM技术》ch8:基于预积分和图优化的紧耦合 LIO 系统

和组合导航一样&#xff0c;也可以通过预积分 IMU 因子加上雷达残差来实现基于预积分和图优化的紧耦合 LIO 系统。一些现代的 Lidar SLAM 系统也采用了这种方式。相比滤波器方法来说&#xff0c;预积分因子可以更方便地整合到现有的优化框架中&#xff0c;从开发到实现都更为便…

Ubuntu 24.04 LTS 更改软件源

Ubuntu 24.04 LTS 修改软件源

【2024年度技术总结】Unity 游戏开发的深度探索与实践

文章目录 前言一、Unity 游戏开发的技术深度总结1、C# 编程基础2、Unity 基础入门3、Unity 实战技巧4、Unity 小技巧分享 二、技术工具与平台的年度使用心得1、学习资源的选择2、开发环境配置3、测试与调试工具 三、技术项目实战经验与成果展示1、【制作100个Unity游戏】专栏2、…

ingress-nginx代理tcp使其能外部访问mysql

一、helm部署mysql主从复制 helm repo add bitnami https://charts.bitnami.com/bitnami helm repo updatehelm pull bitnami/mysql 解压后编辑values.yaml文件&#xff0c;修改如下&#xff08;storageclass已设置默认类&#xff09; 117 ## param architecture MySQL archit…