【苍穹外卖】Day2 手把手敲完细节

news2024/9/24 3:18:42

目录

1. 新增员工

1.1 需求分析和设计

1.2 代码开发

①定义DTO类:(在sky-pojo里)

②EmployeeController中创建新增员工方法save()

③EmployeeService里声明save方法(alt+enter)

④EmployeeServiceImpl中实现save方法

⑤在EmployeeMapper中声明insert方法,插入数据库

1.3 功能测试

1.4 代码完善

1.5 代码提交

1.6 遇到的问题

2. 员工的分页查询

2.1 需求分析和设计

2.2 代码开发

①定义DTO类

②EmployeeController中创建员工分页查询方法page()

③EmployeeService里声明pageQuery方法

④ EmployeeServiceImpl中实现pageQuery方法

⑤在EmployeeMapper中声明pageQuery方法,插入数据库

2.3 功能测试

2.4 代码完善

2.5 代码提交

3. 启用禁用员工账号

3.1 需求分析和设计​编辑

3.2 代码开发

3.3 功能测试

 4. 编辑员工

4.1 需求分析和设计

 4.2 代码开发

 4.3 功能测试-成功

5. 导入分类模块功能

5.1 需求分析和设计

5.2 代码导入

5.3 功能测试


1. 新增员工

步骤:需求分析和设计(产品原型→接口设计→数据库设计)→代码开发

1.1 需求分析和设计

产品原型:

当填写完表单信息, 点击"保存"按钮后, 会提交该表单的数据到服务端, 在服务端中需要接受数据, 然后将数据保存至数据库中。

请求方式:post,由于需要提交员工信息,post可以携带json数据

请求参数:json数据

返回数据:响应码,数据,携带错误信息等..

接口设计:

 其实就是把页面中录入的员工数据打包成json格式插入emplyee表。

数据库设计(emplyee表)

红框中就是页面输入的数据 

1.2 代码开发

当前端提交的数据和实体类中对应的属性差别比较大时,建议使用DTO来封装数据。

①定义DTO类:(在sky-pojo里)
 @Data
public class EmployeeDTO implements Serializable {
 
    private Long id;
 
    private String username;
 
    private String name;
 
    private String phone;
 
    private String sex;
 
    private String idNumber;
 
}
EmployeeController中创建新增员工方法save()

Springboot是面向注解开发,所以注意添加如下注解

EmployeeService里声明save方法(alt+enter)

/**后面直接回车补全注释

.var快捷创建一个对象

/**
     * 新增员工
     * @param employeeDTO
     */
    void save(EmployeeDTO employeeDTO);
④EmployeeServiceImpl中实现save方法

使用了对象属性拷贝的方式进行了强制对象转换。

具体来说,这里使用了Spring框架中的BeanUtils类的静态方法copyProperties来将EmployeeDTO对象的属性值复制到Employee对象中。这种方式可以视作一种强制对象转换,因为它将两个不同类的对象之间的属性进行了映射和复制,从而实现了数据的传递和转换。

    public void save(EmployeeDTO employeeDTO) {

        Employee employee = new Employee();

        //对象属性拷贝,除了拷贝的属性相同,其他的属性都要自己设置
        BeanUtils.copyProperties(employeeDTO, employee);

        //设置账号的状态,默认正常状态 1表示正常 0表示锁定(放在常量类里方便维护可复用)
        employee.setStatus(StatusConstant.ENABLE);

        //设置密码,默认密码123456(md5加密后再存储)
        employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));

        //设置当前记录的创建时间和修改时间
        employee.setCreateTime(LocalDateTime.now());
        employee.setUpdateTime(LocalDateTime.now());

        //设置当前记录创建人id和修改人id
        //TODO 后期需要修改为当前登录用户的id
        employee.setCreateUser(10L);//目前写个假数据,后期修改
        employee.setUpdateUser(10L);

        employeeMapper.insert(employee);//后续步骤定义
    }
⑤在EmployeeMapper中声明insert方法,插入数据库
/**
     * 插入员工数据
     * @param employee
     */
    @Insert("insert into employee (name, username, password, phone, sex, id_number, create_time, update_time, create_user, update_user,status) " +
            "values " +
            "(#{name},#{username},#{password},#{phone},#{sex},#{idNumber},#{createTime},#{updateTime},#{createUser},#{updateUser},#{status})")
    void insert(Employee employee);

