Spring Web MVC练习

news2024/11/23 12:12:47

一:开发程序常见问题

(1)学会定位前后端问题

💗通过看日志,查看到底是前端问题还是后端问题


①前端:F12查看网页的控制台


②后端:测试后端接口参数;查看IDEA的控制台

(测试后端接口参数,即去访问后端写的路径,给参数,看看是否能返回正确结果)


🌟查看请求是否到达了后端,如果没有那就是前端问题,如果有那就是后端问题

(查看方法:在后端的第一行代码上随机打印,如果请求进来了,控制台会有打印的日志)

(2)缓存问题

💗比如说我的前端代码明明写得很完整,但是运行网址的时候没有出现效果,此时右键网页点击"查看页面源代码",发现是空的,那这就是缓存问题


🌟解决办法:点击IDEA右侧的Maven,选择Lifecycle目录下的clean,清除缓存

二:学会使用Lombok

(1)Lombok定义

💗Lombok是一个工具包,它提供了一组注解,用于自动生成常见的Java代码,如getter和setter方法、构造函数、equals和hashCode方法等

(2)Lombok好处

🌟使用Lombok可减少编写样板代码的工作量,提高开发效率,不用每次都setter和getter

(3)Lombok引入(中央仓库方法)

①打开中央仓库,搜索lombok


②选择1.18.24版本

(小tips:当我们选择不熟悉的第三方工具包时,不知道什么版本好,就选择使用人数最多的)


③复制Maven到pom.xml即可

(但凡导入了新的包,一定要记得刷新)

(4)Lombok引入(SpringBoot方法)

①点击左上角的File➜Settings➜Plugins➜搜索EditStarters


②点击install进行安装并重启IDEA即可


③右键pom.xml代码页面,选择Generate


④按照下图所示点击,然后点击OK即可


⑤此时在pom.xml上就有Lombok依赖了,然后刷新Maven即可

(这个连版本都没有,因为Spring已经帮我们搞定好了)

(5)Lombok常用注解

1.Lombok常用注解图


2.@Getter和@Setter

 💗@Getter和@Setter在哪个属性上,就仅代表只有这个属性有getter和setter方法


💙比如:当我把@Getter放在from属性上,就代表只有from属性具有getter方法

3.@Data

 💗使用@Data注解,放在类上,此时所有的属性都有getter和setter方法、构造函数、equals和hashCode方法等


💙比如:我这里有个MessageInfo类,里面的属性我不想手动setter和getter,就用@Data

(此时get和set在其他类直接用即可,比如getfrom、setmessage等等,不用再加什么setter和getter方法)

4.@ToString

💗使用@ToString注解,放在类上,此时说明整个类已经重写了toString方法


三:加法计算器

(1)前端代码

💗前端代码网盘链接:前端代码( 提取码:lzh7)​​​​​​

(2)准备工作

 🌟①将加法计算器的前端代码引入到static目录下


 🌟②初学阶段,建议每做一步就去运行后端然后访问一下,确保没有错误

(static目录下放的是静态文件,可以直接访问)

(3)约定前后端交互接口

(4)后端代码

package com.example.demo.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RequestMapping("/calc")
@RestController
public class CalcController {
    @RequestMapping("/sum")
    public String sum(Integer num1 , Integer num2){
        Integer sum = num1 + num2;
        return "计算结果为:"+sum;
    }
}

(5)注意事项

(6)效果展示

四:用户登录

(1)前端代码

💗前端代码网盘链接:前端代码( 提取码:lzh7)​​​​​​

(2)准备工作

 🌟①将用户登录的前端代码引入到static目录下


 🌟②运行后端并访问,确保没有错误

(1)login.html

(2)index.html

(3)约定前后端交互接口

1.需求分析

①登录页面(login.html):通过账号和密码,校验输入的账号密码是否正确,并告知前端


②首页(index.html):告知前端当前的登录用户是谁

(如果当前已有用户登录,返回登录的账号;如果没有,返回空)

2.登录页面的交互接口

3.首页的交互接口

(4)后端代码

package com.example.demo.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;


