探花交友_第10章_搭建后台系统(新版)

文章目录

  • 探花交友_第10章_搭建后台系统(新版)
      • 1.1 概述
      • 1.2 API网关
        • 1.2.1 搭建网关
          • 依赖
          • 引导类
          • 跨域问题配置类
          • 配置文件
          • 测试
        • 1.2.2 配置鉴权管理器
      • 1.3 Nacos配置中心
        • 1.3.1 添加依赖
        • 1.3.2 添加bootstrap.yml配置
        • 1.3.3 nacos添加配置
    • 2、后台系统
      • 2.1 概述
      • 2.2 环境前端搭建
        • 2.2.1 导入数据库
        • 2.2.2 导入静态页面
          • nginx安装
          • 测试
      • 2.3 搭建后端环境
        • 2.3.1 实体类Admin
        • 2.3.2 导入项目
        • 2.3.3 创建配置文件
      • 2.4 管理员登录
        • 2.4.1 生成验证码
          • 接口文档
          • SystemController
        • 2.4.2 用户登录
          • 接口文档
          • SystemController
          • SystemService
        • 2.4.3 获取用户资料
          • 接口文档
          • AdminVO
          • SystemController
          • SystemService
    • 3、用户管理
      • 3.1 需求分析
      • 3.2 查询用户列表
        • 后台系统
          • ManageController
          • ManagerService
        • 服务提供者
          • UserInfoApi
          • UserInfoImpl
      • 3.3 查看用户详情
        • tanhu-admin
          • ManageController
          • ManagerService
      • 3.4 查看视频列表
        • tanhua-admin
          • ManageController
          • ManagerService
        • tanhua-dubbo-interface
        • tanhua-dubbo-mongo
      • 3.5 查看动态列表
        • tanhua-admin
          • ManageController
          • ManagerService
        • tanhua-dubbo-interface
        • tanhua-dubbo-mongo

1.1 概述

API网关有很多实现方式,我们通过SpringCloud Gateway实现

使用Nacos作为配置中心

1.2 API网关

1.2.1 搭建网关

需求:创建新的网关模块tanhua-gateway,并配置路由

依赖
<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- 监控检查--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!-- nacos配置中心依赖支持<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency>--><dependency><groupId>com.itheima</groupId><artifactId>tanhua-commons</artifactId><version>1.0-SNAPSHOT</version></dependency>
</dependencies>
引导类

tanhua-gateway模块配置引导类

@SpringBootApplication
public class GatewayApplication {public static void main(String[] args) {SpringApplication.run(GatewayApplication.class, args);}
}
跨域问题配置类
package com.itheima.gateway.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.util.pattern.PathPatternParser;/*** 跨域支持*/
@Configuration
public class CorsConfig {@Beanpublic CorsWebFilter corsFilter() {CorsConfiguration config = new CorsConfiguration();config.addAllowedMethod("*");config.addAllowedOrigin("*");config.addAllowedHeader("*");UrlBasedCorsConfigurationSource source =new UrlBasedCorsConfigurationSource(new PathPatternParser());source.registerCorsConfiguration("/**", config);return new CorsWebFilter(source);}
}
配置文件
server:port: 8888
spring:application:name: tanhua-gatewaycloud:nacos:discovery:server-addr: 192.168.136.160:8848gateway:globalcors:add-to-simple-url-handler-mapping: truecorsConfigurations:'[/**]':allowedHeaders: "*"allowedOrigins: "*"allowedMethods:- GET- POST- DELETE- PUT- OPTIONroutes:# 手机端访问- id: tanhua-app-serveruri: lb://tanhua-app-serverpredicates:- Path=/app/**filters:- StripPrefix= 1# 管理后台- id: tanhua-adminuri: lb://tanhua-adminpredicates:- Path=/admin/**filters:- StripPrefix= 1
#自定义配置,定义不需要校验token的连接
gateway:excludedUrls: /user/login,/user/loginVerification,/system/users/verification,/system/users/login
测试

由于加入了网关,所有的请求统一发送到网关,路由到具体的服务。测试时注意修改请求地址

tanhua-app-server访问地址 ip:8888/app/ (IP以自己模拟器为准)

1.2.2 配置鉴权管理器

