Spring概述

​ 我们常说的 Spring 实际上是指 Spring Framework,而 Spring Framework 只是 Spring 家族中的一个分支而已。Spring 是为了解决企业级应用开发的复杂性而创建的。

​ 如果我们想实现某个功能,代码量一般都是固定的,要么全自己写,要么用已有的优秀框架,而Spring不仅已经给我们提供了各种优秀组件,还提供了良好的代码组织逻辑跟业务开发流程规范框架,我们主要学习Spring中以下几点:

  • IOC/DI
  • AOP
  • 声明式事务
  • JdbcTemplate

Spirng组件

​ Spring框架具有很多组件,大约有20多个模块 。我们要记住以下7个核心组件和它的含义。

  1. Spring Core:Spring核心,它是框架最基础的部分,提供IOC和依赖注入DI特性
  2. Spring Context:Spring上下文容器,它是 BeanFactory 功能加强的一个子接口
  3. Spring Web:它提供Web应用开发的支持。
  4. Spring MVC:它针对Web应用中MVC思想的实现。
  5. Spring DAO:提供对JDBC抽象层,简化了JDBC编码,同时,编码更具有健壮性。
  6. Spring ORM:它支持用于流行的ORM框架的整合,比如:Spring + Hibernate、Spring + iBatis、Spring + JDO的整合等。
  7. Spring AOP:即面向切面编程,它提供了与AOP联盟兼容的编程实现。

​ 下图就是maven导入spring后的组件:

IOC

​ IOC(Inversion of Control),中文叫做控制反转

​ Spring提出了一种思想:由Spring来负责控制对象的生命周期和对象间的关系。所有的类都会在Spring容器中登记,告诉Spring这这个类是什么,需要什么,然后Spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的Bean。所有的类的创建、销毁都由Spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是Spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转(Inversion of Controller),也可以叫依赖注入 DI(Dependency Injection)。

​ 举个例子:

public class Book {
private Integer id;
private String name;
private Double price;
//省略getter/setter
}
public class User {
private Integer id;
private String name;
private Integer age; public void doSth() {
Book book = new Book();
book.setId(1);
book.setName("故事新编");
book.setPrice((double) 20);
}
}

​ 上面这个例子中,Book对象的控制权在User里面,Book和User高度耦合,如果在其他对象中需要使用 Book 对象,得重新创建,也就是说,对象的创建、初始化、销毁等操作,统统都要开发者自己来完成。

使用 Spring 之后,我们可以将对象的创建、初始化、销毁等操作交给 Spring 容器来管理。就是说,在项目启动时,所有的 Bean 都将自己注册到 Spring 容器中去(如果有必要的话),然后如果其他 Bean 需要使用到这个 Bean ,则不需要自己去 new,而是直接去 Spring 容器去要。

什么是Bean

​ 我们本篇会一直提到Bean,先在前文给Bean做一个大概的介绍。Spring Bean是被实例的,组装的及被Spring 容器管理的Java对象。Spring 容器会自动完成@bean对象的实例化。创建应用对象之间的协作关系的行为称为:装配(wiring),这就是依赖注入的本质。

何为控制

​ 是 bean 的创建、管理的权利,控制 bean 的整个生命周期。

何为反转

​ 把这个权利交给了 Spring 容器,而不是自己去控制,就是反转。由之前的自己主动创建对象,变成现在被动接收别人给我们的对象的过程,这就是反转。

何为依赖

​ 程序运行需要依赖外部的资源,提供程序内对象的所需要的数据、资源。

何为注入

​ 配置文件把资源从外部注入到内部,容器加载了外部的文件、对象、数据,然后把这些资源注入给程序内的对象,维护了程序内外对象之间的依赖关系。

实例1:进一步了解IOC

​ 我们在IDEA创建一个普通Maven项目,然后再pom文件中引入spring-context 依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId>
<artifactId>SpringDemo</artifactId>
<version>1.0-SNAPSHOT</version> <dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
</dependencies> </project>

​ 然后在 resources 目录下创建一个 spring 的配置文件spring.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> </beans>

​ 文件中我们可以配置bean,把我们的book配置进去

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="org.javaboy.Book" id="book"/>
</beans>

说明:class 属性表示需要注册的 bean 的全路径,id 则表示 bean 的唯一标记,也开可以 name 属性作为 bean 的标记,在超过 99% 的情况下,id 和 name 其实是一样的。

