【JavaEE进阶】Spring 更简单的读取和存储对象

文章目录

  • 一. 存储Bean对象
    • 1. 配置扫描路径
    • 2. 添加注解存储 Bean 对象
      • 2.1 使用五大类注解存储Bean
      • 2.2 为什么要有五大类注解?
      • 2.3 有关获取Bean参数的命名规则
    • 3. 使用方法注解储存 Bean 对象
      • 3.1 方法注解储存对象的用法
      • 3.2 @Bean的重命名
      • 3.3 同⼀类型多个 @Bean 报错
  • 二. 获取 Bean 对象(对象装配)
    • 1. 属性注入
    • 2. Setter注入
    • 3. 构造方法注入(Spring官方推荐)
    • 4. @Resource:另⼀种注入关键字

一. 存储Bean对象

1. 配置扫描路径

配置扫描路径是使用注解之前的前置工作,是非常重要的,是必须的操作项.只有被配置的包下的所有类,添加了注解才能被正确的识别并保存到 Spring 中.

首先创建一个Spring项目.创建好后,第一步就是配置扫描路径:在resources目录中创建一个spring-config.xml文件.然后在spring-config.xml添加如下配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <content:component-scan base-package=""></content:component-scan>
</beans>

<content:component-scan base-package=""></content:component-scan>base-package=""的值设置为需要扫描对象的根路径.注意:这个根路径是从java目录开始的.
在这里插入图片描述

2. 添加注解存储 Bean 对象

想要将对象存储在spring中,有两种注解类型可以实现:

  1. 使用类注解(五大类注解):

    • @Controller:控制器:验证用户请求的数据正确性(相当于安保系统).
    • @Service:服务:编排和调度具体执行方法(相当于客服中心).
    • @Repository:持久层:和数据库交互;(相当于执行者) = DAO(Date Access Obiect)数据访问层
    • @Component:组件;(工具类)
    • @Configuration:配置项(项目中的一些配置)
  2. 方法注解

    • @Bean

2.1 使用五大类注解存储Bean

首先,我们来了解如何使用五大类注解来储存对象

  1. @Controller

    package com.spring.demo;
    
    import org.springframework.stereotype.Controller;
    
    @Controller
    public class UserController {
        public void sayHi() {
            System.out.println("UserController sayHi!");
        }
    }
    

    在扫描路径下创建该UserController类.并在类上加@Controller注解,此时就将Bean存储到容器中了.

    接下来就是从 Spring 中读取出我们的对象,这里还是先使用依赖查找的方式来获取 Bean,使用五大类注解,默认情况下,Bean 的名字就是原类名首字母小写(小驼峰).

    import com.spring.demo.UserController;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class App {
        public static void main(String[] args) {
            //1.获取 srping 容器
            ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
            //2.获取 bean 对象
            //获取对象时使用类名的小驼峰形式作为 name 参数
            UserController userController =  context.getBean("userController", UserController.class);
            //3.使用 bean
            userController.sayHi();
        }
    }
    

    运行结果:
    在这里插入图片描述
    注意:要将Bean存储到Spring中需要满足两个条件:

    1. 使用五大类注解创建的类
    2. 必须在配置的扫描路径下.(包括子包)

    扫描路径也叫做根路径.两个条件缺一不可.

    为什么要设置根路径?
    设置根路径其实也是为了提高程序的性能,因为如果不设置根路径,Spring 就会扫描项目文件中所有的目录,但并不是所有类都需要储存到 Spring当中,这样性能就会比较低,设置了根路径,Spring 就只扫描该根路径下所有的目录就可以了,提高了程序的性能。下来我们演示一下没有配置扫描路径下的情况:
    在这里插入图片描述
    还需要知道的是使用注解存储的 Bean 和使用XML存储的的 Bean 是可以一同使用的,比如我们将刚刚有问题的Student重新通过XML的方式进行存储.
    在这里插入图片描述

    注意:默认情况下,使用原类名首字母小写就能读取到Bean对象.特例情况:原类名如果首字母和第二个字母都是大写的情况下,那么bean名称就是原类名.
    在这里插入图片描述

  2. @Service
    启动类中代码:

    //1.获取 srping 容器
            ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
            //2.获取 bean 对象
            //获取对象时使用类名的小驼峰形式作为 name 参数
            UserService userService =  context.getBean("userService", UserService.class);
            //3.使用 bean
            userService.sayHi();
    

    UserService类:

    package com.spring.demo;
    
    import org.springframework.stereotype.Service;
    
    @Service
    public class UserService {
        public void sayHi(){
            System.out.println("UserService sayHi!");
        }
    }
    

    运行结果:
    在这里插入图片描述