@RequestMapping("/user")
@RestController
public class UserController {
    //登录页
    @RequestMapping("/login")
    public boolean login(String username, String password, HttpSession session) {
        //第一步:先去校验参数的合法性
        //if(!username==null || username.length()==0 || password==null || password.length()==0){
        //return false;
        //}
        if (StringUtils.hasLength(username) || !StringUtils.hasLength(password)){
            return false;
        }
        //第二步:进行用户名和密码的校验(这里因为是初学,不涉及mybatis数据库)
        if ("zhangsan".equals(username) && "123".equals(password)){
            //设置Session
            session.setAttribute("username","zhangsan");
            return true;
        }
        return false;
    }


    //主页
    @RequestMapping("/getUserInfo")
    public String getUserInfo(HttpServletRequest request){
        //从Seesion中获取登录用户
        HttpSession session = request.getSession(false);
        String userName = null;
        if (session!=null){
            userName = (String) session.getAttribute("username");
        }
        return userName;
    }
}

(5)测试后端代码

①登录页


②主页

(6)修改前端代码

①使用VSCode打开并修改登录页login.html

(修改的是script部分,并且要记得保存)

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>登录页面</title>
</head>

<body>
  <h1>用户登录</h1>
  用户名:<input name="userName" type="text" id="userName"><br>
  密码:<input name="password" type="password" id="password"><br>
  <input type="button" value="登录" onclick="login()">
  
  <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
  <script>
    function login() {
      $.ajax({
        url:"/user/login",
        type:"post",
        data:{
          //这是一个 jQuery 代码片段
          //'#'表示获取id;'.'表示获取class
          //因此"username":$("#userName").val()表示获取 id 为 "userName" 的输入框的值
          //其中 "$" 符号是 jQuery 的简写,相当于调用 jQuery 函数
          //".val()" 是 jQuery 提供的方法,用于获取或设置表单元素的值
          "username":$("#userName").val(),   
          "password":$("#password").val()
        },
        success:function(result){    //这个result参数名字可以任取;它表示后端返回的结果
          if(result){
            location.href="/index.html";  //为true则跳转到主页
          }else{
            alert("密码错误!");
          }
        }
      });
    }

  </script>
</body>

</html>

②使用VSCode打开并修改主页index.html

(修改的是script部分,并且要记得保存)

<!doctype html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>用户登录首页</title>
</head>

<body>
    登录人: <span id="loginUser"></span>

    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
    <script>
        //页面被加载时就去调用后端请求
        //$.ajax写在哪就在哪里被调用(比如登录页,写在login里,就是点击的时候调用ajax)
        $.ajax({
            url:"/user/getUserInfo",
            type:"get",
            success:function(username){
                $("#loginUser").text(username);
            }
        });
    </script>
</body>

</html>

(7)效果展示

五:留言板

(1)前端代码

💗前端代码网盘链接:前端代码( 提取码:lzh7)​​​​​​

(2)准备工作

 🌟①将留言板的前端代码引入到static目录下


 🌟②运行后端并访问,确保没有错误

(3)约定前后端交互接口

1.需求分析

🌟后端需要提供两个服务


①提交留言:用户输⼊留言信息之后,后端需要把留言信息保存起来

(因为还没有学到mybatis,先保存到内存中)


②展示留言:页面展示时,需要从后端获取到所有的留言信息

2.获取所有留言的交互接口

🌟所有的留言信息,我们用List来表示,可以用JSON来描述这个List数据


3.发表新留言的交互接口

(4)后端代码

①需要先写一个MessageInfo类,用来存储留言

package com.example.demo.Controller;
import lombok.Data;

@Data
public class MessageInfo {
    private String from;
    private String to;
    private String message;
}

②编写后端代码

package com.example.demo.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;


@RequestMapping("/message")
@RestController
public class MessageController {
    private List<MessageInfo> messageInfos = new ArrayList<>();

    //发表新留言的后端代码
    @RequestMapping("/publish")
    public Boolean publishMessage(MessageInfo messageInfo){
        //第一步:进行参数的校验
        if (!StringUtils.hasLength(messageInfo.getFrom()) || !StringUtils.hasLength(messageInfo.getTo()) || !StringUtils.hasLength(messageInfo.getMessage())) {
            return false;
        }
        //第二步:添加留言到内存中,即List中
        messageInfos.add(messageInfo);
        return true;
    }


    //查看所有留言的后端代码
    @RequestMapping("/getMessageInfo")
    public List<MessageInfo> getMessageInfo(){
        return messageInfos;
    }
}

(5)测试后端代码

①发表新留言


②获取所有留言

(6)修改前端代码

