【Spring Boot项目】个人在线音乐播放器

news2025/2/21 21:01:22

文章目录

  • 项目简介
  • 数据库表的设计
  • 拦截器及返回数据格式
  • 注册功能
  • 登陆功能
  • 音乐列表相关业务
    • 查询功能
    • 上传音乐
    • 播放音乐
    • 收藏音乐
    • 删除功能
      • 删除单个音乐
      • 批量删除音乐
  • 收藏列表
    • 查询收藏的音乐
    • 取消收藏
  • 注销功能

项目简介

本项目主要是实现了在线播放音乐的功能,用户可以随时登陆听自己喜欢的音乐

项目实现的业务功能

  • 注册功能:用户输入账号,密码,并且确认密码后可以完成注册
  • 登陆功能:用户输入注册成功的账号密码,可以登陆
  • 添加音乐:用户登陆成功后,在主页可以上传音乐
  • 查询音乐:用户可以输入音乐名称或者关键字查询相关的音乐
  • 单个删除:用户可以点击按钮,删除对应的音乐
  • 批量删除:用户一次可以删除多个音乐
  • 收藏功能:用户点击对应的按钮,即可收藏对应的音乐
  • 取消收藏:用户可以在收藏列表点击取消收藏按钮,对应的音乐即被取消收藏
  • 播放功能:用户可以点击每首音乐的播放按钮,即可实时播放音乐
  • 注销功能:用户点击此按钮,退出登陆

项目功能展示

注册:

注册

登陆:

在这里插入图片描述

音乐列表

在这里插入图片描述

查询功能:

在这里插入图片描述

收藏列表:

在这里插入图片描述

收藏列表的查询功能:

在这里插入图片描述

我已经将项目部署到到服务器上了,感兴趣的小伙伴可以访问以下链接:个人在线音乐播放器

数据库表的设计

通过上面的业务功能可知,需要一张用户表保存用户信息,需要一张音乐表保存用户添加的音乐信息,还需要一张收藏表来保存每个用户收藏的音乐

用户表:只保存用户基本信息即主键,用户名,密码

create table user(
    id int primary key auto_increment,
    username varchar(20) not null,
    password varchar(255) not null
);

音乐表:音乐表有主键,音乐名称,歌手,上传时间,因为要播放音乐,所以此处还需要保存音乐地址的信息,多个用户都可以上传音乐,所以还需要一个用户id字段

create table music(
    id int primary key auto_increment,
    title varchar(20) not null,
    singer varchar(20) not null,
    `time` varchar(13) not null,
    url varchar(100) not null,
    user_id int not null
);

收藏表:此表将用户和喜欢的音乐关联起来,所以字段为主键,用户id,音乐id

create table lovemusic(
    id int primary key auto_increment,
    user_id int not null,
    music_id int not null
);

拦截器及返回数据格式

创建拦截器对验证用户是否登陆功能做统一处理

创建拦截器:创建一个类实现HandlerInterceptor接口重写preHandle方法

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        if(session == null || session.getAttribute("user") == null){
            return false;
        }
        return true;
    }
}

添加拦截器:创建一个类实现WebMvcConfigurer接口,重写addInterceptors方法添加拦截规则

@Configuration
public class AppConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        LoginInterceptor loginInterceptor = new LoginInterceptor();
        registry.addInterceptor(loginInterceptor).addPathPatterns("/**").
                excludePathPatterns("/login.html").
                excludePathPatterns("/register.html").
                excludePathPatterns("/user/register").
                excludePathPatterns("/user/login").
                excludePathPatterns("/css/**.css").
                excludePathPatterns("/fonts/**").
                excludePathPatterns("/images/**").
                excludePathPatterns("/js/**.js").
                excludePathPatterns("/player/**");
    }
}

注意:登陆页面,注册页面和所有的静态样式都要开放出来

对返回前端的数据进行统一封装

返回给前端的数据应该包含状态码,提示信息,数据

@Data
public class ResponseMessage {
    private int status;
    private String message;
    private Object data;

    public ResponseMessage(int status, String message, Object data) {
        this.status = status;
        this.message = message;
        this.data = data;
    }
}

注册功能

前端设计

对于注册功能,用户输入用户名,密码,并且必须确认密码之后才可注册,所以在前端就对输入内容进行了判空操作,也对确认密码进行了校验,获取到输入框的用户名和密码,发送POST请求,待后端返回数据后,如果注册成功,跳转到登陆页面,如果注册参数有误,则清空输入框,让用户重新注册