​ 最后,我们来测试一下,创建一个Main方法来加载这个配置文件,通过 getBean 方法,从容器中去获取对象:

public class Main {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Book book = (Book) ctx.getBean("book");
System.out.println(book);
}
}

​ 打印的结果为:Book{id=null, name='null', price=null}

说明:上面getBean中传入的是我们命名的name或id,这种方式好处是我们给它起了个名,在引入两个或多个相同对象时,有别名不至于混淆。有些教程喜欢在getBean中直接通过Class 去获取一个 Bean,如传入Book.class,如果spring.xml中引入两个book的bean,那么这种做法就会报错,所以我个人不推荐通过Class去获取Bean。

name与id之间的一些注意点

​ 上文中提到了name与id,确实,大部分时候name和id是一样的,也很少在开发中又用name又用id,但是还是要注意一些细节。

  • 配置两个相同的 id 或者 name 都不能通过。
  • 如果既配置了 id ,也配置了 name ,则两个都生效。如果id和name都没有指定,则用类全名作为name,如<bean class="com.stamen.BeanLifeCycleImpl">,则你可以通过getBean("com.stamen.BeanLifeCycleImpl")返回该实例。
  • 如果配置基本类的时候,注解和配置文件都使用的时候,注解和配置文件中 name 相同的时候, 则两个冲突,配置文件生效; 如果配置基本类的时候,注解和配置文件都使用的时候,注解和配置文件中 name 不相同的时候, 则两个不冲突,都能够生效。

属性注入

​ 上一个例子中我们明白了Spirng的IOC可以帮我们管理Bean,将对象的创建、初始化、销毁等操作交给Spring管理,使开发更加方便。此外,上一个例子中我们在spring.xml中配置了Book,最后打印的结果中我们看到Book中的属性并没有值,是null。这一小节就是了解spring是如何注入属性的,有以下几种方式:

  • 构造方法注入
  • set方法注入
  • p命名空间注入
  • 自动装配和@Autowired注解注入
  • 静态工厂注入
  • 实例工厂注入

构造方法注入

  1. 给Book添加一个有参和无参构造方法:

  2. 在xml中注入bean

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean class="com.wms.Demo01.Book" id="book">
    <constructor-arg index="0" value="1"/>
    <constructor-arg index="1" value="宇宙未解之谜"/>
    <constructor-arg index="2" value="39.9"/>
    </bean>
    </beans>

    或者使用name标签,更加清晰

    <bean class="com.wms.Demo01.Book" id="book">
    <constructor-arg name="id" value="1"/>
    <constructor-arg name="name" value="宇宙未解之谜"/>
    <constructor-arg name="price" value="39.9"/>
    </bean>
  3. 说明:

  • constructor-arg --> 指定构造函数的参数
  • index --> 参数的顺序
  • name --> 参数的名称
  • value --> 给参数赋值
  • 注意,你也可以按index2, 0, 1等顺序来给属性注入值,但记得 index 的值和 value 要一一对应,id就要注入id相符的值。

set方法注入

​ set方法注入方式如下:

<bean class="com.wms.Demo01.Book" id="book">
<property name="id" value="1"/>
<property name="name" value="宇宙未解之谜"/>
<property name="price" value="39.9"/>
</bean>

​ 注意这里使用的是property标签,而且name并不是Book这个对象中定义的属性,而是通过get/set方法分析出来的属性名,只是我们规范get/set方法就是get/set + 属性名。

p命名空间注入

​ p 名称空间注入,使用的比较少,它本质上也是调用了 set 方法。

<bean class="com.wms.Demo01.Book" id="book" p:id="1" p:bookName="宇宙未解之谜" p:price="39.9"></bean>

自动装配和@Autowired注解注入

​ 我将这两个放在一起讲,因为要介绍到byName和byTpye的区别。Spring提供了自动装配的功能,简化了我们的配置,自动装配默认是不打开的,常用的方式有两种,byName和byType。方式是在bean标签中加入autowire="byName"autowire="byType"

<bean class="com.wms.Demo01.Book" id="book" autowire="byType"/>

​ 后续我们还会接触到@Autowired注解,@Autowired注解可以实现自动装配,只要在对应的属性上标记该注解,但是@Autowired注解只按照byType注入。这个注解常见于Controller层。如下:

public class UserController {

    @Autowired
private IUserService userService;
}

​ 这里我们主要还是熟悉byName和byType的区别。其实byName根据被注入的名称作为bean名称作为依赖查找,并将对象设置到该属性。byType通过属性的类型查找javabean依赖的对象并为其注入。