表的字段和属性是一一对应,表的属性采用驼峰命名法(在server的配置文件application.yml中)

mybatis:
  #mapper配置文件
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.sky.entity
  configuration:
    #开启驼峰命名
    map-underscore-to-camel-case: true

1.3 功能测试

两种方法:接口文档(主要)、前后端联调(需要前端开发好)

我们上期讲到,接口文档是由Swagger规范生成,由注解来修饰具有更好可读性的文档。

首先开启启动类SkyAppication.java

然后打开localhost:8081/doc.html——接口文档,开始调试,返回401

原来是存在jwt令牌校验的拦截器

所以我们先到登录页面获取令牌

 添加为全局参数

然后发送,这个时候遇到了一个500问题 ,反复确定insert SQL语句没有错误后,修改发送请求与参考视频里的一致,重新调试,成功添加

前后端联调:登录一直在加载,最终报了一个错(504),怀疑是因为连接着接口文档或者没有往下运行到登录

所以加载不出来,重新debug,成功登陆界面,添加数据成功!

1.4 代码完善

1、要捕获username不唯一的异常

 

debug停在获取jwt令牌的一行,原因是2小时以后原来的token失效,重新获取

在server的handler文件中添加exceptionhandler:

    @ExceptionHandler
    public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
        //Duplicate entry 'zhangsan' for key 'employee.idx_username'
        //我们希望当重复时,提示xx重复
        String message = ex.getMessage();
        if(message.contains("Duplicate entry")){
            String[] sp = message.split(" ");
            String username = sp[2];
            //String msg = username + "已存在";
            String msg = username + MessageConstant.ALREADY_EXISTS;
            return Result.error(msg);
        }else {
            return Result.error(MessageConstant.UNKNOWN_ERROR);
        }
    }

修改之后,异常被捕获,作出响应 

2、创建员工save方法里的创建人和修改人是固定写死的,即

        //TODO 后期需要修改为当前登录用户的id
        employee.setCreateUser(10L);//目前写个假数据,后期修改
        employee.setUpdateUser(10L);

我们需要的user_id就在拦截的token里面,需要进行解析

        //1、从请求头中获取令牌
        String token = request.getHeader(jwtProperties.getAdminTokenName());

        //2、校验令牌
        try {
            log.info("jwt校验:{}", token);
            Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
            Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());
            log.info("当前员工id:", empId);
            //3、通过,放行
            return true;
        } catch (Exception ex) {
            //4、不通过,响应401状态码
            response.setStatus(401);
            return false;
        }

问题是解析得到了empId后,我们要如何传递给service的save方法 

● ThreadLocal

并不是一个线程(Thread),他是一个线程的局部变量

为每个线程提供单独一份存储空间,起到线程隔离的作用,只有线程内才能获取对应的值

那么我们客户端发出的每次请求是否对应一个线程呢?在不同的地方添加语句

System.out.println("当前线程的id:" + Thread.currentThread().getId());

可以看到都对应线程:44 

重新请求对应线程46,说明:一次请求确实对应一个线程。所以可以把id存入ThreadLocal,再在server里取出来.

ThreadLocal常用方法:set(T value), get(), remove()

我们使用ThreadLocal时往往会进行一个简单的封装,包装成一个工具类common-BaseContext

public class BaseContext {

    public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();

    public static void setCurrentId(Long id) {
        threadLocal.set(id);
    }

    public static Long getCurrentId() {
        return threadLocal.get();
    }

    public static void removeCurrentId() {
        threadLocal.remove();
    }

}

添加两句,interceptor(拦截器)里

BaseContext.setCurrentId(empId);

serviceimpl实现类里

employee.setCreateUser(BaseContext.getCurrentId());
        employee.setUpdateUser(BaseContext.getCurrentId());

debug时可以右键-evalueate expression得到里面的值为empId

1.5 代码提交

commit + push即可

1.6 遇到的问题

1、没有自动补全SQL语句功能

net start MYSQL80后可以测试数据库连接

