SSM整合——Springboot

news2024/12/22 18:58:25

1.0 概述

1.1 持久层:

DAO层(mapper)

  • DAO层:DAO层主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此

    • DAO层的设计首先是设计DAO的接口,

    • 然后在spring-mapper.xml的配置文件中定义此接口的实现类,

    • 然后就可在模块中调用此接口来进行数据业务的处理,而不用关心此接口的具体实现类是哪个类,显得结构非常清晰,

    • DAO层的数据源配置,以及有关数据库连接的参数都在spring-mapper的配置文件中进行配置。

1.2 业务层:

Service层

  • Service层:Service层主要负责业务模块的逻辑应用设计。

    • 首先设计接口,再设计其实现的类

    • 接着再在Spring的配置文件中配置其实现的关联。这样我们就可以在应用中调用Service接口来进行业务处理

    • Service层的业务实现,具体要调用到已定义的DAO层的接口

    • 数据库的事务配置在service.xml中配置

    • 封装Service层的业务逻辑有利于通用的业务逻辑的独立性和重复利用性,程序显得非常简洁。

1.3 表现层:

Controller层(Handler层)

  • Controller层:Controller层负责具体的业务模块流程的控制,

    • 在此层里面要调用Service层的接口来控制业务流程,

    • 控制的配置也同样是在springmvc.xml的配置文件里面进行,针对具体的业务流程,会有不同的控制器,

    • 我们具体的设计过程中可以将流程进行抽象归纳,设计出可以重复利用的子单元流程模块,

      这样不仅使程序结构变得清晰,也大大减少了代码量

1.4 View层
  • View层 此层与控制层结合比较紧密,需要二者结合起来协同工发。View层主要负责前台jsp页面的表示.

1.5 各层联系
  • DAO层,Service层这两个层次都可以单独开发,互相的耦合度很低,完全可以独立进行,这样的一种模式在开发大项目的过程中尤其有优势

  • Controller,View层因为耦合度比较高,因而要结合在一起开发,但是也可以看作一个整体独立于前两个层进行开发。这样,在层与层之前我们只需要知道接口的定义,调用接口即可完成所需要的逻辑单元应用,一切显得非常清晰简单。

  • Service逻辑层设计

    • Service层是建立在DAO层之上的,建立了DAO层后才可以建立Service层,而Service层又是在Controller层之下的,因而Service层应该既调用DAO层的接口,又要提供接口给Controller层的类来进行调用,它刚好处于一个中间层的位置。每个模型都有一个Service接口,每个接口分别封装各自的业务处理方法。

2.0 SSM整合

2.1 创建SpringBoot项目

image-20230309210725476

2.2 引入依赖
<properties>
        <java.version>11</java.version>
        <mybatis.version>2.2.2</mybatis.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis.version}</version>
        </dependency>