💚修改的是script部分,记得保存


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>留言板</title>
    <style>
        .container {
            width: 350px;
            height: 300px;
            margin: 0 auto;
            /* border: 1px black solid; */
            text-align: center;
        }

        .grey {
            color: grey;
        }

        .container .row {
            width: 350px;
            height: 40px;

            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .container .row input {
            width: 260px;
            height: 30px;
        }

        #submit {
            width: 350px;
            height: 40px;
            background-color: orange;
            color: white;
            border: none;
            margin: 10px;
            border-radius: 5px;
            font-size: 20px;
        }
    </style>
</head>

<body>
    <div class="container">
        <h1>留言板</h1>
        <p class="grey">输入后点击提交, 会将信息显示下方空白处</p>
        <div class="row">
            <span>谁:</span> <input type="text" name="" id="from">
        </div>
        <div class="row">
            <span>对谁:</span> <input type="text" name="" id="to">
        </div>
        <div class="row">
            <span>说什么:</span> <input type="text" name="" id="say">
        </div>
        <input type="button" value="提交" id="submit" onclick="submit()">
        <!-- <div>A 对 B 说: hello</div> -->
    </div>

    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
    <script>
        //页面一加载时,就请求后端,获取所有留言内容,显示在页面下边
        $.ajax({
            url:"/message/getMessageInfo",      //与后端获取所有留言定义的路径要一样
            type:"get", 
            success:function(messagesList){
                for(var m of messagesList){
                    //拼接显示留言记录
                    //构造节点,即拼接节点的HTML
                    var divE = "<div>"+m.from +"对" + m.to + "说:" + m.message+"</div>";
                    //把节点添加到页面上    
                    $(".container").append(divE);
                }
            }
        });

        function submit(){
            //1. 获取留言的内容
            var from = $('#from').val();
            var to = $('#to').val();
            var say = $('#say').val();
            if (from== '' || to == '' || say == '') {
                return;
            }
            //2.提交留言
            $.ajax({
               url:"/message/publish",          //与后端发布新留言定义的路径要一样
               type:"post", 
               data:{             //data的属性名要和MessageInfo类的属性名一样
                "from":from,
                "to":to,
                "message":say
               },
               success:function(result){
                 if(result){
                    //result为true认为添加成功
                    //3. 构造节点,即拼接节点的HTML
                    var divE = "<div>"+from +"对" + to + "说:" + say+"</div>";
                    //4. 把节点添加到页面上    
                    $(".container").append(divE);
                    //5. 清空输入框的值
                    $('#from').val("");
                    $('#to').val("");
                    $('#say').val("");
                 }else{
                    alert("添加留言失败");
                 }
               }
            });
        }  
    </script>
</body> 
</html>

(7)效果展示

🌟即使点击了刷新,下面的留言依旧会保存

六:图书管理系统

🌟图书管理系统是相对较大的案例,现在只学了Spring Web MVC入门,因此先实现用户登录和图书列表展示的功能,后期再不断完善

(1)前端代码

💗前端代码网盘链接:前端代码( 提取码:lzh7)​​​​​​

(2)准备工作

 🌟①将图书管理系统的前端代码引入到static目录下


 🌟②运行后端并访问,确保没有错误

(1)login.html(登录页)


(2)book_list.html(图书列表展示页)

(3)约定前后端交互接口

1.需求分析

🌟后端需要提供两个服务


①用户登录:账号密码校验接口;根据输入用户名和密码校验登录是否通过


②图书列表:提供图书列表信息

2.用户登录
3.图书列表

(4)后端代码

①需要先写一个BookInfo类,用来存储图书

package com.hlizoo.book;
import lombok.Data;
import java.math.BigDecimal;

@Data
public class BookInfo {
    //图书ID
    private Integer id;
    //图书名字
    private String bookName;
    //图书作者
    private String author;
    //图书数量
    private Integer count;
    //图书定价
    private BigDecimal price;
    //图书出版社
    private String publish;
    //图书借阅状态(状态这里我们用1表示可借阅,其他表示不可借阅)
    private Integer status;
    //图书借阅状态(返回中文)
    private String statusCN;
}

②用户登录

package com.hlizoo.book;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;