其余三种使用方式相同,此处不再做介绍.

2.2 为什么要有五大类注解?

既然都五大类完成的是同样的工作,那为什么要有五大类注解呢?

其实五大类注解主要是为了规范 Java 项目的代码,Java 项目的标准分层如下:

  1. 控制层(Controller)
  2. 服务层(Service)
  3. 数据持久层(Dao)

而五大类注解便是对应着不同的层级别使用的,让程序猿看到某一个注解就可以明确这个了类是做什么的。
程序的⼯程分层,调⽤流程如下:
在这里插入图片描述
包括企业中也是按照这样的结构来将项目分层的,典型的比如阿里,它只是在标准分层在服务层(Service)做了一个扩展,划分的更加细致详细了.
在这里插入图片描述
五大类注解主要起到的是“见名知意”的作用,代码层面上来看,作用是类似的.查看五大类源码可知:
五大类的源码中除了 @Component 以外,其他四大类注解中都包含了 @Component 注解的功能,这四大类注解都是基于 @Component 实现的,是 @Component 拓展。

2.3 有关获取Bean参数的命名规则

上文中在使用依赖查找的方式获取Bean时,我们讲到了getBean方法的BeanName是使用类名的小驼峰形式(即类名的首字母小写)以及第一个字母和第二个字母都大写情况下的特例.

注意:BeanName的规范命名规则并不是 Spring 独创的,而依照 Java 标准库的规则进行的。

BeanName的规范命名规则:

  1. 如果类名不存在或类名为空字符串,BeanName为原类名。
  2. 如果类名字长度大于1,且第一个与第二个字符为大写,BeanName为原类名。
  3. 其他情况,BeanName为原类名的小驼峰形式.

3. 使用方法注解储存 Bean 对象

3.1 方法注解储存对象的用法

类注解是添加到某个类上的,而方法注解是放到某个方法上的.在Spring框架的设计中,方法注解@Bean要配合类注解才能将对象正常存储到Spring容器中.

举个🌰:我们有一个普通书本类

package com.spring.demo;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;

@Controller
public class BookInfo {
    private String bookName;
    private String author;
    private String style;

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getStyle() {
        return style;
    }

    public void setStyle(String style) {
        this.style = style;
    }

    @Override
    @Bean
    public String toString() {
        return "com.spring.demo.BookInfo{" +
                "bookName='" + bookName + '\'' +
                ", author='" + author + '\'' +
                ", style='" + style + '\'' +
                '}';
    }

}

下面演示使用@Bean方法注解储存对象:

package com.spring.demo;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;

@Controller
public class Books {
    @Bean
    public BookInfo getBook(){
        BookInfo bookInfo = new BookInfo();
        bookInfo.setBookName("三体");
        bookInfo.setAuthor("刘慈欣");
        bookInfo.setStyle("文学科幻");
        return bookInfo;
    }

    public void sayHi(){
        System.out.println("Books sayHi!");
    }
}

启动类:

获取方法注解储存的对象时,传入的BeanName参数值默认值就是方法名,上面的代码中方法名为getBook,所以获取时,就使用getBook作为参数来进行获取。

import com.spring.demo.BookInfo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App2 {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        BookInfo book =  context.getBean("getBook", BookInfo.class);

        System.out.println(book);
    }
}

运行结果:
在这里插入图片描述

3.2 @Bean的重命名

获取方法注解储存的对象时,传入的BeanName参数值默值为方法名,但像上面那样返回对象的方法名称往往是getXXX这样式取名的,虽然在语法与实现上是没有问题的,但实际开发写出这样的代码,看起来还是比较别扭的。
实际上注解 @Bean 是可以加参数的,给储存的对象起别名,像下面这个样子。

package com.spring.demo;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;

@Controller
public class Books {
    @Bean(name = "book")
    public BookInfo getBook(){
        BookInfo bookInfo = new BookInfo();
        bookInfo.setBookName("三体");
        bookInfo.setAuthor("刘慈欣");
        bookInfo.setStyle("文学科幻");
        return bookInfo;
    }

    public void sayHi(){
        System.out.println("Books sayHi!");
    }
}

在这里插入图片描述

也可以给 Bean 设置多个别名,总结起来有如下几种方式:

//方式一(省略参数名的情况下默认是name)
@Bean("article1")
//方式二
@Bean(name = "article2")
//方式三
@Bean(value = "article3")
//起多个别名
@Bean(name = {"article4", "article5"})
@Bean(value = {"article6", "article7"})
@Bean({"article8", "article9", "article10"})