byName和byType

  • byName按名称自动装配,当一个bean节点带有 autowire byName的属性时。

    • 将查找其类中所有的set方法名,例如setCat,获得将set去掉并且首字母小写的字符串,即cat。
    • 去spring容器中寻找是否有此字符串名称id的对象。
    • 如果有,就取出注入;如果没有,就报空指针异常。
  • byType按类型自动装配,使用autowire byType首先需要保证:同一类型的对象,在spring容器中唯一。如果不唯一,会报不唯一的异常。

@Autowired、@Qualifier和@Resource

​ 既然讲到了@Autowired,就展开讲一下一些相关的注解。(下面出现的代码来自狂神说的spring教程)

  • @Autowired

    • @Autowired是按类型自动转配的,不支持id匹配。
    • 需要导入 spring-aop的包!
    • @Autowired(required=false) 说明:false,对象可以为null;true,对象必须存对象,不能为null。
  • @Qualifier

    • @Autowired是根据类型自动装配的,加上@Qualifier则可以根据byName的方式自动装配。

    • @Qualifier不能单独使用。

      • 在属性上添加Qualifier注解

      • 示例:

        @Autowired
        @Qualifier(value = "cat2")
        private Cat cat;
        @Autowired
        @Qualifier(value = "dog2")
        private Dog dog;
  • @Resource

    • @Resource如有指定的name属性,先按该属性进行byName方式查找装配;
    • 其次再进行默认的byName方式进行装配;
    • 如果以上都不成功,则按byType的方式自动装配。
    • 都不成功,则报异常。

实体类:

public class User {
//如果允许对象为null,设置required = false,默认为true
@Resource(name = "cat2")
private Cat cat;
@Resource
private Dog dog;
private String str;
}

beans.xml

<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat1" class="com.kuang.pojo.Cat"/>
<bean id="cat2" class="com.kuang.pojo.Cat"/> <bean id="user" class="com.kuang.pojo.User"/>

测试:结果OK

配置文件2:beans.xml , 删掉cat2

<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat1" class="com.kuang.pojo.Cat"/>

实体类上只保留注解

@Resource
private Cat cat;
@Resource
private Dog dog;

结果:OK

结论:先进行byName查找,失败;再进行byType查找,成功。

@Autowired与@Resource异同:

1、@Autowired与@Resource都可以用来装配bean。都可以写在字段上,或写在setter方法上。

2、@Autowired默认按类型装配(属于spring规范),默认情况下必须要求依赖对象必须存在,如果要允许null 值,可以设置它的required属性为false,如:@Autowired(required=false) ,如果我们想使用名称装配可以结合@Qualifier注解进行使用

3、@Resource(属于J2EE复返),默认按照名称进行装配,名称可以通过name属性进行指定。如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

静态工厂注入(TODO)

实例工厂注入(TODO)

更多属性注入方式

​ 上述的属性注入方式是比较基础的注入,实际开发中遇到的问题往往更加复杂,比如在开发过程中可能会注入跟多类型的数据,如:

  • 对象
  • 数组
  • Map

对象注入

可以通过 ref 来引用一个对象。

<bean class="com.wms.Demo01.User" id="user">
<property name="cat" ref="cat"/>
</bean>
<bean class="org.javaboy.Cat" id="cat">
<property name="name" value="小白"/>
<property name="color" value="白色"/>
</bean>

数组注入

  • array

    <bean class="com.wms.Demo01.User" id="user">
    <property name="cat" ref="cat"/>
    <property name="favorites">
    <array>
    <value>足球</value>
    <value>篮球</value>
    <value>乒乓球</value>
    </array>
    </property>
    </bean>
    <bean class="com.wms.Demo01.Cat" id="cat">
    <property name="name" value="小白"/>
    <property name="color" value="白色"/>
    </bean>
  • list

    • array 节点,也可以被 list 节点代替。

    • array 或者 list 节点中也可以是对象。

    • 即可以通过 ref 使用外部定义好的 Bean,也可以直接在 list 或者 array 节点中定义 bean。

      <bean class="com.wms.Demo01.User" id="user">
      <property name="cat" ref="cat"/>
      <property name="favorites">
      <list>
      <value>足球</value>
      <value>篮球</value>
      <value>乒乓球</value>
      </list>
      </property>
      <property name="cats">
      <list>
      <ref bean="cat"/>
      <ref bean="cat2"/>
      <bean class="com.wms.Demo01.Cat" id="cat3">
      <property name="name" value="小花"/>
      <property name="color" value="花色"/>
      </bean>
      </list>
      </property>
      </bean>
      <bean class="com.wms.Demo01.Cat" id="cat">
      <property name="name" value="小白"/>
      <property name="color" value="白色"/>
      </bean>
      <bean class="com.wms.Demo01.Cat" id="cat2">
      <property name="name" value="小黑"/>
      <property name="color" value="黑色"/>
      </bean>