在网关内部可以通过过滤器完成统一鉴权,限流,日志记录等操作。

tanhua-gateway模块配置鉴权过滤器

@Component
public class AuthFilter implements GlobalFilter, Ordered {@Value("${gateway.excludedUrls}")private List<String> excludedUrls; //配置不校验的连接@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//获取当前请求连接String url = exchange.getRequest().getURI().getPath();System.out.println( "url:"+ url);//放行不需要校验的接口if(excludedUrls.contains(url)){return chain.filter(exchange);}//获取请求头中的tokenString token = exchange.getRequest().getHeaders().getFirst("Authorization");//后台系统页面发送的token以"Bearer "开头,需要处理if(!StringUtils.isEmpty(token)){token = token.replace("Bearer ", "");}ServerHttpResponse response = exchange.getResponse();//使用工具类,判断token是否有效boolean verifyToken = JwtUtils.verifyToken(token);//如果token失效,返回状态码401,拦截if(!verifyToken) {Map<String, Object> responseData = new HashMap<>();responseData.put("errCode", 401);responseData.put("errMessage", "用户未登录");return responseError(response,responseData);}return chain.filter(exchange);}//响应错误数据private Mono<Void> responseError(ServerHttpResponse response,Map<String, Object> responseData){// 将信息转换为 JSONObjectMapper objectMapper = new ObjectMapper();byte[] data = new byte[0];try {data = objectMapper.writeValueAsBytes(responseData);} catch (JsonProcessingException e) {e.printStackTrace();}// 输出错误信息到页面DataBuffer buffer = response.bufferFactory().wrap(data);response.setStatusCode(HttpStatus.UNAUTHORIZED);response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");return response.writeWith(Mono.just(buffer));}/*** 设置过滤器的执行顺序*/@Overridepublic int getOrder() {return Ordered.LOWEST_PRECEDENCE;}
}

1.3 Nacos配置中心

Nacos提供了注册中心和配置管理的能力,使用Nacos可以快速实现服务发现、服务配置管理等需求。

这里以网关工程(tanhua-gateway)为例

1.3.1 添加依赖

tanhua-gateway模块中添加配置中心依赖

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

1.3.2 添加bootstrap.yml配置

tanhua-gateway模块中添加引导文件bootstrap.yml,并设置

server:port: 8888
spring:profiles:active: prodapplication:name: tanhua-gatewaycloud:nacos:discovery:server-addr: 192.168.136.160:8848config:server-addr: 192.168.136.160:8848file-extension: yml

1.3.3 nacos添加配置

在nacos中添加网关配置

添加配置内容

配置如下内容

server:port: 8888
spring:cloud:gateway:globalcors:add-to-simple-url-handler-mapping: truecorsConfigurations:'[/**]':allowedHeaders: "*"allowedOrigins: "*"allowedMethods:- GET- POST- DELETE- PUT- OPTIONroutes:# 用户微服务- id: tanhua-app-serveruri: lb://tanhua-app-serverpredicates:- Path=/app/**filters:- StripPrefix= 1# 文章微服务- id: tanhua-adminuri: lb://tanhua-adminpredicates:- Path=/admin/**filters:- StripPrefix= 1
gateway:excludedUrls: /user/login,/user/loginVerification,/system/users/verification,/system/users/login

2、后台系统

2.1 概述

探花交友APP建立的后台管理系统,目的是完成探花交友项目的业务闭环,主要功能包括:用户管理、动态管理、审核管理以及系统管理。

课程中实现的功能有:登录、首页、用户管理、动态审核。

2.2 环境前端搭建

2.2.1 导入数据库

将资料中的tanhua-admin.sql引入到mysql数据库中

2.2.2 导入静态页面

后台系统也是采用前后端分离的方式,前端采用Vue.js实现,关于前端系统我们不进行实现,拿来直接使用。

nginx安装

将资料中提供的nginx解压到合适的位置

其中html目录中为,vue编译后的所有页面。