但是需要注意,当重新命名之后,就不能使用原来的方法名来获取对象了.
在这里插入图片描述
所以使用 @Bean 存储对象的beanName命名规则是,当没有设置name/value属性时,此时 Bean 的默认名字就是方法名,一旦添加了别名name/value属性后,就只能通过重命名的别名来获取 Bean 了,默认的使用方法名获取 Bean 对象就不能使用了。

@Bean 使用时,同一类如果多个 Bean 使用相同的名称,此时程序执行是不会报错的,他会根据类加载顺序和类中代码从上至下的的顺序,将第一个 Bean 存放到 Spring 中,但第一个之后的对象就不会被存放到容器中了,也就是只有在第一次创建 Bean 的时候会将对象和 Bean 名称关联起来,后续再有相同名称的Bean存储时候,容器会自动忽略。

还可以通过类注解 @Order 注解控制类加载顺序(值越小,优先级越高),进而影响 Bean 的存放的先后顺序.

3.3 同⼀类型多个 @Bean 报错

当出现以下多个 Bean,返回同⼀对象类型时程序会报错,如下代码所示:
在这里插入图片描述
在这里插入图片描述
运行结果如下:
在这里插入图片描述
报错的原因是,⾮唯⼀的 Bean 对象.
同⼀类型多个 Bean 报错处理:
解决同⼀个类型,多个 bean 的解决⽅案有以下两个:

  1. 使⽤ @Resource(name="user1") 定义。(@Resource下文有介绍)
    在这里插入图片描述
  2. 使⽤ @Qualifier 注解定义名称。
    在这里插入图片描述

二. 获取 Bean 对象(对象装配)

获取bean对象也叫做对象装配.是把bean对象取出来放到某个类中.有时候也叫对象注⼊(DI).
对象装配(对象注⼊)的实现⽅法以下 3 种:

  1. 属性注⼊
  2. 构造⽅法注⼊
  3. Setter 注⼊
    接下来,我们分别来看。
    下⾯我们按照实际开发中的模式,将 Service 类注⼊到 Controller 类中。

1. 属性注入

属性注⼊是使⽤ @Autowired 实现的,将 Service 类注⼊到 Controller 类中。
User代码:

package com.spring.demo;

public class User {
    private Integer id;
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

Service代码:

package com.spring.demo;

import org.springframework.stereotype.Service;

@Service
public class UserService {
    public void sayHi(){
        System.out.println("UserService sayHi!");
    }
    public User getUser(Integer id){
        User user = new User();
        user.setId(id);
        user.setName("xxxflower-"+id);
        return user;
    }

}

Controller代码:

package com.spring.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class UserController {

    @Autowired
    private UserService userService;

    public User getUser(Integer id){
        return userService.getUser(id);
    }

    public void sayHi() {
        System.out.println("UserController sayHi!");
    }
}

运行结果:
在这里插入图片描述
在这里插入图片描述
优点:简单.
缺点:

  1. 没办法实现final修饰的变量注入.
    在这里插入图片描述
  2. 兼容不好:只适用于Ioc容器.
  3. 风险:因为写法简单,所以违背单一设计原则的概率更大.

2. Setter注入

Setter 注⼊和属性的 Setter ⽅法实现类似,只不过在设置 set ⽅法的时候需要加上 @Autowired 注解,如下代码所示:

package com.spring.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class UserController2 {
    private UserService userService;
	//2.使用Setter注入
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public User getUser(Integer id){
        return userService.getUser(id);
    }
}

运行结果:
在这里插入图片描述
优点:符合单一设计原则(每个方法只传递一个对象)
缺点:

  1. 不能注入不可变对象
    在这里插入图片描述
  2. 使用setter注入的对象可能会被修改.

3. 构造方法注入(Spring官方推荐)

构造⽅法注⼊是在类的构造⽅法中实现注⼊,如下代码所示:

package com.spring.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class UserController3 {

    private UserService userService;
    //3.构造方法注入
    @Autowired
    public UserController3(UserService userService){
        this.userService = userService;
    }

    public User getUser(Integer id){
        return userService.getUser(id);
    }
}

运行结果:
在这里插入图片描述
特点:如果当前类中只有一个构造方法的话,那么@Autowired 注解可以省略.
在这里插入图片描述
优点:

  1. 可以注入一个不可变对象(使用fianl修饰的对象)
    在这里插入图片描述

问题:为什么构造方法可以注入一个不可变对象,而属性注入和Setter注入却不行?
答:这是Java的规定,在java中,被final对象必须满足以下两个条件中的任意一个:

