SpringBoot+Vue3 完成小红书项目

news2024/11/26 6:18:37

简介

该项目采用微服务架构,实现了前后端分离的系统设计。在前端,我们选择了 Vue3 配合 TypeScript 和 ElementUi 框架,以提升开发效率和用户体验。而在后端,则是运用 SpringBoot 和 Mybatis-plus 进行开发,保证了系统的高效和稳定。此外,我们引入了 ElasticSearch 作为全文检索服务,以加快搜索速度和提高检索效率。同时,通过 WebSocket 技术实现了实时聊天和消息推送功能,增强了用户的互动体验。

代码下载

https://url21.ctfile.com/f/15432821-1020751544-c0e7e4?p=8418
(访问密码: 8418)

项目目录

  • yanhuo-web 前段页面
  • yanhuo-auth 认证服务
  • yanhuo-common 公共模块,存放一些工具类或公用类
  • yanhuo-platform 烟火 app 主要功能模块
  • yanhuo-im 聊天模块
  • yanhuo-search 搜索模块
  • yanhuo-util 第三方服务模块,邮箱短信,oss 对象存储服务
  • yanhuo-xo 对象存放模块

源码讲解

Controller 源码示例

首先来看 AlbumController 中的代码,主要讲解八个容易误解的方面。

  1. @RestController:这是一个组合注解,它表示这个类是一个控制器,并且其中的所有方法都会返回数据而不是视图。

  2. @RequestMapping(“/album”):这个注解用于将 HTTP 请求映射到 MVC 和 REST 控制器的处理方法上。在这里,它将所有的请求映射到以/album 为前缀的 URL。

  3. @Autowired:这个注解用于自动注入 Spring 容器中的 bean。在这里,它注入了一个 AlbumService 的实例,这个实例提供了专辑的增删改查操作。

  4. getAlbumPageByUserId 方法:这个方法用于根据用户 ID 获取专辑列表,并支持分页。它接受三个参数:当前页(currentPage),分页数(pageSize)和用户 ID(userId)。它调用 albumService 的 getAlbumPageByUserId 方法来获取数据,并返回一个 Result<?>对象。

  5. saveAlbumByDTO 方法:这个方法用于保存专辑。它接受一个 AlbumDTO 对象作为参数,并使用 ValidatorUtils.validateEntity 方法进行数据校验。然后,它调用 albumService 的 saveAlbumByDTO 方法来保存专辑,并返回一个 Result<?>对象。

  6. getAlbumById 方法:这个方法用于根据专辑 ID 获取专辑。它接受一个 albumId 作为参数,并调用 albumService 的 getAlbumById 方法来获取数据,并返回一个 Result<?>对象。

  7. deleteAlbumById 方法:这个方法用于根据专辑 ID 删除专辑。它接受一个 albumId 作为参数,并调用 albumService 的 deleteAlbumById 方法来删除数据,并返回一个 Result<?>对象。

  8. updateAlbumByDTO 方法:这个方法用于更新专辑。它接受一个 AlbumDTO 对象作为参数,并使用 ValidatorUtils.validateEntity 方法进行数据校验。然后,它调用 albumService 的 updateAlbumByDTO 方法来更新专辑,并返回一个 Result<?>对象。

package com.yanhuo.platform.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yanhuo.common.result.Result;
import com.yanhuo.common.validator.ValidatorUtils;
import com.yanhuo.common.validator.group.AddGroup;
import com.yanhuo.common.validator.group.UpdateGroup;
import com.yanhuo.platform.service.AlbumService;
import com.yanhuo.xo.dto.AlbumDTO;
import com.yanhuo.xo.entity.Album;
import com.yanhuo.xo.vo.AlbumVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/album")
@RestController
public class AlbumController {

    @Autowired
    AlbumService albumService;