@RequestMapping("/user")
@RestController
public class UserController {
    @RequestMapping("/login")
    public Boolean login(String userName, String password, HttpSession session){
        //第一步:校验参数
        if(!StringUtils.hasLength(userName) || !StringUtils.hasLength(password)){
            return false;
        }
        //第二步:验证账户密码是否正确
        if("zhangsan".equals(userName) && "123".equals(password)){
            //此时说明账号密码正确,然后存Session
            session.setAttribute("userName",userName); 
            return true;
        }
        return false;
    }
}

③图书列表展示

package com.hlizoo.book;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;


@RequestMapping("/book")
@RestController
public class BookController {
    @RequestMapping("/getBookList")
    public List<BookInfo> getBookList(){
        //第一步:获取图书的数据(这里的数据是虚拟数据)
        List<BookInfo> bookInfos = mockData();
        //第二步:对图书数据进行处理,比如说状态码返回中文
        for (BookInfo bookInfo : bookInfos) {
            if (bookInfo.getStatus()==1){
                bookInfo.setStatusCN("可借阅!");
            }else {
                bookInfo.setStatusCN("不可借阅!");
            }
        }
        //第三步:返回图书的数据
        return bookInfos;
    }

    //mockData表示虚拟的数据,假的,只是用来测试
    private List<BookInfo> mockData(){
        //关于arraylist的优化:如果大概知道这个集合的容量,就在创建list时去初始化它的容量
        List<BookInfo> bookInfos = new ArrayList<>(15);
        //造15条数据
        for (int i =0;i<15;i++){
            BookInfo bookInfo = new BookInfo();
            bookInfo.setId(i);
            bookInfo.setBookName("图书"+i);
            bookInfo.setAuthor("作者"+i);
            bookInfo.setCount(new Random().nextInt(200));
            bookInfo.setPrice(new BigDecimal(new Random().nextInt(100)));
            bookInfo.setPublish("出版社"+i);
            bookInfo.setStatus(i%5==0?2:1);
            bookInfos.add(bookInfo);
        }
        return bookInfos;
    }
}

(5)测试后端代码

①用户登录


②获取图书列表

(6)修改前端代码

💚修改的是script部分,记得保存


①登录页login.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="css/bootstrap.min.css">
    <link rel="stylesheet" href="css/login.css">
    <script type="text/javascript" src="js/jquery.min.js"></script>
</head>

<body>
    <div class="container-login">
        <div class="container-pic">
            <img src="pic/computer.png" width="350px">
        </div>
        <div class="login-dialog">
            <h3>登陆</h3>
            <div class="row">
                <span>用户名</span>
                <input type="text" name="userName" id="userName" class="form-control">
            </div>
            <div class="row">
                <span>密码</span>
                <input type="password" name="password" id="password" class="form-control">
            </div>
            <div class="row">
                <button type="button" class="btn btn-info btn-lg" onclick="login()">登录</button>
            </div>
        </div>
    </div>
    <script>
        function login() {
            $.ajax({
                url:"/user/login",
                type:"post",
                data:{
                    "userName":$("#userName").val(),
                    "password":$("#password").val(),
                },
                success:function(result){
                    if(result){
                        //如果登录成功,result为true,此时跳转到图书列表页
                        location.href = "book_list.html";
                    }else{
                        alert("用户名或密码输入错误!");
                    }
                }
            });
        }
    </script>
</body>

</html>

②获取图书列表页book_list.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>图书列表展示</title>
    <link rel="stylesheet" href="css/bootstrap.min.css">

    <link rel="stylesheet" href="css/list.css">
    <script type="text/javascript" src="js/jquery.min.js"></script>
    <script type="text/javascript" src="js/bootstrap.min.js"></script>
    <script src="js/jq-paginator.js"></script>

</head>