  1. final修饰的对象,是直接复制的.
  2. final修饰的对象,必须在构造方法中赋值.
  1. 注入的对象不会被改变(构造方法只能执行一次)
  2. 构造方法注入可以保证注入对象完全被初始化
  3. 通用性更好.

4. @Resource:另⼀种注入关键字

在进行类注⼊时,除了可以使⽤ @Autowired 关键字之外,我们还可以使⽤ @Resource 进⾏注⼊,如下代码所示:

package com.spring.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import javax.annotation.Resource;

@Controller
public class UserController {

//    @Autowired
    @Resource
    private UserService userService;

    public User getUser(Integer id){
        return userService.getUser(id);
    }

    public void sayHi() {
        System.out.println("UserController sayHi!");
    }
}

上述三种注入方式使用@Autowired行,使用@Resource也行,但是这两者也是有区别的:

  1. 出身不同:@Autowired 来自于 Spring,而 @Resource 来⾃于 JDK 的注解;
  2. 使⽤时设置的参数不同:相比于 @Autowired 来说,@Resource ⽀持更多的参数设置,例如
    name 设置,根据名称获取 Bean。
  3. @Autowired 可⽤于 Setter 注⼊、构造函数注⼊和属性注⼊,⽽ @Resource 只能⽤于 Setter 注⼊和属性注⼊,不能⽤于构造函数注⼊。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

国产芯力特Mini LIN SBC SIT1028Q应用方案,可替代TJA1028

SIT1028Q是一款内部集成高压LDO稳压源的本地互联网络&#xff08;LIN&#xff09;物理层收发器&#xff0c;可为外部ECU&#xff08;Electronic Control Unit&#xff09;微控制器或相关外设提供稳定的5V/3.3V电源&#xff0c;该LIN收发器符合LIN2.0、LIN2.1、LIN2.2、LIN2.2A、…

应急响应-linux挖矿病毒的实战处置

0x01 服务器现状分析 客户描述服务器卡顿&#xff0c;切通过搜索引擎进去该官网跳转非法页面&#xff0c;但本地访问无异常 0x02 信息收集 通过进程占用情况cpu功率拉满&#xff0c;确定被植入挖矿病毒文件 qq 且存在计划任务update.sh&#xff1a;crontab -l 将该文件上传沙…

Java课题笔记~ HTTP协议(请求和响应)

Servlet最主要的作用就是处理客户端请求&#xff0c;并向客户端做出响应。为此&#xff0c;针对Servlet的每次请求&#xff0c;Web服务器在调用service()方法之前&#xff0c;都会创建两个对象 分别是HttpServletRequest和HttpServletResponse。 其中HttpServletRequest用于封…

【WebService】使用postman调用WebService方法

1、需求 公司原来有一个项目使用的是WebService&#xff0c;想模拟一下怎么调用WebService的方法&#xff0c;使用postman调用怎么调用。 2、postman方式 接口&#xff1a;http://127.0.0.1:8080/SecurityWebService/SecurityCommand?wsdl 对应你的代码配置&#xff1a; …

模拟实现消息队列项目(系列4) -- 服务器模块(内存管理)

目录 前言 1. 创建MemoryDataCenter 2. 封装Exchange 和 Queue方法 3. 封装Binding操作 4. 封装Message操作 4.1 封装消息中心集合messageMap 4.2 封装消息与队列的关系集合queueMessageMap的操作 5. 封装未确认消息集合waitMessage的操作 6. 从硬盘中恢复数据到内存中 7. Memo…

介绍另外一个容器技术, Apptainer

一说到容器&#xff0c;我们往往会脱口而出&#xff0c; Docker&#xff0c; 实际上Docker 仅仅是Linux 容器化的一种&#xff0c; 今天介绍的Apptainer 就是另外一种容器技术。 那么Apptainer 具体是一个什么东西呢&#xff1f; 跟Docker 有什么区别呢&#xff1f; 首先&#…

【Python】python通过cmd创建虚拟环境(pip方式)

前言&#xff1a; 在window中使用pipenv创建虚拟环境时&#xff0c;虚拟环境默认的位置是在C:\User\Administrator\.virtualenvs\目录下&#xff1b;那如果我们想配置到自定义位置&#xff0c;该如何修改呢&#xff1f;当我们在进行python项目开发的时候&#xff0c;为了不让项…

tcl学习之路(四)(vivado设计分析)

1.FPGA芯片架构中的对象 在打开elaborated/synthesied/implemented的情况下&#xff0c;可使用如下命令获取期望的SLICE。SLICE分为SLICEL和SLICEM&#xff0c;由LUT、FF、MUX、CARRY组成。 set all_slice [get_sites SLICE*] set col_slice [get_sites SLICEX0Y*] set all_sl…

【资料分享】全志科技T507-H工业核心板规格书

1 核心板简介 创龙科技SOM-TLT507是一款基于全志科技T507-H处理器设计的4核ARM Cortex-A53全国产工业核心板&#xff0c;主频高达1.416GHz。核心板CPU、ROM、RAM、电源、晶振等所有元器件均采用国产工业级方案&#xff0c;国产化率100%。 核心板通过邮票孔连接方式引出MIPI C…

【爱书不爱输的程序猿】内网的摄像头,远程进行访问的方式方法

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 快速远程访问内网的摄像头【内网穿透】 前言一、快速远程访问内网的摄像头1. 打开“允许远程桌面”开关2. 建立TCP-IP隧道3. 获取生成的TCP-IP隧道地址4. 连接另一台电脑4.1 取得该…

Python自动化测试基础必备知识点总结

目录 一、自动化测试的概念 二、Python自动化测试基础必备知识点 一、自动化测试的概念 性能系统负载能力稳定性过载操作下的系统瓶颈自动化测试&#xff0c;使用程序代替人工&#xff0c;可以提高测试效率性&#xff0c;自动化测试能自动化使用代码模拟大量用户&#xff0c…

java+springboot+mysql小区宠物管理系统

项目介绍&#xff1a; 使用javaspringbootmysql开发的小区宠物管理系统&#xff0c;系统包含超级管理员&#xff0c;系统管理员、用户角色&#xff0c;功能如下&#xff1a; 超级管理员&#xff1a;管理员管理&#xff1b;用户管理&#xff1b;宠物分类&#xff1b;宠物管理&…

【Unity细节】Unity打包后UI面板消失是怎么回事

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 秩沅 原创 收录于专栏&#xff1a;unity细节和bug ⭐关于物体的动画碰到其他碰撞器后停止播放的问题⭐ 文章目录 ⭐关于物体的动画碰…

Netty:用forEachByte遍历处理ByteBuf中的可读字节

说明 io.netty.buffer.ByteBuf的forEachByte(ByteProcessor processor)用指明的ByteProcessor 遍历ByteBuf中的可读字节。遍历的时候用升序遍历。 -这个函数可以在ByteBuf中寻找某个字节首次出现的位置&#xff0c;或者首次不是某个字节的位置。 如果已经遍历完了可读字节但还…

Spring Cloud Gateway

一 什么是Spring Cloud Gateway 网关作为流量的入口&#xff0c;常用的功能包括路由转发&#xff0c;权限校验&#xff0c;限流等。 Spring Cloud Gateway 是Spring Cloud官方推出的第二代网关框架&#xff0c;定位于取代 Netflix Zuul。相比 Zuul 来说&#xff0c;Spring Clo…

Unity背包系统与存档(附下载链接)

下载地址: https://download.csdn.net/download/qq_58804985/88184776 视频演示: 功能: 拖动物品在背包中自由移动,当物品拖动到其他物品上时,和其交换位置.基于EPPlus的背包数据与位置保存 原理: 给定一个道具池表格与一个背包表格 道具池表格负责存储所有道具的信息 背…

[分享]STM32G070 串口 乱码 解决方法

硬件 NUCLEO-G070RB 工具 cubemx 解决方法 7bit 改为 8bit printf 配置方法 添加头文件 #include <stdio.h> 添加重定向代码 #ifdef __GNUC__#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)#else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)#endi…

网络安全(黑客)常用工具(附配套资料+工具安装包)

几十年来&#xff0c;攻击方、白帽和安全从业者的工具不断演进&#xff0c;成为网络安全长河中最具技术特色的灯塔&#xff0c;并在一定程度上左右着网络安全产业发展和演进的方向&#xff0c;成为不可或缺的关键要素之一。 话不多说&#xff0c;2022年全球白帽常用工具排行榜…

解决Windows:Call to undefined function exif_imagetype()

很明显,是php安装时没有打开某些扩展,以致不能执行exif_imagetype()这个方法,因此需要打开。 网上很多人说需要打开下面这两个扩展: extension=php_exif.dll extension=php_mbstring.dll 但只说对了一半,我一开始也按照网上文章说的打开这两个扩展,但是还是同样错误。…

Leetcode-每日一题【剑指 Offer 14- II. 剪绳子 II】

题目 2、3、3的三段&#xff0c;此时得到的最大乘积是18。 答案需要取模 1e97&#xff08;1000000007&#xff09;&#xff0c;如计算初始结果为&#xff1a;1000000008&#xff0c;请返回 1。 示例 1&#xff1a; 输入: 2输出: 1解释: 2 1 1, 1 1 1 示例 2: 输入: 10输出…