    /**
     * 根据用户id获取专辑
     * @param currentPage 当前页
     * @param pageSize 分页数
     * @param userId 用户id
     * @return 专辑数
     */
    @RequestMapping("getAlbumPageByUserId/{currentPage}/{pageSize}")
    public Result<?> getAlbumPageByUserId(@PathVariable long currentPage, @PathVariable long pageSize,String userId){
        Page<Album> page =  albumService.getAlbumPageByUserId(currentPage,pageSize,userId);
        return Result.ok(page);
    }

    /**
     * 保存专辑
     * @param albumDTO 专辑实体
     * @return success
     */
    @RequestMapping("saveAlbumByDTO")
    public Result<?> saveAlbumByDTO(@RequestBody AlbumDTO albumDTO) {
        ValidatorUtils.validateEntity(albumDTO, AddGroup.class);
        albumService.saveAlbumByDTO(albumDTO);
        return Result.ok();
    }


    /**
     * 根据专辑id获取专辑
     * @param albumId 专辑id
     * @return 专辑实体
     */
    @RequestMapping("getAlbumById")
    public Result<?> getAlbumById(String albumId) {
        AlbumVo albumVo = albumService.getAlbumById(albumId);
        return Result.ok(albumVo);
    }

    /**
     * 根据专辑id删除专辑
     * @param albumId 专辑id
     * @return success
     */
    @RequestMapping("deleteAlbumById")
    public Result<?> deleteAlbumById(String albumId) {
        albumService.deleteAlbumById(albumId);
        return Result.ok();
    }

    /**
     * 更新专辑
     * @param albumDTO 专辑实体
     * @return success
     */
    @RequestMapping("updateAlbumByDTO")
    public Result<?> updateAlbumByDTO(@RequestBody AlbumDTO albumDTO) {
        ValidatorUtils.validateEntity(albumDTO, UpdateGroup.class);
        albumService.updateAlbumByDTO(albumDTO);
        return Result.ok();
    }
}

Service 源码示例

下面代码是一个服务实现类,用于处理与笔记相关的业务逻辑。这个类使用了 MyBatis-Plus 框架来简化数据库操作,并使用了 Hutool 工具类库来处理 JSON 数据。下面是这段代码的详细解释:

  1. NoteServiceImpl 类继承了 ServiceImpl<NoteDao, Note>,这意味着它继承了 MyBatis-Plus 提供的基本 CRUD 操作。NoteDao 是一个接口,用于定义与笔记相关的数据库操作方法。Note 是一个实体类,用于映射数据库中的笔记表。

  2. 类中注入了多个服务,包括用户服务、标签服务、分类服务、ES 客户端、关注服务、点赞或收藏服务以及 OSS 客户端。这些服务将在后面的方法中被使用。

  3. getNoteById 方法用于根据笔记 ID 获取笔记详情。该方法首先通过 getById 方法从数据库中获取笔记对象,然后将浏览次数加 1 并更新到数据库。接下来,通过用户 ID 获取用户对象,并将用户名、头像和更新时间设置到 NoteVo 对象中。然后,检查当前用户是否关注了该笔记的作者,并设置 NoteVo 对象的 isFollow 属性。接着,检查当前用户是否点赞或收藏了该笔记,并设置 NoteVo 对象的 isLikeisCollection 属性。最后,通过标签笔记关系服务获取该笔记的所有标签,并设置到 NoteVo 对象中。

  4. saveNoteByDTO 方法用于保存新的笔记。该方法首先从当前用户上下文中获取用户 ID,然后将传入的 JSON 字符串转换为 NoteDTO 对象,并将其转换为 Note 对象。然后,将用户 ID 设置到 Note 对象中,并保存到数据库。接下来,更新用户的动态数量。然后,处理标签关系,将标签 ID 和笔记 ID 保存到标签笔记关系表中。然后,通过 OSS 客户端上传图片,并将图片 URL 保存到 Note 对象中。最后,将 Note 对象更新到数据库,并将笔记信息添加到 ES 搜索引擎中。

  5. deleteNoteByIdsupdateNoteByDTOgetHotPage 方法目前没有实现具体的业务逻辑。这段代码的主要功能是处理与笔记相关的业务逻辑,包括获取笔记详情、保存新的笔记、更新笔记等。代码中使用了 MyBatis-Plus 框架来简化数据库操作,并使用了 Hutool 工具类库来处理 JSON 数据。此外,代码中还使用了 ES 搜索引擎和 OSS 对象存储服务来处理笔记的搜索和图片存储。