这篇文章非常有用:IDEA设置MYSQL语句自动提示补全

最后发现是因为安装的社区版本很多功能都没有,所以重新安装Utimate版本

2、Cannot resolve symbol 'SQLIntegrityConstraintViolationException'

import java.sql.SQLIntegrityConstraintViolationException;(导入这个包)


2. 员工的分页查询

2.1 需求分析和设计

分析产品原型——

请求方式:get方式请求,

查询参数:页码,每页记录数,员工姓名(不同于增加员工查询参数是json格式,这里使用Query)

后端相应数据:响应码,错误信息,总的数据数total,和这一页展示的员工数据集合records

接口设计:

2.2 代码开发

根据接口设置对应的DTO

后面所有的分页查询都封装成PageResult对象,再+code+msg封装成统一的result

具体来说,Result<Object>接口传入PageResult对象

①定义DTO类
@Data
public class EmployeePageQueryDTO implements Serializable {

    //员工姓名
    private String name;

    //页码
    private int page;

    //每页显示记录数
    private int pageSize;

}
EmployeeController中创建员工分页查询方法page()

路径等于@RequestMapping+下面的路径

@RequestMapping("/admin/employee")

@PostMapping("/login")
@PostMapping("/logout")
@GetMapping("/page")
    @GetMapping("/page")
    @ApiOperation("员工分页查询")
    public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO){
        Log.info("员工分页查询,参数为:{}", employeePageQueryDTO);
        PageResult pageResult = employeeService.pageQuery(employeePageQueryDTO);    //service存储分页查询的方法
        return Result.success(pageResult);
    }
EmployeeService里声明pageQuery方法
    /**
     * 分页查询方法
     * @param employeePageQueryDTO
     * @return
     */

    PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO);
④ EmployeeServiceImpl中实现pageQuery方法

一般来说通过从数据库中导入分页数据

select * from employee limit 0,10(limit关键字查询第0-10条)

mybatis框架提供插件pagehelper,简化分页操作 (在pom.xml中增加配置)

        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
        </dependency>

 page和pageSize已知,直接用pagehelper

    /**
     * 分页查询
     * @param employeePageQueryDTO
     * @return
     */
    public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
        //select * from employee limit 0,10(limit关键字查询第0-10条)
        //实现原理:将page封装后存入threadlocal,在分页查询前取出来,动态拼接实现SQL
        PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());
        Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);   //返回pagehelper格式的对象

        long total = page.getTotal();
        List<Employee> records = page.getResult();

        return new PageResult(total, records);
    }
⑤在EmployeeMapper中声明pageQuery方法,插入数据库

由于是动态SQL,要使用动态标签,注解不太方便,

所以我们将SQL写入映射配置文件,在server-resources-mapper-EmployeeMapper.xml里

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sky.mapper.EmployeeMapper">
</mapper>

ctrl+点击EmployeeMapper可以进入EmployeeMapper.java文件说明映射已经建立好了

同时为了确保xml文件被扫描到,在application.xml中增加配置

mybatis:
  #mapper配置文件
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.sky.entity
  configuration:
    #开启驼峰命名
    map-underscore-to-camel-case: true

下载mybatisx插件:

红色头绳的表示映射配置文件,蓝色头绳的表示mapper接口。在mapper接口点击红色头绳的小鸟图标会自动跳转到对应的映射配置文件,在映射配置文件中点击蓝色头绳的小鸟图标会自动跳转到对应的mapper接口。也可以在mapper接口中定义方法,自动生成映射配置文件中的 statement 

alt+enter-select自动生成配置文件,在自动生成的基础上编写动态SQL