<body>
    <div class="bookContainer">
        <h2>图书列表展示</h2>
        <div class="navbar-justify-between">
            <div>
                <button class="btn btn-outline-info" type="button" onclick="location.href='book_add.html'">添加图书</button>
                <button class="btn btn-outline-info" type="button" onclick="batchDelete()">批量删除</button>
            </div>
        </div>

        <table>
            <thead>
                <tr>
                    <td>选择</td>
                    <td class="width100">图书ID</td>
                    <td>书名</td>
                    <td>作者</td>
                    <td>数量</td>
                    <td>定价</td>
                    <td>出版社</td>
                    <td>状态</td>
                    <td class="width200">操作</td>
                </tr>
            </thead>
            <tbody>
                <!--留着这段代码是为了下面的拼接Html方便一点 -->
                <!-- <tr>
                    <td><input type="checkbox" name="selectBook" value="1" id="selectBook" class="book-select"></td>
                    <td>4</td>
                    <td>大秦帝国第四册</td>
                    <td>我是作者</td>
                    <td>23</td>
                    <td>33.00</td>
                    <td>北京出版社</td>
                    <td>可借阅</td>
                    <td>
                        <div class="op">
                            <a href="book_update.html?bookId=4">修改</a>
                            <a href="javascript:void(0)" onclick="deleteBook(4)">删除</a>
                        </div>
                    </td>
                </tr> -->
            </tbody>
        </table>

        <div class="demo">
            <ul id="pageContainer" class="pagination justify-content-center"></ul>
        </div>
        <script>

            getBookList();
            function getBookList() {
                $.ajax({
                    url:"/book/getBookList",
                    type:"get",
                    success:function(books){
                        var finalHtml = "";
                        for(var book of books){
                            //book拿的是后端的值,因此要和BookInfo的属性名要一致
                            //根据每一条记录去拼接html,也就是一个<tr>标签
                            finalHtml += '<tr>';
                            finalHtml += '<td><input type="checkbox" name="selectBook" value="'+book.id+'" id="selectBook" class="book-select"></td>';
                            finalHtml += '<td>'+book.id+'</td>';
                            finalHtml += '<td>'+book.bookName+'</td>';
                            finalHtml += '<td>'+book.author+'</td>';
                            finalHtml += '<td>'+book.count+'</td>';
                            finalHtml += '<td>'+book.price+'</td>';
                            finalHtml += '<td>'+book.publish+'</td>';
                            finalHtml += '<td>'+book.statusCN+'</td>';
                            finalHtml += '<td><div class="op">';
                            finalHtml += '<a href="book_update.html?bookId='+book.id+'">修改</a>';
                            finalHtml += '<a href="javascript:void(0)" onclick="deleteBook('+book.id+')">删除</a>';
                            finalHtml += '</div></td></tr>';  
                        }
                        console.log(finalHtml);
                        $("tbody").html(finalHtml);
                    }
                });
            }
    
            //翻页信息
            $("#pageContainer").jqPaginator({
                totalCounts: 100, //总记录数
                pageSize: 10,    //每页的个数
                visiblePages: 5, //可视页数
                currentPage: 1,  //当前页码
                first: '<li class="page-item"><a class="page-link">首页</a></li>',
                prev: '<li class="page-item"><a class="page-link" href="javascript:void(0);">上一页<\/a><\/li>',
                next: '<li class="page-item"><a class="page-link" href="javascript:void(0);">下一页<\/a><\/li>',
                last: '<li class="page-item"><a class="page-link" href="javascript:void(0);">最后一页<\/a><\/li>',
                page: '<li class="page-item"><a class="page-link" href="javascript:void(0);">{{page}}<\/a><\/li>',
                //页面初始化和页码点击时都会执行
                onPageChange: function (page, type) {
                    console.log("第"+page+"页, 类型:"+type);
                }
            });
            function deleteBook(id) {
                var isDelete = confirm("确认删除?");
                if (isDelete) {
                    //删除图书
                    alert("删除成功");
                }
            }
            function batchDelete() {
                var isDelete = confirm("确认批量删除?");
                if (isDelete) {
                    //获取复选框的id
                    var ids = [];
                    $("input:checkbox[name='selectBook']:checked").each(function () {
                        ids.push($(this).val());
                    });
                    console.log(ids);
                    alert("批量删除成功");
                }
            }

        </script>
    </div>
</body>

</html>

(7)效果展示

七:应用分层

(1)问题引入

通过上面的练习,我们学习了Spring MVC简单功能的开发,但是我们也发现了⼀些问题


🌟问题:目前我们程序的文件和代码有点"杂乱",然而当前只是"⼀点点功能"的开发;如果我们把整个项目功能完成呢? 代码会更加的"杂乱无章"!

(2)应用分层概念

💗应用分层是⼀种软件开发设计思想


💜它将应用程序分成N个层次,这N个层次分别负责各自的职责,多个层次之间协同提供完整的功能;根据项目的复杂度,把项目分成三层,四层或者更多层

(3)应用分层作用

💗软件设计原则:高内聚低耦合