Map 注入

<property name="map">
<map>
<entry key="age" value="100"/>
<entry key="name" value="abc"/>
</map>
</property>

Properties 注入

<property name="info">
<props>
<prop key="age">100</prop>
<prop key="name">abc</prop>
</props>
</property>

补充

  • 如果炫技,上面的都可以说。
  • 如果问Spring对象创建方式,要说到构造方法、静态工厂、实例工厂
  • 如果问到Spring注入方式,要说到构造方法、set方法、自动注入、p命名空间

Context

IOC 容器只是提供一个管理对象的空间而已,如何向容器中放入我们需要容器代为管理的对象呢?这就涉及到Spring的应用上下文Context

​ 工作中通过XML配置或注解 将需要管理的Bean跟Bean之间的协作关系配置好,然后利用应用上下文对象Context加载进Spring容器,容器就能为你的程序提供你想要的对象管理服务了。Spring 框架本身就提供了很多个容器的实现。我们在实例1中的Main中出现了ClassPathXmlApplicationContext,就是一种容器,还有很多容器,如下:

  1. AnnotationConfigApplicationContext:从一个或多个基于java的配置类中加载上下文定义,适用于java注解的方式。
  2. ClassPathXmlApplicationContext:从类路径下的一个或多个xml配置文件中加载上下文定义,适用于xml配置的方式。
  3. FileSystemXmlApplicationContext:从文件系统下的一个或多个xml配置文件中加载上下文定义,也就是说系统盘符中加载xml配置文件。
  4. AnnotationConfigWebApplicationContext:专门为web应用准备的,适用于注解方式。
  5. XmlWebApplicationContext:从web应用下的一个或多个xml配置文件加载上下文定义,适用于xml配置方式。

​ 比如ClassPathXmlApplicationContext,来自于我们常提到的ApplicationContext,但如果你点开源码看,就知道ClassPathXmlApplicationContext并不是直接实现ApplicationContext的,而是一层一层的递进,这是为了IOC全面性而考虑。此处的ApplicationContext也是面试中经常出现的问题,经常与BeanFactory一起作比较。

ApplicationContext & BeanFactory区别

BeanFactory接口

  • spring的原始接口,针对原始接口的实现类功能较为单一, 可以理解为 HashMap:它一般只有 get, put 两个功能。

    • Key - bean name
    • Value - bean object
  • BeanFactory接口实现类的容器,特点是每次在获得对象时才会创建对象
  • 优缺点:
    • 优点:应用启动的时候占用资源很少,对资源要求较高的应用,比较有优势;
    • 缺点:运行速度会相对来说慢一些。而且有可能会出现空指针异常的错误,而且通过Bean工厂创建的Bean生命周期会简单一些。

ApplicationContext接口

  • 每次容器启动时就会创建容器中配置的所有对象
  • 它是 BeanFactory 的子类,更好的补充并实现了 BeanFactory.ApplicationContext 多了很多功能,因为它继承了多个接口。 ApplicationContext 的里面有两个具体的实现子类,用来读取配置配件的,上面列举了5个。
  • 优缺点:
    • 优点:所有的Bean在启动的时候都进行了加载,系统运行的速度快;在系统启动的时候,可以发现系统中的配置问题。
    • 缺点:把费时的操作放到系统启动中完成,所有的对象都可以预加载,缺点就是内存占用较大。

BeanFactory & FactoryBean的区别