修改Nginx的/conf/nginx.conf配置文件:

    server {listen       8088;  #请求端口server_name  localhost;#charset koi8-r;#access_log  logs/host.access.log  main;location / {root   html;index  index.html index.htm;}location  /management {proxy_pass http://127.0.0.1:8888/admin;  #转发java后台网关地址}#....略}
  • 访问vue页面的路径:localhost:8088
  • 其中内部调用java服务器网关的路径 : http://127.0.0.1:8888/admin
测试

双击nginx.exe,待启动完成后访问:http://127.0.0.1:8088即可访问后台项目

2.3 搭建后端环境

后端工程模块是准备好的,依赖两个实体类,这里先准备好。

2.3.1 实体类Admin

admin:是后台中超级管理员对象

package com.tanhua.model.admin;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;//后台系统的管理员对象
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Admin implements Serializable {/*** id*/private Long id;/*** 用户名*/private String username;/*** 密码*/private String password;/*** 头像*/private String avatar;
}

2.3.2 导入项目

将今日资料中的tanhua-admin模块导入到探花项目中,完成开发。

2.3.3 创建配置文件

创建application.yml配置文件

spring:datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/tanhua-admin?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=falseusername: rootpassword: rootrabbitmq:host: 192.168.136.160port: 5672username: guestpassword: guest    redis:host: 192.168.136.160port: 6379cloud:  #nacos配置nacos:discovery:server-addr: 192.168.136.160:8848
dubbo:    #dubbo配置registry:address: spring-cloud://localhostconsumer:check: falseretries: 0protocols:dubbo:port: -1#配置短信平台信息
tanhua:  #手机验证码,咱们自己注册(不要白嫖)sms:signName: 物流云商templateCode: SMS_106590012accessKey: LTAI4GKgob9vZ53k2SZdyAC7secret: LHLBvXmILRoyw0niRSBuXBZewQ30laoss:accessKey: LTAI4GKgob9vZ53k2SZdyAC7secret: LHLBvXmILRoyw0niRSBuXBZewQ30laendpoint: oss-cn-beijing.aliyuncs.combucketName: tanhua143url: https://tanhua143.oss-cn-beijing.aliyuncs.comaip:appId: 22837663apiKey: nA43galrxfUZTGtYRVK8F8tbsecretKey: MQp567q4nGnIKfniURa2XAw8bT1SlPE3huanxin:appkey: 1110201018107234#tanhuaclientId: YXA6nxJJ_pdEQ_eYUlqcRicS4wclientSecret: YXA6GMUxVEZhAvxlMn4OvHSXbWuEUTE
#mybaits-plus
mybatis-plus:global-config:db-config:table-prefix: tb_    #数据库表前缀id-type: auto        #数据库表主键的策略

2.4 管理员登录

后台系统的登录模块独立于APP端的登录。

2.4.1 生成验证码

验证码:页面端发送请求到服务端。服务端生成一个验证码的图片,已流的形式返回

接口文档

接口地址:http://192.168.136.160:3000/project/25/interface/api/322

  • 手机端获取验证码可以通过手机号码保证唯一性。

  • 页面端验证码自动生成UUID保证唯一性

SystemController

tanhua-admin模块中的SystemController中添加方法。

/*** 生成图片验证码*/
@GetMapping("/verification")
public void verification(String uuid, HttpServletResponse response) throws IOException {//1、通过工具类生成验证码对象(图片数据和验证码信息)LineCaptcha captcha = CaptchaUtil.createLineCaptcha(299, 97);String code = captcha.getCode(); //2、调用service,将验证码存入到redisredisTemplate.opsForValue().set(Constants.CAP_CODE+uuid,code);//3、通过输出流输出验证码captcha.write(response.getOutputStream());
}

2.4.2 用户登录

接口文档

接口地址:http://192.168.136.160:3000/project/25/interface/api/313

SystemController
/*** 用户登录*/
@PostMapping("/login")
public ResponseEntity login(@RequestBody Map map) {Map retMap = adminService.login(map);return ResponseEntity.ok(retMap);
}
SystemService
//用户登录
public ResponseEntity login(Map map) {//1、获取请求的参数(username,password,verificationCode(验证码),uuid)String username = (String) map.get("username");String password = (String) map.get("password");String verificationCode = (String) map.get("verificationCode");String uuid = (String) map.get("uuid");//2、判断用户名或者密码是否为空if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {//用户名或者密码为空//throw new BusinessException("用户名或者密码为空");Map map1 = new HashMap();map.put("message","用户名或者密码为空");return ResponseEntity.status(500).body(map1);}//3、判断验证码是否正确if (StringUtils.isEmpty(username)) {//验证码为空throw new BusinessException("验证码为空");}//从redis中获取验证码String key = Constants.CAP_CODE+uuid;String code = redisTemplate.opsForValue().get(key);if (StringUtils.isEmpty(code) || !code.equals(verificationCode)) {//验证码错误throw new BusinessException("验证码错误");}redisTemplate.delete(key);//4、根据用户名查询用户QueryWrapper<Admin> qw = new QueryWrapper<>();qw.eq("username", username);Admin admin = adminMapper.selectOne(qw);//5、判断用户是否存在,密码是否一致password = SecureUtil.md5(password); //md5加密if(admin == null || !admin.getPassword().equals(password)) {//用户名错误或者密码不一致throw new BusinessException("用户名或者密码");}//6、通过JWT生成tokenMap<String, Object> claims = new HashMap<String, Object>();claims.put("username", username);claims.put("id", admin.getId());String token = JwtUtils.getToken(claims);//8、构造返回值Map res = new HashMap();res.put("token", token);return ResponseEntity.ok(res);
}

2.4.3 获取用户资料

接口文档

文档地址:http://192.168.136.160:3000/project/25/interface/api/295

AdminVO
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AdminVo {/*** id*/private String id;/*** 用户名*/private String username;/*** 头像*/private String avatar;public static AdminVo init(Admin admin) {AdminVo vo = new AdminVo();vo.setAvatar(admin.getAvatar());vo.setUsername(admin.getUsername());vo.setId(admin.getId().toString());return vo;}}
SystemController
/*** 获取用户的信息*/
@PostMapping("/profile")
public ResponseEntity profile() {AdminVo vo = adminService.profile();return ResponseEntity.ok(vo);
}
SystemService
//获取当前用户的用户资料
public AdminVo profile() {Long id = AdminHolder.getId();Admin admin = adminMapper.selectById(id);return AdminVo.init(admin);
}

3、用户管理

3.1 需求分析

用户管理:对探花交友客户端注册用户的管理(查询业务数据),使用Dubbo的形式调用tanhua-dubbo-service获取响应的数据结果

3.2 查询用户列表

后台系统

tanhu-admin模块配置ManageControllerManagerService

ManageController
@GetMapping("/users")
public ResponseEntity users(@RequestParam(defaultValue = "1") Integer page,@RequestParam(defaultValue = "10") Integer pagesize) {PageResult result = managerService.findAllUsers(page,pagesize);return ResponseEntity.ok(result);
}
ManagerService
public ResponseEntity findAllUsers(Integer page, Integer pagesize) {//1、调用API分页查询数据列表   Ipage<UserInfo>IPage<UserInfo> iPage = userInfoApi.findAll(page,pagesize);//2、需要将Ipage转化为PageResultPageResult result = new PageResult(page, pagesize, iPage.getTotal(), iPage.getRecords());//3、构造返回值return ResponseEntity.ok(result);
}

服务提供者

tanhua-dubbo-interface模块的UserInfoApi接口定义查询所有用户信息方法

tanhua-dubbo-db模块UserInfoImpl实现类中添加查询方法

UserInfoApi
/*** 分页查询所有用户信息** @param page* @param pagesize* @return*/
IPage findAll(Integer page, Integer pagesize);
UserInfoImpl

UserInfoApiImpl中实现查询所有用户信息方法

@Override
public IPage<UserInfo> findAll(Integer page, Integer pagesize) {return userInfoMapper.selectPage(new Page<UserInfo>(page,pagesize),null);
}

3.3 查看用户详情

tanhu-admin

ManageController
/*** 根据id查询用户详情** @param userId* @return*/
@GetMapping("/users/{userId}")
public ResponseEntity findUserById(@PathVariable("userId") Long userId) {UserInfo userInfo = managerService.findUserById(userId);return ResponseEntity.ok(userInfo);
}
ManagerService
/*** 根据用户ID查询用户详情** @param userId* @return*/
public UserInfo findUserById(Long userId) {return userInfoApi.findById(userId);
}

3.4 查看视频列表

tanhua-admin

tanhua-admin模块ManageControllerManagerService添加方法

ManageController
    /*** 查询指定用户发布的所有视频列表*/@GetMapping("/videos")public ResponseEntity videos(@RequestParam(defaultValue = "1") Integer page,@RequestParam(defaultValue = "10") Integer pagesize,Long uid ) {PageResult result = managerService.findAllVideos(page,pagesize,uid);return ResponseEntity.ok(result);}
ManagerService
//查询指定用户发布的所有视频列表
public PageResult findAllVideos(Integer page, Integer pagesize, Long uid) {return videoApi.findByUserId(page, pagesize, uid);
}

tanhua-dubbo-interface

tanhua-dubbo-interface中的VideoApi中定义查询指定用户发布的视频列表方法

/*** 查询指定用户发布的视频列表** @param page* @param pagesize* @param uid* @return*/
PageResult findByUserId(Integer page, Integer pagesize, Long uid);

tanhua-dubbo-mongo

tanhua-dubbo-mongo中的VideoApiImpl中实现查询指定用户发布的视频列表方法

@Override
public PageResult findByUserId(Integer page, Integer pagesize, Long userId) {Query query = Query.query(Criteria.where("userId").in(userId));long count = mongoTemplate.count(query, Video.class);query.limit(pagesize).skip((page -1) * pagesize).with(Sort.by(Sort.Order.desc("created")));List<Video> list = mongoTemplate.find(query, Video.class);return new PageResult(page,pagesize,count,list);
}

3.5 查看动态列表

tanhua-admin

tanhua-admin模块ManageControllerManagerService添加方法

ManageController
//查询动态
@GetMapping("/messages")
public ResponseEntity messages(@RequestParam(defaultValue = "1") Integer page,@RequestParam(defaultValue = "10") Integer pagesize,Long uid,Integer state) {PageResult result = managerService.findAllMovements(page,pagesize,uid,state);return ResponseEntity.ok(result);
}
ManagerService
//查询动态
public PageResult findAllMovements(Integer page, Integer pagesize, Long uid, Integer state) {//1、调用API查询数据 :Movment对象PageResult result = movementApi.findByUserId(uid,state,page,pagesize);//2、解析PageResult,获取Movment对象列表List<Movement> items = (List<Movement>) result.getItems();//3、一个Movment对象转化为一个Voif(CollUtil.isEmpty(items)) {return new PageResult();}List<Long> userIds = CollUtil.getFieldValues(items, "userId", Long.class);Map<Long, UserInfo> map = userInfoApi.findByIds(userIds, null);List<MovementsVo> vos = new ArrayList<>();for (Movement movement : items) {UserInfo userInfo = map.get(movement.getUserId());if(userInfo != null) {MovementsVo vo = MovementsVo.init(userInfo, movement);vos.add(vo);}}//4、构造返回值result.setItems(vos);return result;
}

tanhua-dubbo-interface

tanhua-dubbo-interface中的MovementApi中定义根据用户ID分页查询用户发布的动态列表方法

/*** 根据用户ID分页查询用户发布的动态列表*/
PageResult findByUserId(Long uid, Integer state, Integer page, Integer pagesize);

tanhua-dubbo-mongo

tanhua-dubbo-mongo中的MovementApi中实现根据用户ID分页查询用户发布的动态列表方法

@Override
public PageResult findByUserId(Long uid, Integer state, Integer page, Integer pagesize) {Query query = new Query();if(uid != null) {query.addCriteria(Criteria.where("userId").is(uid));}if(state != null) {query.addCriteria(Criteria.where("state").is(state));}//查询总数long count = mongoTemplate.count(query, Movement.class);//设置分页参数query.with(Sort.by(Sort.Order.desc("created"))).limit(pagesize).skip((page -1) * pagesize);List<Movement> list = mongoTemplate.find(query, Movement.class);return new PageResult(page,pagesize,count,list);
}

探花交友_第10章_搭建后台系统(新版)相关推荐

  1. 探花交友_第10章_实现推荐功能

    探花交友_第10章_实现推荐功能 文章目录 探花交友_第10章_实现推荐功能 1.了解推荐系统 1.1.什么是推荐系统? 1.2.电商是推荐系统的先行者 1.3.推荐系统业务流程 1.4.协同过滤推荐 ...

  2. 明解C语言入门篇_第10章_指针

    前言 本文为业余学习<明解C语言入门篇>的记录,包含代码清单和练习题. 开始学习时间:2022年8月21日 +++++++++++++++++++++++++++++++ 第1章 初识C语 ...

  3. Linux系统配置及服务管理_第10章_计划任务日志管理

    一.计划任务 简介: 作用:计划任务主要是做一些周期性的任务,目前最主要的用途是定期备份数据. 分类: 一次性调度执行 at 循环调度执行 cron 1.一次性调度执行 at (1)安装 yum -y ...

  4. linux crontab 每5分钟执行一次_Linux系统配置及服务管理_第10章_计划任务

    一·简介 作用: 计划任务主要是做一些周期性的任务, 目前最主要的用途是定期备份数据. 分类 一次性调度执行 at Schedule one-time tasks with at. 循环调度执行 cr ...

  5. 链表_第10章_基本数据结构_算法导论

    双向链表(double linked list)中每个元素都是一个对象,每个对象有一个关键字key与两个指针:next and prev.next指向链表的后一个元素,prev指向前驱元素. 单链接的 ...

  6. 探花交友_第2章_环境搭建(新版)

    探花交友_第2章_环境搭建(新版) 文章目录 探花交友_第2章_环境搭建(新版) 课程介绍 <探花交友> 1.项目介绍 1.1.项目背景 1.2.市场分析 1.3.目标用户群体 1.4.使 ...

  7. 探花交友_第9章_小视频方案(新版)

    探花交友_第9章_小视频方案(新版) 文章目录 探花交友_第9章_小视频方案(新版) 1. 我的访客 1.1 需求分析 1.1.1 功能说明 1.1.2 数据库表 1.2 记录访客数据 tanhua- ...

  8. 探花交友_第6章_圈子互动(新版)

    探花交友_第6章_圈子互动(新版) 文章目录 探花交友_第6章_圈子互动(新版) 课程说明 1. 动态查询 1.1 查询好友动态 1.1.1 接口文档 1.1.2 代码步骤 1.1.3 代码实现 ta ...

  9. 探花交友_第5章_圈子、小视频功能实现

    探花交友_第5章_圈子.小视频功能实现 文章目录 探花交友_第5章_圈子.小视频功能实现 1.圈子点赞实现分析 2.点赞 2.1.定义枚举 2.2.dubbo服务 2.2.1.定义接口 2.2.2.编 ...

最新文章

  1. 16条很有用的Chrome浏览器命令
  2. 机器学习数学基础:常见分布与假设检验
  3. 计算机主机组装的过程,电脑主机组装需要怎样的操作流程简单至极?
  4. python里面的pip是什么意思_Python-pip和conda有什么区别?
  5. mysql修改密码1820_mysql5.7初始化密码报错ERROR1820(HY000):YoumustresetyourpasswordusingALTERUSERstateme...
  6. java列表框_Java图形用户界面之列表框
  7. [计算机网络] - DNS基础介绍
  8. 20200316:H指数(leetcode274)
  9. praat 语音识别教程
  10. MTK FM收音机修改门限减少杂台
  11. CTF-misc练习(https://buuoj.cn)之第二页
  12. 第七章·【第一次上岗:核桃编程】
  13. 应用层协议@传输层协议
  14. <XII>无人值守安装脚本
  15. 点评美国名校的(EE)和(CS)
  16. 云栖大会首设“科技脱贫”专场 ,20张会场门票等你来拿!
  17. 2013年国外十大最受欢迎搜索引擎网站
  18. 工程师注意了,你PCB板就是这样被抄的!
  19. 知网导出引用文件,插入到Endnote管理文献
  20. matlab 邻近度 离群点_MATLAB到底有多厉害

热门文章

  1. python安装虚拟环境没有activate_python安装虚拟环境
  2. 家具行业销售人员销售提成管理系统
  3. Windows复制文件提示指定的文件名无效或太长
  4. 2022-2027年中国智能电网建设光通信器件行业市场调研及未来发展趋势预测报告
  5. 国内外主要射频器件厂商介绍
  6. 一名大学毕业生的反思
  7. P5266 【深基17.例6】学籍管理
  8. python时间时间换算 精确到毫秒
  9. ELLIOTT SMITH~BetweenTheBare
  10. 美团点评2020校招笔试练习