​
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
注意:引入 spring-boot-devtools 依赖后,每次我们只需要重新编译源代码即可,不要需要重启springboot项目
2.3 工程搭建
#启动端口
server.port=8088
#数据源
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql:///220706a
spring.datasource.username=root
spring.datasource.password=123456
# 日志登记
logging.level.com.whitecamellia.mybatis_demo = debug
#xml配置
mybatis.mapper-locations=classpath:mapper/*Mapper.xml
#驼峰映射
mybatis.configuration.map-underscore-to-camel-case=true
#配置别名
mybatis.type-aliases-package = com.whitecamellia.mybatis_demo.entity 
#主键返回
mybatis.configuration.use-generated-keys=true
# 延迟加载
mybatis.configuration.lazy-loading-enabled=true
#二级缓存
mybatis.configuration.cache-enabled=true
2.4 封装Result工具类
package com.whitecamellia.ssm_test.util;
import lombok.Getter;
@Getter
public class Result {
    private int code;
    private String message;
    private Object data;
​
    private Result() {
    }
​
    public static Result ok () {
        Result result = new Result();
        result.code = 200;
        result.message = "success";
        return result;
    }
​
    public static Result ok (Object data) {
        Result result = new Result();
        result.code = 200;
        result.message = "success";
        result.data = data;
        return  result;
    }
​
    public static Result error (int code,String message) {
        Result result = new Result();
        result.code = code;
        result.message = message;
        return  result;
    }
}
​
​
// 测试
@RestController
public class PersonController {
    @Autowired
    private PersonService personService;
​
    @GetMapping("/findList")
    public Result findList () {
        List<Person> list = personService.findList();
        return  list.size()!= 0 ?
                Result.ok(list) :
                Result.error(201,"无数据");
    }
}
2.5 优化工具类
@Getter
public class Result<T> {
    private int code;
    private String message;
    private T data;
​
    private static final int DEFAULT_SUCCESS_CODE = 200;
    private static final String DEFAULT_SUCCESS_MESSAGE = "SUCCESS";
​
    private Result() {
    }
​
    public static Result<Void> ok () {
        Result<Void> result = new Result<>();
        result.code = DEFAULT_SUCCESS_CODE;
        result.message = DEFAULT_SUCCESS_MESSAGE;
        return result;
    }
​
    public static  T> Result<T> ok (T data) {
        Result<T> result = new Result<>();
        result.code = DEFAULT_SUCCESS_CODE;
        result.message = DEFAULT_SUCCESS_MESSAGE;
        result.data = data;
        return result;
    }
​
    public static Result<Void> error (int code,String message) {
        Result<Void> result = new Result<>();
        result.code = code;
        result.message = message;
        return result;
    }
​
}
2.6 测试
 @GetMapping("/findList")
    public Result<List<Person>> findList () {
        return  Result.ok(personService.findList());
    }

3.0 分页

3.1 基本使用
@RestController
public class SpAttributeController {
    @Autowired
    private SpAttributeService spAttributeService;
​
    @GetMapping("/find")
    public Result<List<SpAttribute>> findByPage() {
        return Result.ok(spAttributeService.findByPage());
    }
}
public interface SpAttributeService {
    List<SpAttribute> findByPage();
}
@Service
public class SpAttributeServiceImpl implements SpAttributeService {
​
    @Autowired
    private SpAttributeMapper spAttributeMapper;
​
    @Override
    public List<SpAttribute> findByPage() {
        return spAttributeMapper.findByPage();
    }
}
@Mapper
public interface SpAttributeMapper {
    @Select(" select * from sp_attribute")
    List<SpAttribute> findByPage();
}
@Data
public class SpAttribute {
    private Integer attrId;
    private String attrName;
    private Integer catId;
    private String attrSel;
    private String attrWrite;
    private String attrVals;
   // getter&&setter
}
3.2 导入依赖
<pagehelper-version>1.4.1</pagehelper-version>
<dependency>
     <groupId>com.github.pagehelper</groupId>
     <artifactId>pagehelper-spring-boot-starter</artifactId>
     <version>${pagehelper-version}</version>
</dependency>
3.3 分页助手
 Page<SpAttribute> page1 = PageHelper.offsetPage(pageNum, pageSize);
  Page<SpAttribute> page2 = PageHelper.startPage(pageNum, pageSize);
3.4 测试:
//  http://localhost:8088/findByPage1?pageNum=1&pageSize=10
    @GetMapping("/findByPage1")
    public Result<List<SpAttribute>> findByPage1(Integer pageNum, Integer pageSize) {
//      PageHelper.offsetPage(pageNum, pageSize);
        PageHelper.startPage(pageNum, pageSize);
        return Result.ok(spAttributeService.findByPage());
   }
3.5 封装PageData
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageData<T> {
    private List<T> data;
    private long total;
}
3.6 测试
 @GetMapping("/findByPage2")
    public Result<PageData<SpAttribute>> findByPage2(Integer pageNum, Integer pageSize) {
        Page<SpAttribute> result = PageHelper.startPage(pageNum, pageSize);
        spAttributeService.findByPage();
        PageData<SpAttribute> pageData = new PageData<>(result.getResult(), result.getTotal());
        return Result.ok(pageData);
 }
3.7 分页演示
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>table 模块快速使用</title>
    <!-- 引入 layui.css -->
    <link rel="stylesheet" href="//unpkg.com/layui@2.6.8/dist/css/layui.css">
​
    <!-- 引入 layui.js -->
    <script src="//unpkg.com/layui@2.6.8/dist/layui.js"></script>
</head>
<body>
<table id="demo" lay-filter="test"></table>
​
<script>
    layui.use('table', function () {
        var table = layui.table;
​
        //第一个实例
        table.render({
            elem: '#demo'
            , height: 312
            , url: '/findByPage3' //数据接口
            , page: true //开启分页
            , cols: [[ //表头
                {field: 'attrId', title: '主键id', width: 180, sort: true, fixed: 'left'}
                , {field: 'attrName', title: '属性名称', width: 180}
                , {field: 'catId', title: '类型id', width: 180, sort: true}
                , {field: 'attrSel', title: '动态参数', width: 180}
                , {field: 'attrWrite', title: '静态属性', width: 180}
            ]],
            parseData: function(d){
                return {
                    code: d.code,
                    msg: d.message,
                    count: d.data.total,
                    data: d.data.data,
                };
            }
        });
​
    });
</script>
</body>
</html>
 
 @GetMapping("/findByPage3")
   public Result<PageData<SpAttribute>> findByPage3(@RequestParam(name = "page")
                                                      Integer pageNum,
                                                     @RequestParam(name = "limit")
                                                      Integer pageSize) {
        Page<SpAttribute> result = PageHelper.startPage(pageNum, pageSize);
        spAttributeService.findByPage();
        PageData<SpAttribute> pageData = new PageData<>(result.getResult(), result.getTotal());
        return Result.ok(pageData);
    }
3.8 增加排序功能
 Page<SpAttribute> result = PageHelper.startPage(pageNum, pageSize, "attr_id DESC");
3.9 注意事项:
  • 在使用排序时,我们发现pagehelper采用的是字符串拼接的形式,这样会有潜在的sql注入问题,这就要求我们在排序时必须严格校验排序的参数。必须与表或者实体类字段做好对应。

前端传参  
  @GetMapping("/findByPage")
    public Result<PageData<SpAttribute>> findByPage(@RequestParam(defaultValue = "1") Integer pageNum,    
                                                    @RequestParam(defaultValue = "10") Integer pageSize) {
      pageSize = pageSize >= 50 ? 50 : pageSize;
      return ...
    }
注意事项:
  • pageNum,pageSize指定默认值

  • pageNum 可以不做限制但是pageSize必做,防止前端恶意传参

pageHelper注意事项
  • 分页插件是当调用startPage或者offsetPage之后开始拦截select语句,拦截之后,在select语句后拼接limit参数,拦截以后,分页功能关闭,再准备拦截下一次select语句。也就是说如果我们连续发了2个select语句请求只会拦截第一次操作。

  • 不要在拦截select语句与请求的select语句之间使用page的任意方法,只有select语句请求以后,page里面才有数据。

4.0 事务

事务:transaction

4.1 基本使用
public class Account {
    private Integer id;
    private String name;
    private double balance;
    //getter&&setter
}
​@RestController
public class AccountController {
    @Autowired
    private AccountService accountService;
​
    @PostMapping("/balance")
    public void update() {
        boolean update = accountService.update();
        System.out.println(update);
    }
}
​
public interface AccountService {
    boolean update();
}

在你认为可能出现问题的方法上加上注解@Transactional

​@Service
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountMapper accountMapper;
​
    @Transactional
    @Override
    public boolean update() {
        int sub = accountMapper.sub();
        int i = 1 / 0;
        int add = accountMapper.add();
        return sub == add ? true : false;
    }
}
@Mapper
public interface AccountMapper {
    int sub();
    int add();
}
<?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.whitecamellia.mapper.AccountMapper">
    <update id="add">
        UPDATE account
        set balance = balance + 500
        WHERE id = 2
    </update>
​
    <update id="sub">
        UPDATE account
        set balance = balance - 500
        WHERE id = 1
    </update>
​
</mapper>


4.2 rollbackFor
@Service
​
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountMapper accountMapper;
​
    @Transactional  //  默认 只有运行时异常  会自动回滚
    @Override
    public boolean update() throws FileNotFoundException {
        int sub = accountMapper.sub();
       // IOException 非运行时异常
        FileInputStream fileInputStream = new FileInputStream("C:\\WINDOWS\\1.txt"); 
        int add = accountMapper.add();
        return sub == add ? true : false;
    }
​
}
 
  • 程序报错!尽管我们添加了事务注解,但是我们发现数据还是可以在数据库中进行修改

  • 实际上spring框架在封装 @Transactional注解默认只会处理runtimeException,对于编译异常,默认交给用户处理。

  • 我们希望编译异常也交给spring框架来管理,具体配置如下

@Transactional(rollbackFor = RuntimeException.class)//默认
@Transactional(rollbackFor = Exception.class) // 所有 遇见运行时异常 或者 非运行时异常。都会回滚,前提是该方法内的异常抛出而非捕获
@Service
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountMapper accountMapper;
​
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean update() throws FileNotFoundException {
        int sub = accountMapper.sub();
//      int i = 1 / 0;
        FileInputStream fileInputStream = new FileInputStream("C:\\WINDOWS\\1.txt");
        int add = accountMapper.add();
        return sub == add ? true : false;
    }
​
}
4.3 事务的传播机制
  • REQUIRED (默认)

    • 支持当前事务,如果当前没有事务,则新建事务

    • 如果当前存在事务,则加入当前事务,合并成一个事务

  • REQUIRES_NEW

    • 新建事务,如果当前存在事务,则把当前事务挂起(无论当前环境是否有事物)

    • 这个方法会独立提交事务,不受调用者的事务影响,父级异常,它也是正常提交

  • NESTED

    • 如果当前存在事务,它将会成为父级事务的一个子事务,方法结束后并没有提交,只有等父事务结束才提交

    • 如果当前没有事务,则新建事务

    • 如果它异常,父级可以捕获它的异常而不进行回滚,正常提交

    • 但如果父级异常,它必然回滚,这就是和 REQUIRES_NEW 的区别

  • SUPPORTS

    • 如果当前存在事务,则加入事务

    • 如果当前不存在事务,则以非事务方式运行,这个和不写没区别

  • NOT_SUPPORTED

    • 以非事务方式运行

    • 如果当前存在事务,则把当前事务挂起

  • MANDATORY

    • 如果当前存在事务,则运行在当前事务中

    • 如果当前无事务,则抛出异常,也即父级方法必须有事务

  • NEVER

    • 以非事务方式运行,如果当前存在事务,则抛出异常,即父级方法必须无事务

一般用得比较多的是 REQUIREDREQUIRES_NEW

REQUIRES_NEW 一般用在子方法需要单独事务。

@Transactional(propagation = Propagation.REQUIRED)

代码演示:

testService

public interface TestService {
    void TestInsert ();
}

testServiceImpl

@Service
public class TestServiceImpl implements TestService {
    @Autowired
    private PersonMapper personMapper;
  
    @Transactional
    @Override
    public void TestInsert() {
        Person person = new Person();
        person.setName("测试");
        person.setAge(20);
        // int i = 1 / 0;
        personMapper.insert(person);
    }
}
 

PersonServiceImpl

@Service
public class PersonServiceImpl implements PersonService {
    @Autowired
    private PersonMapper personMapper;
​
    @Autowired
    private TestService testService;
  
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(Person person) throws FileNotFoundException {
           int insert = personMapper.insert(person);
​
        testService.TestInsert();
//        int i = 1 / 0;
//        new FileInputStream("c:/1.txt");
        return insert;
    }
}
 

@Transactional(propagation = Propagation.REQUIRES_NEW)

@Service
public class TestServiceImpl implements TestService {
    @Autowired
    private PersonMapper personMapper;
    // 默认
//  @Transactional(propagation = Propagation.REQUIRED)
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public void TestInsert() {
        Person person = new Person();
        person.setName("测试");
        person.setAge(20);
        personMapper.insert(person);
    }
}

4.4 事务的失效场景

5.0 Lombok

5.1 常用注解
@Getter
@Setter
@ToString
@EqualsAndHashCode
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
//    @Getter
    private Integer id;
//    @Setter
    private String name;
    private Integer age;
}
5.2 @Slf4j (日志框架)
编译前
@Slf4j
class Demo {
    public static void main(String[] args) {
​
    }
}
编译后
class Demo {
    private static final Logger log = LoggerFactory.getLogger(Demo.class);
​
    Demo() {
    }
​
    public static void main(String[] args) {
       // 日志输出级别:debug、info、warn、error
            log.debug();
    }
}
 
5.3 级别演示
@Slf4j
@Service
public class PersonServiceImpl implements PersonService {
    @Autowired
    private PersonMapper personMapper;
    @Override
    public List<Person> findList() {
        log.debug("开始打印数据");
        return personMapper.findList();
    }
}

注意:我们项目配置文件中配置日志的打印级别是debug,故会将所有的日志全部打印

#开发环境日志级别
logging.level.com.whitecamellia.ssm_test=debug
#生产环境日志级别
#logging.level.com.whitecamellia.ssm_test=info
#再次精简打印信息
logging.level.root=warn
5.4 调试打印
@Slf4j
@Service
public class PersonServiceImpl implements PersonService {
    @Autowired
    private PersonMapper personMapper;
    @Override
    public List<Person> findList() {
        List<Person> list = personMapper.findList();
        log.debug("开始打印{}集合数据",list);
        return  list;
    }
}
5.5 写入日志
#生产环境,将打印信息写到文件中
logging.file.name = logger.log

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

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

相关文章

【Unity学习笔记】光照简介

本节主要是简单介绍一些常见的光照组件和渲染设置。 文章目录 灯光类型平行光Directional Light点光源Point Light聚光灯Spot Light面积光 Area Light 阴影设置全局光照明光照模式直接光照与间接光照Mixed Lighting 光照探针Light Probe Group光照探针组 反射探针 灯光类型 在…

00后女孩月薪3200,3年买两套房,这个程序员变现新风口千万要把握住

00后女孩月薪3200&#xff0c;3年买两套房&#xff0c;这个程序员变现新风口千万要把握住 前几天&#xff0c;在网上看到了一份中国90后收入的调查报告&#xff1a; 报告显示&#xff1a; 90后月均收入8000元&#xff0c;三成90后零存款&#xff0c;两成90后存款达到10万以上…

鸿蒙开发之页面与组件生命周期

一、页面间的跳转 创建文件的时候记得选择创建page文件&#xff0c;这样就可以在main->resources->profile->main_pages.json中自动形成页面对应的路由了。如果创建的时候你选择了ArkTS文件&#xff0c;那么需要手动修改main_pages.json文件中&#xff0c;添加相应的…

mysql字段设计规范:使用unsigned(无符号的)存储非负值

如果一个字段存储的是数值&#xff0c;并且是非负数&#xff0c;要设置为unsigned&#xff08;无符号的&#xff09;。 例如&#xff1a; 备注&#xff1a;对于类型是 FLOAT、 DOUBLE和 DECIMAL的&#xff0c;UNSIGNED属性已经废弃了&#xff0c;可能在mysql的未来某个版本去…

​flutter 代码混淆

​flutter 代码混淆 Flutter 应用混淆&#xff1a;Flutter 应用的混淆非常简单&#xff0c;只需要在构建 release 版应用时结合使用 --obfuscate 和 --split-debug-info 这两个参数即可。–obfuscate --split-debug-info 用来指定输出调试文件的位置&#xff0c;该命令会生成一…

threejs 多屏互动效果,居然还能这么玩

threejs 多屏互动效果 看别人做了多屏互动的效果&#xff0c;觉得还挺有意思的&#xff0c;也顺便自己动手操作一下试试。 先来张效果图&#xff1a; 项目地址 参考地址 项目基于vuethreejs。 思路 大体思路如下&#xff1a; 架设一个正投影摄像机&#xff0c;在屏幕中间…

技术阅读周刊第9️⃣期

技术阅读周刊&#xff0c;每周更新。 历史更新 20231107&#xff1a;第五期20231117&#xff1a;第六期20231124&#xff1a;第七期20231201&#xff1a;第八期 美团技术博客十周年&#xff0c;感谢一路相伴 - 美团技术团队 URL: https://tech.meituan.com/2023/12/04/ten-year…

java学生选课系统 数据库版

首先让我们创建一个数据库 让我们向表中插入数据然后查询它

AI全栈大模型工程师(二十八)如何做好算法备案

互联网信息服务算法 什么情况下要备案&#xff1f; 对于B2B业务&#xff0c;不需要备案。 但在B2C领域&#xff0c;一切要视具体情况而定。 如果我们自主训练大型模型&#xff0c;这是必要的。 但如果是基于第三方模型提供的服务&#xff0c;建议选择那些已获得备案并且具有较大…

光伏开发设计施工一体化系统都有哪些功能?

随着全球对可再生能源的需求不断增加&#xff0c;光伏行业得到了快速发展。同时也面临着一些挑战&#xff0c;例如初始投资成本高、需要大量土地和水资源等。鹧鸪云光伏与储能软件利用技术创新&#xff0c;促进光伏行业数字化升级。 一、智能测算 1.投融资表&#xff1a;采用…

如何处理PHP开发中的单元测试和自动化测试?

如何处理PHP开发中的单元测试和自动化测试&#xff0c;需要具体代码示例 随着软件开发行业的日益发展&#xff0c;单元测试和自动化测试成为了开发者们重视的环节。PHP作为一种广泛应用于Web开发的脚本语言&#xff0c;单元测试和自动化测试同样也在PHP开发中扮演着重要的角色…

java智慧工地系统:让工地管理可视化、数字化、智能化

智慧工地功能包括&#xff1a;劳务管理、施工安全管理、视频监控管理、机械安全管理、危大工程监管、现场物料监管、绿色文明施工、安全隐患排查、施工综合管理、施工质量管理、设备管理、系统管理等模块。 一、项目开发环境 技术架构&#xff1a;微服务 开发语言&#xff1a;…

Ubuntu 设置共享文件夹

一、在Windows中建立一个英文的文件夹 注意&#xff1a;新建文件夹的名称一定要是英文的&#xff0c;不能出现中文的路径&#xff08;可能出现问题&#xff09; 二、在VMware中添加共享文件 3: VMware安装VMware Tools 一般安装成功桌面上会显示这个安装包&#xff0c;&…

【从零开始学习JAVA集合 | 第一篇】深入解读HashMap源码(含面试题)

目录 目录 前言&#xff1a; HashMap简介&#xff1a; HashMap的常用常量和变量&#xff1a; HashMap的重要考点&#xff1a; HashMap的存储过程&#xff1a; HashMap的扩容过程&#xff1a; HashMap的初始化&#xff1a; 常见面试题&#xff1a; 总结&#xff1a;…

菜鸟学习日记(python)——迭代器与生成器

迭代器 迭代是 Python 最强大的功能之一&#xff0c;是访问集合元素的一种方式。 迭代器是一个可以记住遍历的位置的对象。 迭代器对象从集合的第一个元素开始访问&#xff0c;直到所有的元素被访问完结束。迭代器只能往前不会后退。 迭代器有两个基本的方法&#xff1a;it…

【大数据】Hudi 核心知识点详解(一)

&#x1f60a; 如果您觉得这篇文章有用 ✔️ 的话&#xff0c;请给博主一个一键三连 &#x1f680;&#x1f680;&#x1f680; 吧 &#xff08;点赞 &#x1f9e1;、关注 &#x1f49b;、收藏 &#x1f49a;&#xff09;&#xff01;&#xff01;&#xff01;您的支持 &#x…

win10中CMD找不到adb的解决方法

问题描述&#xff1a; 在cmd命令行输入”adb devices” 时就会出现”adb不是内部命令或者外部命令….”&#xff0c;出现这个问题主要是windows系统环境变量没设置好。 配置环境变量 找到本地 adb.exe 程序所在目录&#xff0c;复制当前目录&#xff1b;找到高级系统设置 &g…

CleanMyMac X2024(Mac优化清理工具)v4.14.5中文版

CleanMyMac X是一款颇受欢迎的专业清理软件&#xff0c;拥有十多项强大的功能&#xff0c;可以进行系统清理、清空废纸篓、清除大旧型文件、程序卸载、除恶意软件、系统维护等等&#xff0c;并且这款清理软件操作简易&#xff0c;非常好上手&#xff0c;特别适用于那些刚入手苹…

Xubuntu16.04系统中使用EDIMAX EW-7822UAC无线网卡开启5G自发AP

目录 1.关于 EDIMAX EW-7822UAC2.驱动安装3.查看无线网卡信息3.通过create_ap配置5G自发AP 1.关于 EDIMAX EW-7822UAC 官网介绍 https://www.edimax.com/edimax/merchandise/merchandise_detail/data/edimax/global/wireless_adapters_ac1200_dual-band/ew-7822uac/ 详细参数…

大数据企业如何使用IP代理进行数据抓取

目录 一、引言 二、IP代理概述 三、为什么大数据企业需要使用IP代理 四、使用IP代理进行数据抓取的步骤 1、获取可用的代理IP 2、配置代理IP 3、设置请求头部信息 4、开始数据抓取 5、错误处理和重试 五、IP代理的注意事项 六、总结 一、引言 随着互联网的快速发展…