①高内聚:一个板块中各个元素之间联系的紧密程度越高越好;如果一个板块中的元素、语句、程序段等等它们的联系度越高,则内聚性越高


②低耦合:一个软件中的各个层或者模块之间依赖的关联程度越低越好,比如一个模块修改一处代码,其他模块代码的改动越少越好


💚应用分层好处总结:

(4)如何分层

💞三层架构


💗代码分层逻辑:先由Controller去调用Service,然后Service去调用Dao

①Controller(表现层):接受请求,返回结果


②Service(业务逻辑层):主要处理业务相关逻辑


③Dao(数据层):处理数据的,包含数据的存储,增删改查


💚还有一个叫model的包,我们一般放的是实体类

(5)代码重构

💛以图书管理系统的代码为例,进行代码重构

1.创建包

💗创建四个包,分别取名为Controller、Service、Dao、model


2.代码分类

①将BookController、UserController放到Controller包


②将BookInfo放到model包

3.举例代码分层

🌟我们以BookController为例,说明代码分层


4.代码分层

①在Dao包下创建一个BookDao文件,用来存放数据

🖤把BookController里的mockData方法移到BookDao去


②在Service包下创建一个BookService文件

🖤将BookController里的业务逻辑层移过去,然后进行改造


③在BookController进行代码重构

(由Controller去调用Service,然后Service去调用Dao)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java中包的概念

内容仅供复习 java中包是把一些类进行打包&#xff0c;在一个包中所有public的类可以直接使用。如果在别的包中要使用一个类就必须import这个包。friendly类型的方法在同个包中可以使用&#xff0c;在不同包里面不可以访问这个类型的方法。 创建一个java项目&#xff0c;在src…

【Http协议】 二

实际开发中&#xff0c;经常需要能够手动的构造出Http协议的请求 一般是通过以下几种方式&#xff1a; 1.通过html中的form表单 2.通过js的ajax 3.Java代码&#xff08;其他各种语言&#xff09; 4.借助一些第三方工具 1.通过html的form标签/表单构造http请求 >对于编写html…

SpringBoot通过注解形式实现系统操作日志

介绍 我们在日常开发工作中&#xff0c;肯定逃不开与日志接触&#xff0c;一些比较严谨的后台管理系统里面会涉及到一些比较重要的资料&#xff0c;有些公司为了知道有哪些人登录了系统&#xff0c;是谁在什么时候修改了用户信息或者资料&#xff0c;所以就有了操作日志这么个…

MySQL 基础学习笔记(一)

目录 1 SQL简介2 MySQL基本语法2.1 语法规则2.2 数据类型 3 DDL3.1 操作数据库3.2 操作表 4 DML4.1 添加数据4.2 修改数据4.3 删除数据 5 DQL5.1 基础查询5.2 条件查询5.3 排序查询5.4 聚合查询5.5 分组查询5.6 分页查询 1 SQL简介 SQL &#xff1a;Structured Query Language&…

基于 MySQL 多通道主主复制的机房容灾方案

文章中介绍了多种 MySQL 高可用技术&#xff0c;并介绍了根据自身需求选择多通道主主复制技术的过程和注意事项。 作者&#xff1a;徐良&#xff0c;现任中国移动智慧家庭运营中心数据库高级经理&#xff0c;多年数据库运维优化经验&#xff0c;历任华为、一线互联网公司高级 D…

使用Nokogiri和OpenURI库进行HTTP爬虫

目录 一、Nokogiri库 二、OpenURI库 三、结合Nokogiri和OpenURI进行爬虫编程 四、高级爬虫编程 1、并发爬取 2、错误处理和异常处理 3、深度爬取 总结 在当今的数字化时代&#xff0c;网络爬虫已经成为收集和处理大量信息的重要工具。其中&#xff0c;Nokogiri和OpenUR…

softmax的高效CUDA编程和oneflow实现初步解析

本文参考了添加链接描述,其中oneflow实现softmax的CUDA编程源代码参考链接添加链接描述 关于softmax的解读以及CUDA代码实现可以参考本人之前编写的几篇文章添加链接描述,添加链接描述,添加链接描述 下面这个图片是之前本人实现的softmax.cu经过接入python接口,最终和pytor…

Javascript基础-BOM