package com.yanhuo.platform.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yanhuo.common.auth.AuthContextHolder;
import com.yanhuo.common.exception.YanHuoException;
import com.yanhuo.common.result.Result;
import com.yanhuo.common.utils.ConvertUtils;
import com.yanhuo.platform.client.EsClient;
import com.yanhuo.platform.client.OssClient;
import com.yanhuo.platform.service.*;
import com.yanhuo.xo.dao.NoteDao;
import com.yanhuo.xo.dto.NoteDTO;
import com.yanhuo.xo.entity.*;
import com.yanhuo.xo.vo.NoteSearchVo;
import com.yanhuo.xo.vo.NoteVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class NoteServiceImpl extends ServiceImpl<NoteDao, Note> implements NoteService {
    @Autowired
    UserService userService;

    @Autowired
    TagNoteRelationService tagNoteRelationService;

    @Autowired
    TagService tagService;

    @Autowired
    CategoryService categoryService;

    @Autowired
    EsClient esClient;

    @Autowired
    FollowerService followerService;

    @Autowired
    LikeOrCollectionService likeOrCollectionService;

    @Autowired
    OssClient ossClient;


    @Override
    public NoteVo getNoteById(String noteId) {
        Note note = this.getById(noteId);
        note.setViewCount(note.getViewCount() + 1);
        User user = userService.getById(note.getUid());
        NoteVo noteVo = ConvertUtils.sourceToTarget(note, NoteVo.class);
        noteVo.setUsername(user.getUsername())
                .setAvatar(user.getAvatar())
                .setTime(note.getUpdateDate().getTime());

        boolean follow = followerService.isFollow(user.getId());
        noteVo.setIsFollow(follow);

        String currentUid = AuthContextHolder.getUserId();
        List<LikeOrCollection> likeOrCollectionList = likeOrCollectionService.list(new QueryWrapper<LikeOrCollection>().eq("like_or_collection_id", noteId).eq("uid", currentUid));
        if(!likeOrCollectionList.isEmpty()) {
            Set<Integer> types = likeOrCollectionList.stream().map(LikeOrCollection::getType).collect(Collectors.toSet());
            noteVo.setIsLike(types.contains(1));
            noteVo.setIsCollection(types.contains(3));
        }

        //得到标签
        List<TagNoteRelation> tagNoteRelationList = tagNoteRelationService.list(new QueryWrapper<TagNoteRelation>().eq("nid", noteId));
        List<String> tids = tagNoteRelationList.stream().map(TagNoteRelation::getTid).collect(Collectors.toList());

        if (!tids.isEmpty()) {
            List<Tag> tagList = tagService.listByIds(tids);
            noteVo.setTagList(tagList);
        }

        this.updateById(note);
        return noteVo;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public String saveNoteByDTO(String noteData, MultipartFile[] files) {
        String currentUid = AuthContextHolder.getUserId();
        NoteDTO noteDTO = JSONUtil.toBean(noteData, NoteDTO.class);
        Note note =ConvertUtils.sourceToTarget(noteDTO, Note.class);
        note.setUid(currentUid);
        boolean  save = this.save(note);
        if(!save){
            return null;
        }
        // TODO 需要往专辑中添加

        User user = userService.getById(currentUid);
        user.setTrendCount(user.getTrendCount() + 1);
        userService.updateById(user);

        List<String> tids = noteDTO.getTagList();
        List<TagNoteRelation> tagNoteRelationList = new ArrayList<>();

        String tags="";
        if(!tids.isEmpty()){
            for (String tid : tids) {
                TagNoteRelation tagNoteRelation = new TagNoteRelation();
                tagNoteRelation.setTid(tid);
                tagNoteRelation.setNid(note.getId());
                tagNoteRelationList.add(tagNoteRelation);
            }
            tagNoteRelationService.saveBatch(tagNoteRelationList);
            tags  = tagService.listByIds(tids).stream().map(Tag::getTitle).collect(Collectors.joining(","));
        }
        Category category = categoryService.getById(note.getCid());
        Category parentCategory = categoryService.getById(note.getCpid());

        List<String> dataList;
        try {
            Result<List<String>> result = ossClient.saveBatch(files, 1);
            dataList = result.getData();
        }catch (Exception e){
           throw new YanHuoException("添加图片失败");
        }
        String[] urlArr = dataList.toArray(new String[dataList.size()]);
        String urls = JSONUtil.toJsonStr(urlArr);
        note.setUrls(urls);
        note.setNoteCover(urlArr[0]);
        this.updateById(note);

        // 往es中添加数据
        NoteSearchVo noteSearchVo = ConvertUtils.sourceToTarget(note, NoteSearchVo.class);
        noteSearchVo.setUsername(user.getUsername())
                .setAvatar(user.getAvatar())
                .setLikeCount(0L)
                .setCategoryName(category.getTitle())
                .setCategoryParentName(parentCategory.getTitle())
                .setTags(tags)
                .setTime(note.getUpdateDate().getTime());
        esClient.addNote(noteSearchVo);
        return note.getId();
    }

    @Override
    public void deleteNoteByIds(List<String> noteIds) {

    }

    @Override
    public String updateNoteByDTO(NoteDTO noteDTO) {
        return null;
    }

    @Override
    public Page<NoteVo> getHotPage(long currentPage, long pageSize) {
        return null;
    }
}

Vue3 源码示例

这段代码是一个Vue3组件的模板和脚本部分,用于展示和加载关注者的动态(trends)。下面是对代码的详细解释:

模板部分(Template)
  1. <template> 标签内定义了组件的结构。
  2. 使用了Vue的v-infinite-scroll指令来实现无限滚动加载更多数据。
  3. 使用v-for指令循环渲染trendData数组中的每个动态项。
  4. 每个动态项包含用户头像、用户信息、动态内容、图片和交互按钮(点赞、评论等)。
  5. 使用v-ifv-else指令来条件渲染加载中的图片和已加载的图片。
  6. 事件绑定(@click)用于处理用户交互,如跳转到用户页面、点赞、查看动态等。
脚本部分(Script)
  1. 导入了必要的Vue组件和图标。
  2. 使用Vue 3的Composition API(<script setup>)定义组件的逻辑。
  3. 响应式变量,如currentPagepageSizetrendData等,用于控制分页和存储数据。
  4. handleLoad函数,用于处理图片加载完成的事件。
  5. toUser函数,用于导航到用户页面。
  6. getFollowTrends函数,用于获取关注者的动态数据。
  7. loadMoreData函数,用于加载更多动态数据。
  8. toMain函数,用于显示动态的详细内容。
  9. close函数,用于关闭动态详细内容的显示。
  10. refresh函数,用于刷新动态数据。
  11. like函数,用于处理点赞和取消点赞的操作。
    12.initData函数,用于初始化动态数据。
  12. 在组件挂载时调用initData函数。
样式部分(Style)
  1. 使用了Less预处理器编写样式。
  2. 定义了.container.trend-container.trend-item等类,用于设置组件的布局和样式。
  3. 使用了flex布局来排列用户头像、信息和图片。
  4. 使用了scoped属性,确保样式只应用于当前组件。
<template>
  <div class="container" v-infinite-scroll="loadMoreData">
    <ul class="trend-container">
      <li class="trend-item" v-for="(item, index) in trendData" :key="index">
        <a class="user-avatar">
          <img class="avatar-item" :src="item.avatar" @click="toUser(item.uid)" />
        </a>
        <div class="main">
          <div class="info">
            <div class="user-info">
              <a class>{{ item.username }}</a>
            </div>
            <div class="interaction-hint">
              <span>{{ item.time }}</span>
            </div>
            <div class="interaction-content" @click="toMain(item.nid)">
              {{ item.content }}
            </div>
            <div class="interaction-imgs" @click="toMain(item.nid)">
              <div class="details-box" v-for="(url, index) in item.imgUrls" :key="index">
                <el-image
                  v-if="!item.isLoading"
                  :src="url"
                  @load="handleLoad(item)"
                  style="height: 230px; width: 100%"
                >
                </el-image>
                <el-image
                  v-else
                  :src="url"
                  class="note-img animate__animated animate__fadeIn animate__delay-0.5s"
                  fit="cover"
                ></el-image>
              </div>
            </div>
            <div class="interaction-footer">
              <div class="icon-item">
                <i
                  class="iconfont icon-follow-fill"
                  style="width: 1em; height: 1em"
                  @click="like(item.nid, item.uid, index, -1)"
                  v-if="item.isLike"
                ></i>
                <i
                  class="iconfont icon-follow"
                  style="width: 1em; height: 1em"
                  @click="like(item.nid, item.uid, index, 1)"
                  v-else
                ></i
                ><span class="count">{{ item.likeCount }}</span>
              </div>
              <div class="icon-item">
                <ChatRound style="width: 0.9em; height: 0.9em" /><span class="count">{{
                  item.commentCount
                }}</span>
              </div>
              <div class="icon-item"><More style="width: 1em; height: 1em" /></div>
            </div>
          </div>
        </div>
      </li>
    </ul>
    <div class="feeds-loading">
      <Refresh style="width: 1.2em; height: 1.2em" color="rgba(51, 51, 51, 0.8)" />
    </div>
    <FloatingBtn @click-refresh="refresh"></FloatingBtn>
    <Main
      v-show="mainShow"
      :nid="nid"
      class="animate__animated animate__zoomIn animate__delay-0.5s"
      @click-main="close"
    ></Main>
  </div>
</template>
<script lang="ts" setup>
import { ChatRound, More, Refresh } from "@element-plus/icons-vue";
import { ref } from "vue";
import { getFollowTrendPage } from "@/api/follower";
import { formateTime } from "@/utils/util";
import FloatingBtn from "@/components/FloatingBtn.vue";
import Main from "@/pages/main/main.vue";
import type { LikeOrCollectionDTO } from "@/type/likeOrCollection";
import { likeOrCollectionByDTO } from "@/api/likeOrCollection";
import { useRouter } from "vue-router";

const router = useRouter();
const currentPage = ref(1);
const pageSize = ref(5);
const trendData = ref<Array<any>>([]);
const trendTotal = ref(0);
const topLoading = ref(false);
const mainShow = ref(false);
const nid = ref("");
const likeOrCollectionDTO = ref<LikeOrCollectionDTO>({
  likeOrCollectionId: "",
  publishUid: "",
  type: 0,
});

const handleLoad = (item: any) => {
  item.isLoading = true;
};

const toUser = (uid: string) => {
  router.push({ name: "user", state: { uid: uid } });
};

const getFollowTrends = () => {
  getFollowTrendPage(currentPage.value, pageSize.value).then((res) => {
    const { records, total } = res.data;
    console.log(records, total);
    records.forEach((item: any) => {
      item.time = formateTime(item.time);
      trendData.value.push(item);
    });
    trendTotal.value = total;
  });
};

const loadMoreData = () => {
  currentPage.value += 1;
  getFollowTrends();
};

const toMain = (noteId: string) => {
  nid.value = noteId;
  mainShow.value = true;
};

const close = (nid: string, isLike: boolean) => {
  const index = trendData.value.findIndex((item) => item.nid === nid);
  trendData.value[index].isLike = isLike;
  mainShow.value = false;
};

const refresh = () => {
  let scrollTop =
    window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
  const clientHeight =
    window.innerHeight ||
    Math.min(document.documentElement.clientHeight, document.body.clientHeight);
  if (scrollTop <= clientHeight * 2) {
    const timeTop = setInterval(() => {
      document.documentElement.scrollTop = document.body.scrollTop = scrollTop -= 100;
      if (scrollTop <= 0) {
        clearInterval(timeTop);
        topLoading.value = true;
        setTimeout(() => {
          currentPage.value = 1;
          trendData.value = [];
          getFollowTrends();
          topLoading.value = false;
        }, 500);
      }
    }, 10); //定时调用函数使其更顺滑
  } else {
    document.documentElement.scrollTop = 0;
    topLoading.value = true;
    setTimeout(() => {
      currentPage.value = 1;
      trendData.value = [];
      getFollowTrends();
      topLoading.value = false;
    }, 500);
  }
};

const like = (nid: string, uid: string, index: number, val: number) => {
  likeOrCollectionDTO.value.likeOrCollectionId = nid;
  likeOrCollectionDTO.value.publishUid = uid;
  likeOrCollectionDTO.value.type = 1;
  likeOrCollectionByDTO(likeOrCollectionDTO.value).then(() => {
    trendData.value[index].isLike = val == 1;
    trendData.value[index].likeCount += val;
  });
};

const initData = () => {
  getFollowTrends();
};

initData();
</script>

<style lang="less" scoped>
.container {
  flex: 1;
  padding: 0 24px;
  padding-top: 72px;
  width: 67%;
  height: 100vh;
  margin: 0 auto;

  .feeds-loading {
    margin: 3vh;
    text-align: center;
  }

  .trend-container {
    .trend-item {
      display: flex;
      flex-direction: row;
      padding-top: 24px;
      max-width: 100vw;

      .user-avatar {
        margin-right: 24px;
        flex-shrink: 0;

        .avatar-item {
          width: 48px;
          height: 48px;
          display: flex;
          align-items: center;
          justify-content: center;
          cursor: pointer;
          border-radius: 100%;
          border: 1px solid rgba(0, 0, 0, 0.08);
          object-fit: cover;
        }
      }

      .main {
        flex-grow: 1;
        flex-shrink: 1;
        display: flex;
        flex-direction: row;
        padding-bottom: 12px;
        border-bottom: 1px solid rgba(0, 0, 0, 0.08);

        .info {
          flex-grow: 1;
          flex-shrink: 1;

          .user-info {
            display: flex;
            flex-direction: row;
            align-items: center;
            font-size: 16px;
            font-weight: 600;
            margin-bottom: 4px;

            a {
              color: #333;
            }
          }
          .interaction-hint {
            font-size: 14px;
            color: rgba(51, 51, 51, 0.6);
            margin-bottom: 8px;
          }
          .interaction-content {
            display: flex;
            font-size: 14px;
            color: #333;
            margin-bottom: 12px;
            line-height: 140%;
            cursor: pointer;
          }

          .interaction-imgs {
            display: flex;
            .details-box {
              width: 25%;
              border-radius: 4px;
              margin: 8px 12px 0 0;
              cursor: pointer;

              .note-img {
                width: 100%;
                height: 230px;
                display: flex;
                border-radius: 4px;
                align-items: center;
                justify-content: center;
                cursor: pointer;
                object-fit: cover;
              }
            }
          }

          .interaction-footer {
            margin: 8px 12px 0 0;
            padding: 0 12px;
            display: flex;
            justify-content: space-between;
            align-items: center;

            .icon-item {
              display: flex;
              justify-content: left;
              align-items: center;
              color: rgba(51, 51, 51, 0.929);
              .count {
                margin-left: 3px;
              }
            }
          }
        }
      }
    }
  }
}
</style>

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

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

相关文章

CFS三层靶机

参考博客&#xff1a; CFS三层内网靶场渗透记录【详细指南】 - FreeBuf网络安全行业门户 CFS三层靶机搭建及其内网渗透【附靶场环境】 | TeamsSix CFS三层网络环境靶场实战 - PANDA墨森 - 博客园 (cnblogs.com) CFS三层靶机实战--内网横向渗透 - 知乎 (zhihu.com) CFS靶机…

C++类和对象-C++对象模型和this指针->成员变量和成员函数分开存储、this指针概念、空指针访问成员函数、const修饰成员函数

#include<iostream> using namespace std; //成员变量 和 成员函数 分开储存的 class Person { public: Person() { mA 0; } //非静态成员变量占对象空间 int mA; //静态成员变量不占对象空间 static int mB; //函数也不占对象空间…

安卓价值1-如何在电脑上运行ADB

ADB&#xff08;Android Debug Bridge&#xff09;是Android平台的调试工具&#xff0c;它是一个命令行工具&#xff0c;用于与连接到计算机的Android设备进行通信和控制。ADB提供了一系列命令&#xff0c;允许开发人员执行各种操作&#xff0c;包括但不限于&#xff1a; 1. 安…

儿时游戏“红色警戒”之“AI警戒”

一、红色警戒里“警戒”命令背后的算法原理是什么 在《红色警戒》系列即时战略游戏中&#xff0c;“警戒”命令背后的算法原理相对简单但又实用&#xff0c;其核心目标是让单位能够自动检测并反击一定范围内的敌方单位。虽然具体的实现细节未公开&#xff0c;但可以推测其基本…

ICLR 2023#Learning to Compose Soft Prompts for Compositional Zero-Shot Learning

组合零样本学习&#xff08;CZSL&#xff09;中Soft Prompt相关工作汇总&#xff08;一&#xff09; 文章目录 组合零样本学习&#xff08;CZSL&#xff09;中Soft Prompt相关工作汇总&#xff08;一&#xff09;ICLR 2023#Learning to Compose Soft Prompts for Compositional…

变形金刚:第 2 部分:变形金刚的架构

目录 一、说明 二、实现Transformer的过程 第 1 步&#xff1a;代币化&#xff08;Tokenization&#xff09; 第 2 步&#xff1a;对每个单词进行标记嵌入 第 3 步&#xff1a;对每个单词进行位置嵌入 第 4 步&#xff1a;输入嵌入 第 5 步&#xff1a;编码器层 2.5.1 多头自注…

Linux makefile 大型多文件的处理

最简单的例子是 main.cpp test.cpp test.h 首先将这三个写好 然后的话 test.cpp 上面输出 helloworld 首先我们在同一个目录下创建一个makefile 文件 然后用vim 编辑它 如下图&#xff08;使用的c&#xff09; mybin 是我们的可执行程序 gcc是编译的命令 gcc 前面必…

[HCIE]vxlan --静态隧道

实验目的:1.pc2与pc3互通&#xff08;二层互通&#xff09;&#xff1b;2.pc1与pc3互通&#xff08;三层互通&#xff09; 实验说明&#xff1a;sw1划分vlan10 vlan20 ;sw2划分vlan30&#xff1b;上行接口均配置为Trunk 实验步骤&#xff1a; 1.配置CE1/CE2/CE3环回口互通&a…

深度学习之反向传播算法

反向传播算法 数学公式算法代码结果 算法中一些函数的区别 数学公式 算法代码 这里用反向传播算法&#xff0c;计算 y w * x模型 import numpy as np import matplotlib.pyplot as ply#反向传播算法&#xff0c;需要使用pytorch框架&#xff0c; #这里导入pytorch框架&#xf…

力扣_面试题:配对交换

配对交换 链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题目意思就是交换相邻两个二进制位 &#xff0c;用&分别取出even&#xff08;偶位和&#xff09;odd&#xff08;奇位和&#xff09; 偶位和用0xAAAAAAAA&#xff0c;奇…

[数学建模] 计算差分方程的收敛点

[数学建模] 计算差分方程的收敛点 差分方程&#xff1a;差分方程描述的是在离散时间下系统状态之间的关系。与微分方程不同&#xff0c;差分方程处理的是在不同时间点上系统状态的变化。通常用来模拟动态系统&#xff0c;如在离散时间点上更新状态并预测未来状态。 收敛点&…

4核16g云服务器多少钱?

4核16G服务器租用优惠价格26元1个月&#xff0c;腾讯云轻量4核16G12M服务器32元1个月、96元3个月、156元6个月、312元一年&#xff0c;阿腾云atengyun.com分享4核16服务器租用费用价格表&#xff0c;阿里云和腾讯云详细配置报价和性能参数表&#xff1a; 腾讯云4核16G服务器价…

2024年2月份实时获取地图边界数据方法,省市区县街道多级联动【附实时geoJson数据下载】

首先&#xff0c;来看下效果图 在线体验地址&#xff1a;https://geojson.hxkj.vip&#xff0c;并提供实时geoJson数据文件下载 可下载的数据包含省级geojson行政边界数据、市级geojson行政边界数据、区/县级geojson行政边界数据、省市区县街道行政编码四级联动数据&#xff0…

C#使用迭代器显示公交车站点

目录 一、涉及到的知识点 1.迭代器 2.IList接口及实现IList接口的Add方法 二、实例 1.源码 2.生成效果 一、涉及到的知识点 1.迭代器 迭代器是.NET 4.5开始的一个新特性&#xff0c;它是可以返回相同类型的值的有序序列的一段代码。迭代器可用作方法、运算符或get访问器…

Java安全 CC链6分析

CC链6分析 前言CC链分析核心transform链Lazymap类TiedMapEntry类HashMap方法 最终exp 前言 CC链6不受jdk版本与cs版本的影响&#xff0c;在Java安全中最为通用&#xff0c;并且非常简洁&#xff0c;非常有学习的必要&#xff0c;建议在学习CC链6之前先学习一下 URLDNS链 和 CC…

【Python如何通过多种方法输出九九乘法表】

1、九九乘法表方法一&#xff1a; for i in range(1, 10): # 对i在1到9进行循环&#xff08;不包括10&#xff09;for j in range(1, i 1): # 对j在1到i进行循环&#xff08;不包括i&#xff09;print(%d * %d %2d % (j, i, j * i), end ) # 对j,i进行格式化输出&#x…

【C++函数探幽】内联函数inline

&#x1f4d9; 作者简介 &#xff1a;RO-BERRY &#x1f4d7; 学习方向&#xff1a;致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f4d2; 日后方向 : 偏向于CPP开发以及大数据方向&#xff0c;欢迎各位关注&#xff0c;谢谢各位的支持 目录 1. 前言2.概念3.特性…

位图

目录 位图的概念 位图的实现 寻找位置 set reset test 面试题 1.给定100亿个整数&#xff0c;设计算法找到只出现一次的整数&#xff1f; 2. 给两个文件&#xff0c;分别有100亿个整数&#xff0c;我们只有1G内存&#xff0c;如何找到两个文件交集&#xff1f; 3. 位…

SpringBoot Starter造了个自动锁轮子

可能有人会有疑问&#xff0c;为什么外面已经有更好的组件&#xff0c;为什么还要重复的造轮子&#xff0c;只能说&#xff0c;别人的永远是别人的&#xff0c;自己不去造一下&#xff0c;就只能知其然&#xff0c;而不知其所以然。&#xff08;其实就为了卷&#xff09; 在日常…

VS Code之Java代码重构和源代码操作

文章目录 支持的代码操作列表调用重构分配变量字段和局部变量的差别Assign statement to new local variable在有参构造函数中将参数指定成一个新的字段 将匿名类转换为嵌套类什么是匿名类&#xff1f;匿名类转换为嵌套类的完整演示 转换为Lambda表达式Lambda 表达式是什么?转…