后端设计

前端传来的参数有用户名,密码,首先判断用户名是否存在,根据用户名在用户表中查询,看能否查询出信息,如果查询到了,说明该账号已被注册过了,如果查询不到信息,说名该账号没有被注册,可以添加用户名和密码到数据库中了

    //注册
    @RequestMapping("/register")
    public ResponseMessage register(@RequestParam String username,@RequestParam String password){

        //判断用户名是否存在
        User user = userService.getUserByName(username);
        if(user != null){
            //用户名存在,直接返回错误信息给前端
            return new ResponseMessage(-1,"用户名已存在",false);
        }
        //用户名不存在,往用户表插入注册数据
        int n = userService.insertUser(username,password);
        if(n == 1){
            return new ResponseMessage(1,"注册成功",true);
        }else {
            return new ResponseMessage(-1,"注册失败",false);
        }
    }

查询和插入sql:

    <select id="getUserByName" resultType="com.example.demo.model.User">
        select * from user where username=#{username}
    </select>
    <insert id="insertUser">
        insert into user (username,password) values(#{username},#{password})
    </insert>

登陆功能

前端设计

获取到输入框的用户名和密码后,对数据进行判空后,然后发送POST请求,待后端返回响应后,如果登陆成功,则跳转到音乐列表页面,如果用户名或密码不正确,提示用户错误信息

后端设计

前端传来的参数有用户名,密码,首先校验用户名是否存在,如果用户名不存在返回给前端错误信息,如果用户名存在,再校验密码是否正确,如果正确,创建session保存用户信息

    //登陆
    @RequestMapping("/login")
    public ResponseMessage login(@RequestParam String username, @RequestParam String password, HttpServletRequest req){
        //校验用户是否存在
        User user = userService.getUserByName(username);
        if(user == null){
            return new ResponseMessage(-1,"用户名不存在","");
        }else {
            //校验密码是否正确
            if(!password.equals(user.getPassword())){
                return new ResponseMessage(-1,"密码错误","");
            }
            //创建session保存用户信息
            HttpSession session = req.getSession(true);
            session.setAttribute("user",user);
            return new ResponseMessage(1,"登陆成功",user);
        }
    }

查询sql:

       <select id="getUserByName" resultType="com.example.demo.model.User">
        select * from user where username=#{username}
       </select>

音乐列表相关业务

查询功能

前端设计

页面一加载就要查询该用户所有的音乐,并且用户也可以手动的输入音乐昵称进行模糊查询,所以前端创建函数的时候,该函数的参数可以为空,也可以是音乐名称,当参数为空的时候就要在页面加载完成后立即调用,当参数不为空的时候,就要由用户手动点击按钮进行调用

后端设计

当不输入任何名称时候,默认查找所有音乐,也就是当访问到该页面时自动进行了不带任何名称的查询,所以一加载到页面就能看到全部的音乐信息,当输入名称时,根据输入的名称模糊匹配,在进行查询的时候默认带上用户id,因为数据库中的音乐是多个用户拥有的

    //根据歌名查询音乐,当歌名为空时,查询全部音乐(根据歌名和用户id查询)
    @RequestMapping("/findmusic")
    public ResponseMessage findMusic(String musicName,HttpServletRequest req){
        //获取到用户id,根据用户id查询该用户的音乐
        HttpSession session = req.getSession();
        User user = (User)session.getAttribute("user");
        int userId = user.getId();
        //当查询内容为空时,查询该用户所有音乐
        if(musicName == null){
            List<Music> allMusics = musicService.getAllMusic(userId);
            return new ResponseMessage(1,"查询成功",allMusics);
        }
        //当查询内容不为空时,根据查询内容模糊匹配
        List<Music> musics = musicService.findByName(musicName,userId);
        return new ResponseMessage(1,"查询成功",musics);
    }

查询sql:

    <select id="getAllMusic" resultType="com.example.demo.model.Music">
        select * from music where user_id=#{userId}
    </select>
    <select id="findByName" resultType="com.example.demo.model.Music">
        select * from music where title like concat('%',#{musicName},'%') and user_id=#{userId}
    </select>

上传音乐

前端设计

上传的音乐包含音乐文件和歌手,所以前端要对参数进行判空校验,参数校验完后,就发送body格式为FormData格式的数据,因为文件上传需要使用改格式,待后端返回响应后,如果上传成功就跳转到音乐列表页面,如果上传失败就提示用户错误信息

后端设计

  1. 校验该音乐是否存在

上传音乐的参数有音乐文件和歌手,后端接收文件的类型为MultipartFile,需要注意的是必须添加@RequestPart注解,在获取到音乐文件后,首先要判断该音乐存在不存在,这里我们认为歌手和音乐文件的名称相同的音乐是同一首音乐,所以得先获取上传文件的名称,根据这个名称和歌手在数据中校验该音乐是否存在,由于同一首音乐可以被多个用户上传,所以此处还必须带上用户id这个参数,当该音乐存在时,返回前端错误信息,当不存在时在执行后边逻辑

        HttpSession session = req.getSession();
        User user = (User) session.getAttribute("user");
        int userId = user.getId();

        //检查数据库是否已经有了该音乐(音乐名称+歌手)
        String fileName = file.getOriginalFilename(); //获取文件名称,xxx.mp3
        String title = fileName.substring(0,fileName.lastIndexOf(".")); //获取音乐名称
        Music getMusic = musicService.getMusic(title,singer,userId);
        if(getMusic != null){
            return new ResponseMessage(-1,"此音乐已经存在",false);
        }

查询sql:

    <select id="getMusic" resultType="com.example.demo.model.Music">
        select * from music where title=#{title} and singer=#{singer} and user_id=#{userId}
    </select>
  1. 保存文件到服务器本地

如果该音乐不存在,先保存音乐到服务器,此时我的电脑就是服务器,所以保存在本地磁盘,如果部署到linux上,linux就是服务器主机,需要保存到linux,在保存的时候如果出现异常,就保存失败,返回错误信息给前端

注意:保存文件的时候,应该给每个用户有一个单独的文件来保存音乐,保证每个用户在删除音乐文件时,别的用户的音乐文件不受干扰

        //保存文件到服务器
        //SAVE_PATH为配置的本机路径
        String path = SAVE_PATH+userId+"/"+fileName;
        File dest = new File(path);
        //目录不存在,则创建目录
        if(!dest.exists()){
            dest.mkdirs();
        }
        try {
            file.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
            return new ResponseMessage(-1,"上传失败",false);
        }
  1. 插入数据库

将文件保存在本地后,就要将该音乐保存到数据中中,此时需要先获取插入需要的数据,因为用户id,歌手,音乐名称在前面都获取过了,所以此处只需获取时间和url,此处的url为播放音乐时的路径

        //保存音乐的url,该url为播放音乐时的后端路径
        String url = "/music/get?path="+fileName;
        //获取上传的时间
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        String time = df.format(new Date());

在获取到所有字段的信息后,就将这些数据组装到Music对象中,往数据库中插入这个对象

    Music music = new Music();
    music.setSinger(singer);
    music.setTitle(title);
    music.setTime(time);
    music.setUserId(user.getId());
    music.setUrl(url);

    int n = musicService.insertMusic(music);
    if(n == 1){
        return new ResponseMessage(1,"上传成功",true);
    }else {
        dest.delete();
        return new ResponseMessage(-1,"上传失败",false);
    }

插入sql:

    <insert id="insertMusic">
        insert into music (title,singer,time,url,user_id) values(#{title},#{singer},#{time},#{url},#{userId})
    </insert>

播放音乐

对于播放音乐功能,用户点击播放按钮,后端应该返回给前端音乐文件的内容,我们可以使用ResponseEntity<byte[]>,将文件的内容读到字节数组中,再返回给前端,我们根据前端请求的参数和本地的文件名可以获取到本地保存音乐的文件,使用Files.readAllBytes(file.toPath())将文件内容读到字节数组中返回给前端

    //播放音乐
    @RequestMapping("/get")
    public ResponseEntity<byte[]> get(String path,HttpServletRequest req){ //返回值为body内容
        HttpSession session = req.getSession();
        User u = (User) session.getAttribute("user");
        int userId = u.getId();
        //获取文件路径,需要用户id,因为每个用户的音乐文件路径相互独立
        File file = new File(SAVE_PATH+userId+"/"+path);
        byte[] bytes = null; //将文件的内容读到字节数组中
        try {
            bytes = Files.readAllBytes(file.toPath());
            if(bytes != null){
                return ResponseEntity.ok(bytes); //返回body内容和ok状态
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ResponseEntity.badRequest().build(); //400
    }

收藏音乐

前端设计

点击某个音乐的收藏按钮,就会携带该音乐的id发送请求,后端接受到音乐id后,将该音乐保存在收藏表中,待后端返回响应,提示成功或失败信息

后端设计

对于收藏功能来说,需要知道收藏的音乐,以及是哪个用户,即建立音乐id和用户id之间对应的关系,但是在往收藏表中添加数据时,需要校验该用户是否已经收藏过该音乐,如果收藏过了就无需再次收藏,如果没有收藏,则插入数据

    //收藏音乐
    @RequestMapping("/likemusic")
    public ResponseMessage likeMusic(String id, HttpServletRequest req){
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute("user");

        //获取到音乐id和用户id
        int musicId = Integer.parseInt(id);
        int userId = user.getId();
        //查看该用户是否收藏过该音乐
        LoveMusic loveMusic = loveMusicService.getLoveMusic(userId,musicId);
        if(loveMusic != null){
            //收藏过,返回错误信息
            return new ResponseMessage(-1,"该音乐已被收藏",false);
        }
        //未收藏过,往收藏表中插入数据
        int n = loveMusicService.insertLoveMusic(userId,musicId);
        if(n == 1){
            return new ResponseMessage(1,"收藏成功",true);
        }else {
            return new ResponseMessage(-1,"收藏失败",false);
        }
    }

查询与插入sql:

    <select id="getLoveMusic" resultType="com.example.demo.model.LoveMusic">
        select * from lovemusic where user_id=#{userId} and music_id=#{musicId}
    </select>
    <insert id="insertLoveMusic">
        insert into lovemusic (user_id,music_id) values (#{userId},#{musicId})
    </insert>

删除功能

删除功能提供了两种,一是每次只删除一个音乐,二是可以选中多个音乐,一次性删除,但是删除时都需要校验该音乐是否存在,因为只有音乐存在才能删除成功

注意: 删除时需要注意一个问题,就是删除音乐时如果用户收藏了这个音乐,那么收藏表中的数据也因该被删除

删除单个音乐

前端设计

点击某个音乐对应的删除按钮,携带音乐id发送请求,后端会将该音乐的数据库中数据和本地保存的音乐文件删掉,待后端返回响应,如果删除成功书信音乐列表页面,如果删除失败提示错误信息

后端设计

前端点击删除,传递给后端的参数是音乐id,后端需要从session中获取到用户id,因为用户点击删除按钮,删除的是自己拥有的音乐,所以需要结合用户id删除,否则就会把其他用户拥有的音乐误删,删除完数据库中数据后,还需要删除本地保存的音乐文件,每个用户都有自己的文件保存路径,所以删除本地路径的时候,删除用户对应路径的音乐文件

    //删除单个音乐
    @RequestMapping("/delete")
    public ResponseMessage deleteById(String id,HttpServletRequest req){
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute("user");
        //获取到用户id
        int userId = user.getId();
        //获取音乐id
        Integer musicId = Integer.parseInt(id);
        //校验数据库是否存在要删除的音乐
        Music music = musicService.getById(musicId,userId);
        if(music == null){
            //如果不存在返回给前端错误信息
            return new ResponseMessage(-1,"该音乐不存在",false);
        }
        //如果存在则删除数据库中音乐
        int n = musicService.deleteById(musicId,userId);

        //删除服务器路径保存的音乐
        String path = music.getTitle(); //获取音乐名称
        String url = music.getUrl();
        String suffix = url.substring(url.lastIndexOf(".")); //获取后缀
        path = SAVE_PATH+userId+"/"+path+suffix; //拼接路径
        File file = new File(path);
        if(file.delete()){
            //同步查看收藏的音乐是否有该音乐,如果有也要删除收藏的该音乐
            int m = loveMusicService.deleteLoveMusicByMusicId(musicId,userId);
            return new ResponseMessage(1,"删除成功",true);
        }else {
            return new ResponseMessage(-1,"删除失败",false);
        }
    }

批量删除音乐

前端设计

与上述删除一个音乐类似,只是请求携带的数据是音乐id数组,该数组通过遍历复选框得到,如果遍历的复选框被选中则将此对应的音乐id添加到数组中

后端设计

批量删除的逻辑与上面删除一个的逻辑相同,只是前端传递的是一个音乐id数组,遍历该数组执行与上述相同的逻辑即可

    //批量删除
    @RequestMapping("/deletepart")
    public ResponseMessage deletePart(@RequestParam("id[]") List<Integer> ids,HttpServletRequest req){
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute("user");
        int userId = user.getId();
        int sum = 0;
        //拿到每一个id,先查再删
        for(int i = 0;i < ids.size();i++){
            int musicId = ids.get(i);
            Music music = musicService.getById(musicId,userId);
            if(music == null){
                return new ResponseMessage(-1,"要删除的音乐不存在",false);
            }
            int n = musicService.deleteById(ids.get(i),userId);
            String path = music.getTitle();
            String url = music.getUrl();
            String suffix = url.substring(url.lastIndexOf("."));
            path = SAVE_PATH+userId+"/"+path+suffix;
            File file = new File(path);
            if(file.delete()){
                int m = loveMusicService.deleteLoveMusicByMusicId(musicId,userId);
                sum += n;
            }else {
                return new ResponseMessage(-1,"删除失败",false);
            }
        }
        if(sum == ids.size()){
            return new ResponseMessage(1,"删除成功",true);
        }else {
            return new ResponseMessage(-1,"删除失败",false);
        }
    }

查询和删除sql:

    <select id="getById" resultType="com.example.demo.model.Music">
        select * from music where id=#{id} and user_id=#{userId}
    </select>
        <delete id="deleteById">
        delete from music where id=#{id} and user_id=#{userId}
    </delete>
        <delete id="deleteLoveMusicByMusicId">
        delete from lovemusic where music_id=#{musicId} and user_id=#{userId}
    </delete>

收藏列表

查询收藏的音乐

前端设计

查询收藏音乐的功能与前面在音乐列表查询的功能类似,页面一加载就要发送请求,获取该用户全部收藏的音乐此时的查询是查询内容为空时的查询,当用户输入名称点击查询按钮时,就要根据该用户输入的名称进行模糊查询

后端设计

在跳转到收藏列表后,后端就要查询到该用户所有的收藏音乐返回给前端,当然用户页可以通过音乐名称来查询收藏的音乐,所以在查询的时候需要判断用户输入的音乐名称是否为空,如果为空就查询当前用户所有收藏的音乐,如果不为空,就根据用户输入的音乐名称进行模糊匹配

    //查询当前用户收藏的音乐
    @RequestMapping("/findlovemusic")
    public ResponseMessage findLoveMusic(String musicName,HttpServletRequest req){
        HttpSession session = req.getSession();
        User user = (User) session.getAttribute("user");
        //获取到该用户id
        int userId = user.getId();
        //如果传递的参数为空,就查询所有音乐
        if(musicName == null){
            List<Music> musics = loveMusicService.getLoveMusicByUserId(userId);
            return new ResponseMessage(1,"查询成功",musics);
        }
        //传递参数不为空,根据查询内容模糊匹配
        List<Music> musics = loveMusicService.getLoveMusicByMusicName(musicName,userId);
        return new ResponseMessage(1,"查询成功",musics);
    }

查询sql:

    <select id="getLoveMusicByUserId" resultType="com.example.demo.model.Music">
        select * from music where id in (select music_id from lovemusic where user_id=#{userId})
    </select>
        <select id="getLoveMusicByMusicName" resultType="com.example.demo.model.Music">
        select * from music where id in (select music_id from lovemusic where user_id=#{userId}) and title like concat('%',#{musicName},'%')
    </select>

取消收藏

前端设计

用户点击某音乐的对应的收藏按钮时,携带该音乐id发送请求,后端接收到该音乐id后就会将该音乐从收藏表中删掉,待后端返回响应后,如果取消收藏成功,就刷新当前用户收藏列表页面,如果取消失败,提示错误信息

后端设计

取消收藏只是将音乐从收藏表中删除,不会从音乐表中删除,也不会删除该音乐文件

    //取消当前用户收藏的某个音乐
    @RequestMapping("/deletelovemusic")
    public ResponseMessage deleteLoveMusic(@RequestParam String id, HttpServletRequest req){
        //获取音乐id
        Integer musicId = Integer.parseInt(id);
        User user = (User)req.getSession().getAttribute("user");
        //获取用户id
        Integer userId = user.getId();
        //根据用户id和音乐id,删除收藏表中对应的数据
        int n = loveMusicService.deleteLoveMusic(userId,musicId);
        if(n == 1){
            return new ResponseMessage(1,"取消收藏成功",true);
        }
        return new ResponseMessage(-1,"取消失败",false);
    }

删除sql:

    <delete id="deleteLoveMusic">
        delete from lovemusic where user_id=#{userId} and music_id=#{musicId}
    </delete>

注销功能

用户点击注销按钮,删除session中保存的用户信息,重定向到登陆页面

    //注销
    @RequestMapping("/logout")
    public void logout(HttpServletRequest req,HttpServletResponse resp) throws IOException {
        HttpSession session = req.getSession();
        session.removeAttribute("user");
        resp.sendRedirect("../login.html");
    }

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

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

相关文章

[RCTF 2019]Nextphp

知识点&#xff1b;利用 FFI 绕过 disable_functionFFI 介绍与利用 首先 FFI 肯定要开&#xff0c;且 PHP 版本肯定要早 7.4 以上 简介&#xff1a; FFI &#xff0c;可以让我们直接在PHP脚本中调用C语言写的库中的函数。 FFI 的安全性问题 FFI虽然给了我们很大的灵活性&am…

人脸视频检索系统设计(C++)

目录 人脸检索系统框架的构建 1 一.软件实现的主要界面 1 二.软件的需求概括 1 三.软件代码设计过程中需要注意的问题 2 四.程序到目前为止产生的诸多缺陷 4 五.程序的详细设计过程 4 1.输入部分的设计 4 2.检测结果部分的设计过程 10 人脸检索系统框架的构建 ------FaceMFC_v…

腾讯148道面试题,(程序员必备学习方向)全会拿45Koffer没问题

相信你可能经历过这些&#xff1a; 已经工作两三年了&#xff0c;每个项目都会加班加点全力以赴去完成&#xff0c;薪资增长幅度却不如人意。听说年后离职的老同事&#xff0c;金三刚拿下高薪offer&#xff0c;年薪直奔50万了。由于现在的公司接触不到新技术&#xff0c;对自己…

思科网络部署实验

作者介绍&#xff1a; 作者&#xff1a;小刘在C站 每天分享课堂笔记&#xff0c;一起努力&#xff0c;共赴美好人生&#xff01; 夕阳下&#xff0c;是最美的绽放。 今天带个大家一个实验&#xff0c;为网络篇的综合实验&#xff0c;有能力的可以试一试不会的可以私信小刘。 配…

排序算法:插入排序、冒泡排序、选择排序、希尔排序、堆排序、快速排序、归并排序

排序算法相关总结&#xff0c;涉及的排序算法有&#xff1a;插入排序、冒泡排序、选择排序、希尔排序、堆排序、快速排序、归并排序&#xff08;动图不是自己画的&#x1f31e;&#xff09;。 目录1.插入排序2.冒泡排序3.选择排序4.希尔排序5.堆排序6.快速排序7.归并排序总结稳…

【Revit二次开发】模型中存储数据——参数和外部存储(Parameter, Schema and Entity)

模型中存储数据参数读取写入外部存储SchemaEntity快速获取外部存储参数参数 在Revit平台API中&#xff0c;每个图元对象都有参数属性&#xff0c;它是隶属于图元所有属性的集合&#xff0c;在此集合中更改属性值。 每个图元的参数都有一个与之关联的ElementId类型的ID大多数参…

KMP算法

文章目录KMP算法KMP算法 KMP算法要解决的问题就是在字符串&#xff08;也叫主串&#xff09;中的模式&#xff08;pattern&#xff09;定位问题。说简单点就是我们平时常说的关键字搜索。模式串就是关键字&#xff08;接下来称它为P&#xff09;&#xff0c;如果它在一个主串&…

C++图的建立---邻接矩阵-----邻接表

目录 图的表示方式 邻接矩阵 邻接表 图的遍历 深度优先遍历 深度优先遍历算法步骤&#xff1a; 图的广度优先遍历 广度优先遍历算法步骤: 图的邻接矩阵存储来创建图 代码 运行结果&#xff1a; 图的邻接表存储来创建图 如下图&#xff1a; 运行结果&#xff1…

认定能源管理体系的条件

能源管理体系认证申请清单&#xff08;GB/T 23331-2012《能源管理体系 要求》国家标准&#xff09;体系运行时间超过6个月 1、营业执照复印件&#xff1b; 2、组织机构代码证&#xff08;适用时&#xff09;&#xff1b; 3、生产许可证和其他行政许可证明复印件、资质证明等…

保卫城市消费券安全,从这些做起

近日&#xff0c;顶象发布的《城市消费券安全调研报告》&#xff08;以下简称《调研报告》&#xff09;中明确提出&#xff0c;自消费券发放之日起&#xff0c;黑灰产便盯上了这块蛋糕。据不完全统计&#xff0c;190多亿的消费券&#xff0c;消费者只抢到29%。 而在百度键入消…

公众号网课答案在线查搭建

公众号网课答案在线查搭建 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 题库&#xff1a;题库后台&#xff08;点击跳转&#…

操作系统实验三虚拟存储器管理之模拟页面置换算法(FIFOLRU)

文章目录 一、概述 &#xff08;1&#xff09;置换算法 &#xff08;2&#xff09;缺页率与命中率 二、先进先出置换算法&#xff08;FIFO&#xff09; (1)定义 (2)示例 &#xff08;3&#xff09;Belady异常 三、最近最久未使用置换算法&#xff08;LRU&#xff09; &#…

LeetCode每日一题——764. 最大加号标志

LeetCode每日一题系列 题目&#xff1a;764. 最大加号标志 难度&#xff1a;普通 文章目录LeetCode每日一题系列题目示例思路题解题目 在一个 n x n 的矩阵 grid 中&#xff0c;除了在数组 mines 中给出的元素为 0&#xff0c;其他每个元素都为 1。mines[i] [xi, yi]表示 g…

谈谈HTTP协议的方法里,GET和POST的区别?我来教你如何回答~

目录 前言 一、什么是GET、POST&#xff1f; 1.1GET 1.2POST 二、如何轻松回答&#xff1f; 第一步、直接盖棺定论&#xff1a; 第二步、谈细节上的区别&#xff1a; 前言 要想回答好这个问题&#xff0c;咱们先来了解以下什么是GET、POST方法&#xff0c;有哪些细节要注…

阿宇wifi球机如何连接手机

首先下载APP&#xff0c;请见以下三种方式&#xff1a; &#xff08;1&#xff09;至APP Store、各大应用市场搜索 “智U”&#xff0c;下载并安装APP。  &#xff08;2&#xff09;登录ezcloud.uniview.com官网&#xff0c;扫描界面右下方智U APP二维码&#xff0c;下载并…

SpringBoot线上服务假死解决,CPU内存正常

背景 开发小伙伴都知道线上服务挂掉&#xff0c;基本都是因为cpu或者内存不足&#xff0c;出现GC频繁OOM之类的情况。本篇文章区别以上的情况给小伙伴们 带来不一样的服务挂掉。 还记得哔哩哔哩713事故中那场诡计多端的0吗&#xff1f; 对就是这个0&#xff0c;和本次事故没关…

Python基础知识入门(二)

Python基础知识入门&#xff08;一&#xff09; 一、数字类型 Python 数字数据类型用于存储数值。数据类型是不允许改变的&#xff0c;如改变数字数据类型的值&#xff0c;将重新分配内存空间。 1.数字函数 函数 描述 abs(x) 返回数字的绝对值。如abs(-10) 返回 10。 fa…

前端小游戏——推箱子

最近刚刚更新完了HTML&#xff0c;CSS的万字总结&#xff0c;有很多人已经学习完了文章&#xff0c;感觉反馈还不错&#xff0c;今天&#xff0c;用HTML&#xff0c;CSS&#xff0c;JS的知识编写了一个童年经典游戏 - 推箱子&#xff0c;供学习参考。 推荐学习专栏&#xff1a…

EdrawMax Ultimate v12.0 图表和流程图

EDraw Max 是一个多合一的应用程序&#xff0c;用作演示构建器、图表创建者、可视化业务规划师和协作空间&#xff08;用于快速共享图表和模型并接收反馈&#xff09;。 该软件可用于哪些潜在用途&#xff1f; 任何人都可以从 EDraw Max 中受益。它所针对的主题和感兴趣的领域…

【EasyRL学习笔记】第十一章 模仿学习

文章目录一、前言二、行为克隆三、逆强化学习四、第三人称视角模仿学习五、序列生成和聊天机器人六、关键词总结七、习题一、前言 模仿学习 (imitation learning&#xff0c;IL) 讨论的问题是&#xff0c;假设我们连奖励都没有&#xff0c;要怎么进行更新以及让智能体与环境交…