文章目录 BOM——Browser Object Model定时器--延时函数 JS执行机制具体流程 三个常见对象location对象navigator对象history对象 本地存储介绍sessionStoragesessionStorage 存储复杂数据类型字符串拼接 正则表达式元字符 BOM——Browser Object Model 浏览器对象模型&#x…

【LeetCode:26. 删除有序数组中的重复项 | 双指针】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

怎么从外面远程访问服务器设备?

怎么从外面远程访问服务器设备&#xff1f; “我家里有一台服务器设备&#xff0c;当我在学校时需要远程访问家里的服务器。请问是否可以从外网远程访问家里的服务器设备&#xff0c;有什么方法可以实现吗&#xff1f;” 远程访问服务器设备&#xff0c;一种典型…

20量子比特!芬兰成功研发第二台量子计算机

&#xff08;图片来源&#xff1a;网络&#xff09; 近期&#xff0c;芬兰国家技术研究中心&#xff08;VTT&#xff09;宣布&#xff0c;已顺利研发芬兰第二台量子计算机&#xff0c;该计算机具有20个超导量子比特&#xff0c;由芬兰国家技术研究中心&#xff08;VTT&#xf…

java如何获取调用接口的ip?

获取调用者的ip 场景&#xff1a;想知道哪个ip访问的某个接口时&#xff0c;就需要打印出来看看&#xff0c;这时就可以使用这个方法了。 案例&#xff1a; //HttpServletRequest 入参加上,请求对象public ForkResponse queryXXX(RequestBody XXXX xxxx, HttpServletRequest …

Ps:快速选择工具​

对那些有清晰轮廓的对象进行抠图&#xff0c;在 Ps 中传统的方法是钢笔工具和快速选择工具 Quick Selection Tool。其中&#xff0c;快速选择工具以其使用简单快捷而受到众人喜爱。 快捷键&#xff1a;W ◆ ◆ ◆ 常用操作方法与技巧 1、将快速选择工具的笔刷从目标对象的内部…

用前端框架Bootstrap和Django实现用户注册页面

01-新建一个名为“mall_backend”的Project 命令如下&#xff1a; CD E:\Python_project\P_001\myshop-test E: django-admin startproject mall_backend02-新建应用并注册应用 执行下面条命令依次创建需要的应用&#xff1a; CD E:\Python_project\P_001\myshop-test\mall…

Nacos常规问题汇总

一、Nacos常规问题 Nacos是什么 Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集&#xff0c;帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。详情可以参考Nacos官网介绍。 Nacos如何支持多环境 在日常使用中常常需要不同的环…

“破解我!“---160个CrackMe练习002-Afkayas.1.Exe

文章目录 前言题目分析程序分析Keygen 前言 系列之002&#xff0c;记录学习。 题目分析 一道一星的题目 惯例查壳。 32-bit的文件&#xff0c;用的是 VB 写的。 关于Visual Basic&#xff1a; Visual Basic&#xff08;VB&#xff09;是由微软公司开发的包含环境的事件驱动…

酒店预订订房小程序源码系统 带完整搭建教程

酒店预订订房小程序源码系统是一种基于互联网技术的线上预订平台&#xff0c;旨在为用户提供方便快捷的酒店预订服务。该系统通常包括前端用户界面、后端服务器和数据库三个部分&#xff0c;其中前端界面主要展示酒店信息、订房需求信息、订单信息等&#xff0c;后端服务器负责…

国风AI绘画平台Trik;「一个女孩的一生」走红;音视频转文字的精准处理指南;神经网络原理动画 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f251; 智谱AI推出第三代基座大模型ChatGLM3&#xff0c;瞄向了 GPT-4V https://github.com/THUDM/ChatGLM3 10月27日&#xff0c;智谱AI宣布…

EVM6678L 开发教程: 烧写 IBL(Intermediate Bootloader)

目录 EVM6678L 开发教程: 烧写 IBL烧写出厂IBL修改IBL引导格式 EVM6678L 开发教程: 烧写 IBL 参考: C:\ti\mcsdk_2_01_02_06\tools\boot_loader\ibl\doc\README.txtC:\ti\mcsdk_2_01_02_06\tools\boot_loader\ibl\doc\evmc6678-instructions.txtC:\ti\mcsdk_2_01_02_06\tools…

js 异常数组 [空白,Array(10),空白,Array(10),空白]

异常数组 [空白&#xff0c;Array(10)&#xff0c;空白&#xff0c;Array(10)&#xff0c;空白] 的解决方案