​ 既然提到了BeanFactory,面试中往往会用FactoryBean来“坑”面试者,这里就讲一下两者的区别。

  • BeanFactory

    • BeanFactory 以 Factory 结尾,表示它是一个工厂类(接口),BeanFacotry 是 Spring 中比较原始的Factory。
    • BeanFactory 无法支持 Spring 的许多插件,如AOP功能、Web应用等。ApplicationContext 接口由BeanFactory接口派生而来,提供了国际化访问、事件传播等多个功能。
    • BeanFactory 是 IOC 容器的核心,负责生产和管理 Bean 对象。
  • FactoryBean
    • FactoryBean 以 Bean 结尾,表示它是一个Bean。
    • FactoryBean 是工厂类接口,用户可以通过实现该接口定制实例化 Bean 的逻辑。FactoryBean 接口对于 Spring 框架来说占用重要的地位,Spring自身就提供了70多个FactoryBean的实现。
    • 当在IOC容器中的Bean实现了 FactoryBean 后,通过getBean(String BeanName)获取到的 Bean 对象并不是 FactoryBean 的实现类对象,而是这个实现类中的 getObject() 方法返回的对象。要想获取FactoryBean的实现类,就要 getBean(String &BeanName),在BeanName之前加上 &

循环依赖

​ 从字面上来理解就是A依赖B的同时B也依赖了A,例如

自动化配置

​ 例如我有一个 UserService,我希望在自动化扫描时,这个类能够自动注册到 Spring 容器中去,那么可以给该类添加一个 @Service,作为一个标记。

​ 和 @Service 注解功能类似的注解,一共有四个:

  • @Component

  • @Repository

  • @Service

  • @Controller

    ​ 这四个中,另外三个都是基于 @Component 做出来的,而且从目前的源码来看,功能也是一致的,那么为什么要搞三个呢?主要是为了在不同的类上面添加时方便。

  • 在 Service 层上,添加注解时,使用 @Service

  • 在 Dao 层,添加注解时,使用 @Repository

  • 在 Controller 层,添加注解时,使用 @Controller

  • 在其他组件上添加注解时,使用 @Component

    ​ 添加完成后,自动化扫描有两种方式,一种就是通过 Java 代码配置自动化扫描,另一种则是通过 xml 文件来配置自动化扫描。

Java 代码配置自动扫描

​ 在项目启动中加载配置类,在配置类中,通过 @ComponentScan 注解指定要扫描的包(如果不指定,默认情况下扫描的是配置类所在的包下载的 Bean 以及配置类所在的包下的子包下的类)

XML 配置自动化扫描

<context:component-scan base-package="org.javaboy.javaconfig"/>

​ 上面这行配置表示扫描 org.javaboy.javaconfig 下的所有 Bean。当然也可以按照类来扫描。

Bean的生命周期和作用域

​ 这两个问题也是面试中常客

Bean的生命周期

​ Spring IOC 初始化跟销毁 Bean 的过程大致分为Bean定义、Bean初始化、Bean的生存期 跟 Bean的销毁4个部分。流程图如下:

浓缩一下:

Bean的生命周期,从Spring容器的创建开始,到Spring容器销毁结束。

  1. ​ 实例化Bean对象
  2. ​ 装配:填充属性
  3. ​ 回调:(可选,如果实现了Aware系列的接口,则会调用回调函数)
  4. ​ 调用预初始化方法(可选,如果实现了BeanPost-Processor的预初始化方法)
  5. ​ 初始化(init-method)
  6. ​ 调用预初始化后置方法(如果实现了BeanPost-Processor的初始化后方法)
  7. ​ 使用bean
  8. ​ 容器关闭
  9. ​ 如果实现了DisposableBean接口,则调用该方法的destory()方法。
  10. ​ 调用自定义的destory方法。

Bean的作用域

​ 在 XML 配置中注册的 Bean,或者用 Java 配置注册的 Bean,如果我多次获取,获取到的对象是否是同一个?

​ 答案是是,因为Spring中Bean默认是单例的,所以多次获取的Bean都是同一个。这里就涉及到Bean的作用域的知识点,

​ 四种常见的 Spring Bean 的作用域:

  • singleton : 唯一 bean 实例,Spring 中的 bean 默认都是单例的。

  • prototype : 每次请求都会创建一个新的 bean 实例。

  • request : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效。

  • session : 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。

    怎么更改作用域?

    xml中:

    <bean class="org.javaboy.User" id="user" scope="prototype" />

    注解:

    @Repository
    @Scope("prototype")
    public class UserDao {
    public String hello() {
    return "userdao";
    }
    }