<mapper namespace="com.sky.mapper.EmployeeMapper">
    <select id="pageQuery" resultType="com.sky.entity.Employee">
        select * from  employee
        <where>
            <if test="name != null and name !=’‘">
                and name like concat('%',#{name},'%')   //模糊搜索+字符串拼接
            </if>
        </where>
        order by create_time desc   //降序排序
    </select>
</mapper>

2.3 功能测试

①接口文档:

返回401,说明token又过期了,在application.yml中

返回两条json(报了500看了一下是因为xml文件里加中文注释)

 ②前后端联调

功能一:分页查询,前端已经显示了

功能二:模糊查询调用name like语句

2.4 代码完善

刚刚在测试时已经发现了问题,红框里的最后操作时间不是规范格式

第一种方式需要一个一个地处理,第二种方式则可以统一处理

通过server-config-WebMvcConfiguration里重写Spring框架里自带的一个方法extendHandlerExceptionResolvers,扩展消息转换器((对后端返回给前端的数据做统一处理)

通过实现WebMvcConfigurer接口,你可以按需选择性地覆盖接口中的方法,只实现你需要的配置,而不需要处理所有配置。

    /**
     * 扩展Spring MVC框架的消息转换器
     * @param exceptionResolvers
     */
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters){
        log.info("扩展消息转换器...");
        //创建一个消息转换器对象
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        //需要为消息转换器设置一个对象转换器,将java对象序列化为json数据
        converter.setObjectMapper(new JacksonObjectMapper());
        //将自己的消息转换器converter加入容器converters里,并优先使用
        converters.add(0, converter);
    }

2.5 代码提交


3. 启用禁用员工账号

3.1 需求分析和设计

POST请求是因为启用禁用 本质是修改

一般来说,状态用路径参数传,id用请求参数传

3.2 代码开发

EmployeeController中创建方法

    /**
     * 启用禁用员工账号
     * @param status
     * @param id
     * @return
     */
    @PostMapping("/status/{status}")
    @ApiOperation("启用禁用员工账号")
    public Result startOrStop(@PathVariable Integer status, Long id){
        log.info("启用禁用员工账号,参数为:{},{}", status, id);
        employeeService.startOrStop(status, id);
        return Result.success();
    }

 EmployeeService里声明

    /**
     * 启用禁用员工账号
     * @param status
     * @param id
     */
    void startOrStop(Integer status, Long id);

EmployeeServiceImpl中实现

    public void startOrStop(Integer status, Long id) {
        //根据id改status,动态更新所以传实体类比较合适
        //update employee set status =? where id = ?
        Employee employee = new Employee();
        employee.setStatus(status);
        employee.setId(id);
        employeeMapper.update(employee);
    }

也可以通过@Builder构建器获得一个构件器对象

    public void startOrStop(Integer status, Long id) {
        //根据id改status,动态更新所以传实体类比较合适
        //update employee set status =? where id = ?
        Employee employee = Employee.builder()
                .status(status)
                .id(id)
                .build();
        employeeMapper.update(employee);
    }

在EmployeeMapper中

    /**
     * 根据主键动态修改属性
     * @param employee
     */
    void update(Employee employee);

既然是动态的,SQL语句也要放在映射配置文件里写

    <update id="update">
        update employee
        <set>
            <if test="name != null">name = #{name},</if>
            <if test="username != null">username = #{username},</if>
            <if test="password != null">password = #{password},</if>
            <if test="phone != null">phone = #{phone},</if>
            <if test="sex != null">sex = #{sex},</if>
            <if test="idNumber != null">id_Number = #{idNumber},</if>
            <if test="updateTime != null">update_Time = #{updateTime},</if>
            <if test="updateUser != null">update_User = #{updateUser},</if>
            <if test="status != null">status = #{status},</if>
        </set>
        where id = #{id}
    </update>

3.3 功能测试

修改成功!

前后端联调也成功! 

最后记得提交!


 4. 编辑员工

4.1 需求分析和设计

点击修改,就会跳转修改界面

 接口设计:

涉及到两个接口:一个是根据id查询员工信息(GET),一个是修改员工信息(PUT)

还有提交用POST,删除用DELETE

 4.2 代码开发

①根据id查询员工信息比较简单,这里只放具体实现了

    /**
     * 根据id查询员工信息
     * @param id
     * @return
     */
    @Select("select * from employee where id = #{id}")
    Employee getById(Long id);

前后端联调成功,并且可以从开发者工具-网络看到响应格式

② 编辑员工信息

利用mapper之前定义好的update语句更新员工信息

    /**
     * 编辑员工信息
     * @param employeeDTO
     */
    public void update(EmployeeDTO employeeDTO) {
        Employee employee = new Employee();
        BeanUtils.copyProperties(employeeDTO, employee);

        employee.setUpdateTime(LocalDateTime.now());
        employee.setUpdateUser(BaseContext.getCurrentId());

        employeeMapper.update(employee);
    }

 4.3 功能测试-成功

5. 导入分类模块功能

5.1 需求分析和设计

 设计包括6个接口,和员工管理类似

5.2 代码导入

mapper-xml-service-imple-controller倒序导入,这样不会报错

maven编译一遍无误

5.3 功能测试


两天终于敲完了 Day2,进度有点慢啊T^T

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

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

相关文章

喜讯丨美格智能通过国际EcoVadis平台认证企业社会责任并荣获承诺奖章,彰显可持续发展实力

作为全球领先的无线通信模组及解决方案提供商&#xff0c;美格智能在社会责任领域再创新高。近日&#xff0c;美格智能凭借在企业社会责任和可持续性采购发展方面的卓越表现&#xff0c;通过国际在线权威评价机构EcoVadis对公司环境、劳工与人权、商业道德、可持续采购等方面审…

线性回归笔记

https://blog.51cto.com/u_16213589/7682076 残差图 多元回归-最小二乘法-残差分析笔记 一.多元线性回归模型的假设 我们需要进行以下六个假设&#xff0c;这些假设是经典的多元线性回归模型有效的前提&#xff1a; 1、因变量Y和自变量X1&#xff0c;X2&#xff0c;…&#…

文献阅读:基于测序的空间转录组方法的系统比较

文献介绍 文献题目&#xff1a; Systematic comparison of sequencing-based spatial transcriptomic methods 研究团队&#xff1a; 田鲁亦&#xff08;广州实验室&#xff09;、刘晓东&#xff08;西湖大学&#xff09; 发表时间&#xff1a; 2024-07-04 发表期刊&#xff…

Python自动化测试系列[v1.0.0][自动化测试报告]

BeautifulReport测试报告 获取BeautifulReport模块 BeautifulReport 源码Clone地址为 BeautifulReport &#xff0c;其中BeautifulReport.py和其template是我们需要的 BeautifulReport 如下代码是BeautifulReport.py的源码&#xff0c;其中几个注释的地方需要注意&#xff…

C编程使用clock函数实现计算一段代码的执行时间:毫秒单位

一、函数原型 在Linux系统中&#xff0c;clock()函数是一个非常重要且常用的函数&#xff0c;它主要用于测量程序运行的CPU时间。这个函数是C/C语言中的一个标准函数&#xff0c;其原型定义在<time.h>头文件中。以下是对clock()函数的详细解析&#xff1a; #include <…

Khoj 一个处在免费领域应用最佳的AI对话工具

文章目录 1. 了解 khoj1.1 文档1.2 价格1.3 代理人 2. 特点3. 应用3.1 全文搜索3.1.1 ChatGPT没有3.1.2 Khoj 3.2 APP 对话3.2.1 khoj & whatsApp3.2.2 ChatGPT 3.3 摘要总结3.3.1 ChatGPT3.3.2 Khoj 3.4 图片分析3.4.1 chatgpt3.4.2 khoj 3.5 格式转换3.5.1 ChatGPT3.5.2 …

基于STM主题模型的主题提取分析-完整代码数据

直接看结果: 代码: import re from collections import defaultdict import random import matplotlib.pyplot as plt import numpy as npimport pandas as pd import numpy as np import re from sklearn.feature_extraction.text import CountVectorizer from nltk.corpus…

c++ 多边形 xyz 数据 获取 中心点方法

有需求需要对。多边形 获取中心点方法&#xff0c;绝大多数都是 puthon和java版本。立体几何学中的知识。 封装函数 point ##########::getCenterOfGravity(std::vector<point> polygon) {if (polygon.size() < 2)return point();auto Area [](point p0, point p1, p…

聚类分析方法(二)

目录 三、层次聚类方法&#xff08;一&#xff09;层次聚类策略&#xff08;二&#xff09;AGNES算法&#xff08;三&#xff09;DIANA算法 四、密度聚类方法&#xff08;一&#xff09;基本概念&#xff08;二&#xff09;算法描述&#xff08;三&#xff09;计算实例&#xf…

flowable7.0.1常见问题解答

说明&#xff1a;本文采用Q-A的形式&#xff0c;持续更新... Q&#xff1a;flowable中任务审批时在taskCompleted监听中获取当前审批提交的表单内容&#xff1f; A&#xff1a;taskService.setLocalVirables(Map<String,Object> variables)&#xff1b;也可以通过添加缓…

MVC 可以把通用命名空间放在配置文件

这种方式的引入,是将命名空间引入到所有视图中了,不需要在使用using单独引用了。

【大数据】什么是数据湖?一文揭示数据湖的本质

很多人跟我一样&#xff0c;对于数据湖充满好奇&#xff0c;也许还读了不少数据湖文章&#xff0c;但无论别人怎么说&#xff0c;你还是会觉得难以把握数据湖的本质。 有些人会望文生义说&#xff0c;数据湖嘛&#xff0c;就是什么东西都可以往里面扔&#xff0c;特别是对非结构…

奇瑞新能源车型EQ2在驾校领域的CAN总线数据应用

在当今这个快速发展的汽车时代&#xff0c;科技的进步不仅推动了汽车性能的提升&#xff0c;也为驾驶培训领域带来了革命性的变化。其中&#xff0c;奇瑞EQ2作为一款电动汽车&#xff0c;其在驾校领域的应用尤其值得关注&#xff0c;特别是其采用的CAN总线技术。CAN总线&#x…

【面向就业的Linux的基础】从入门到熟练,探索Linux的秘密(十三)-常用的命令

上述是一些系统命令的基本练习&#xff0c;可以当做日常笔记学习收藏一下&#xff01;&#xff01;&#xff01; 目录 前言 一、文件权限 二、文件检索 三、查看文件内容 四、用户相关 五、工具 六、安装软件 七、作业​​​​​​​ 总结 前言 上述是一些系统命令的…

MATLAB实现-基于CNN-LSTM卷积神经网络结合长短期记忆神经网络数据分类预测(多输入多分类)

MATLAB实现-基于CNN-LSTM卷积神经网络结合长短期记忆神经网络数据分类预测&#xff08;多输入多分类&#xff09; 基于CNN-LSTM卷积神经网络结合长短期记忆神经网络数据分类预测&#xff08;多输入多分类&#xff09; 1.数据均为Excel数据&#xff0c;直接替换数据就可以运行…

互助学习平台小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;学生管理&#xff0c;课程信息管理&#xff0c;课程分类管理&#xff0c;课程评价管理&#xff0c;学习计划管理&#xff0c;留言板管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;课程信息…

2-25 基于matlab的语音信号降噪处理算法

基于matlab的语音信号降噪处理算法&#xff0c;采用谱减法&#xff0c;可以对强噪声背景下的语音信号进行去噪。输入原始信号及加噪信号&#xff0c;对加噪信号进行降噪&#xff0c;并提高信噪比。程序已调通&#xff0c;可直接运行。 2-25 语音信号降噪处理算法 谱减法 - 小红…

商业地产规划vr实景还原系统更直观生动

在今日的建筑行业论坛中&#xff0c;众多业界专家深入探讨了建筑设计与展示的未来趋势。我们作为VR建筑展示领域的领军企业&#xff0c;始终秉持着对城市规划与发展的深度思考。多年来&#xff0c;我们积极参与并助力了无数城市片区的规划与建设。 回首2015年&#xff0c;我们与…

假期笔记1:anaconda的安装与pycharm中的引用

1.下载安装 Download Anaconda Distribution | Anaconda 2.填个邮箱 11111.. 3.下载。有点需要时间 4.安装&#xff0c;双击&#xff0c;根据实际进行&#xff0c;记清安装路径 5。环境设置 conda -V 6.创建环境 conda create --name env_name conda create --na…

python基础语法笔记(有C语言基础之后)

input()用于输入&#xff0c;其有返回值&#xff08;即用户输入的值&#xff09;&#xff0c;默认返回字符串。括号里可放提示语句 一行代码若想分为多行来写&#xff0c;需要在每一行的末尾加上“\” 单个“/”表示数学中的除法&#xff0c;不会取整。“//”才会向下取整。 …