单点突破:Spring(上)的更多相关文章

  1. spring上传文件

    在使用spring上传文件的时候,使用的文件接收参数类型为 org.springframework.web.multipart.MultipartFile 如果该参数没有指定@RequestParam ...

  2. spring 上传 下載文件

    1,spring配置文件添加文件上传配置 <!-- 上传文件 --> <bean id="multipartResolver" class="org.s ...

  3. Spring上传文件,图片,以及常见的问题

    1. 在工程依赖库下添加文件上传jar包 commons-fileupload-1.2.2.jar commons-io-2.4.jar 2.在springMVC配置文件中配置视图解析multipar ...

  4. spring 上传文件文件的一个例子,

    /** * 类名称:UploadTest 类描述:创建人:zhang 创建时间:2015年3月13日 下午4:20:57 修改人:zhang * 修改时间:2015年3月13日 下午4:20:57 修 ...

  5. spring boot:spring security+oauth2+sso+jwt实现单点登录(spring boot 2.3.3)

    一,sso的用途 ? 1,如果有多个应用系统,用户只需要登录一次就可以访问所有相互信任的应用系统. 不需要每次输入用户名称和用户密码, 也不需要创建并记忆多套用户名称和用户密码. 2,系统管理员只需维 ...

  6. Spring 上传文件

    最近碰到一个上传文件的需求,其实之前也做过但是都是search->copy 没有细究过,这次纯手工. 先看一下需要依赖的包: <dependency> <groupId> ...

  7. 机器学习模型从windows下 spring上传到预发布会导致模型不可加载

    1.通过上传到redis,程序通过redis拉取模型,解决问题. 2.问题原因初步思考为windows下模型文件上传到 linux导致,待继续跟进查找.

  8. Spring上传报错413

    SpringMVC上传文件报错413 笔者今天工作时,运维的同事反馈我们上线不久的项目上传文件过大时,总是提示上传失败. 场景重现一下,发现报错信息显示413:Request entity too l ...

  9. 单点突破:Set

    HashSet HashSet存放的是散列值,它是按照元素的散列值来存取元素的. 元素的散列值通过hashCode方法计算 HashSet通过判断两个元素的Hash值是否相等,如果相等就会用equal ...

随机推荐

  1. Aircrack-ng破解无线WIFI密码

    首先,如果kali是装在虚拟机里面的话,是不能用物理机的无线网卡的.所以,如果我们要想进行无线破解,需要外接一个无线网卡设备,并且该设备要支持 monitor 监听模式 iwconfig :系统配置无 ...

  2. C#-CMD

    private static string InvokeCmd(string cmdArgs) { string Tstr = ""; Process p = new Proces ...

  3. android Javah生成JNI头文件

    项目要用到c语言库,因此来学习下jni 首先是在cmd中使用javah,出现了javah不是内部或外部命令的错误提示,javah是jdk自带的工具,提示说明在系统环境变量中没有jdk的路径,或者配置错 ...

  4. 【maven】You may use+to add a project ro to let the plugin find all pom.xml files...

    错误显示 解决方法 点击pom.xml,再Add as Maven Project 如果还不能解决,点击idea的log 复制报错(技巧:可以先将idea.log删除,比较好定位) Caused by ...

  5. SpringBoot端口和上下文路径

    可以通过修改application.properties,修改访问的端口号和上下文路径 spring.mvc.view.prefix=/WEB-INF/jsp/ spring.mvc.view.suf ...

  6. Django(5)django配置信息

    前言 Django的配置文件settings.py用于配置整个网站的环境和功能,核心配置必须有项目路径.密钥配置.域名访问权限.App列表.中间件.资源文件.模板配置.数据库的连接方式 基本配置信息 ...

  7. .Net 中两分钟集成敏感词组件

    现如今大部分服务都会有用户输入,为了服务的正常运行,很多时候不得不针对输入进行敏感词的检测.替换.如果人工做这样的工作,不仅效率低,成本也高.所以,先让代码去处理输入,成为了经济方便的途径.水弟在这里 ...

  8. SE_WorkX_提问回顾与个人总结

    项目 内容 课程:北航-2020-春-软件工程 博客园班级博客 要求:正所谓"实践是认识的来源.目的.动力以及检验认识真理性的唯一标准",在经历了一个学期的学习和实践后,请大家写一 ...

  9. Spring Cloud Gateway 之获取请求体(Request Body)的几种方式

    Spring Cloud Gateway 获取请求体 一.直接在全局拦截器中获取,伪代码如下 private String resolveBodyFromRequest(ServerHttpReque ...

  10. Shell脚本 /dev/null 2>&1详解

    Shell脚本---- /dev/null 2>&1详解   1.可以将/dev/null看作"黑洞". 它非常等价于一个只写文件. 所有写入它的内容都会永远丢失. ...