学习spring Bean的生命周期

完整项目结构

├── pom.xml
└── src/├── main/│   ├── java/│   │   └── com/│   │       └── zhang/│   │           ├── bean/│   │           │   ├── Address.java│   │           │   ├── MyBeanPostProcessor.java│   │           │   └── Person.java│   │           └── factory/│   │               ├── MyFactoryBean.java│   │               ├── PersonInstanceFactory.java│   │               └── PersonStaticFactory.java│   └── resources/│   │  ├── db.properties│       └── ioc.xml└── test/└── java/└── MyTest.java

项目主要内容和学习方面

这个项目是一个Spring框架的学习练习demo,主要学习了以下几个方面:

  1. Spring IoC容器基础

    • 通过ClassPathXmlApplicationContext加载配置文件并创建IoC容器
    • 学习了从容器中获取Bean的多种方式(根据id、根据类型)
  2. Bean的作用域

    • 测试了Spring中Bean的单例模式
  3. 依赖注入

    • 通过配置文件实现PersonAddress等实体类的依赖注入
  4. Bean的生命周期

    • 实现了MyBeanPostProcessor类,学习Bean的后置处理器机制
  5. 工厂模式

    • 学习了多种工厂创建Bean的方式:
      • 静态工厂(PersonStaticFactory
      • 实例工厂(PersonInstanceFactory
      • FactoryBean(MyFactoryBean
  6. 数据源配置

    • 项目中包含了Druid数据源的配置测试

主要Java类说明

  • 实体类Person.java(人员实体)、Address.java(地址实体)
  • 后置处理器MyBeanPostProcessor.java(Bean生命周期处理器)
  • 工厂类PersonStaticFactory.java(静态工厂)、PersonInstanceFactory.java(实例工厂)、MyFactoryBean.java(FactoryBean实现)
  • 测试类MyTest.java(用于测试Spring的各种功能)

项目依赖包括Spring框架的核心模块、MySQL驱动和Druid数据源。

代码

bean

public class Address {private String province;private String city;private String town;public Address() {System.out.println("Address被创建");}public String getProvince() {return province;}public void setProvince(String province) {this.province = province;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}public String getTown() {return town;}public void setTown(String town) {this.town = town;}@Overridepublic String toString() {return "Address{" +"province='" + province + '\'' +", city='" + city + '\'' +", town='" + town + '\'' +'}';}
}import java.util.*;public class Person {private Integer id;private String name;private Integer age;private String gender;
//    private Date date;private String[] hobbies;private Address address;private List<Address> lists;
private Set<String> sets;
private Map<String,Object> maps;
private Properties properties;public void init(){
//    先写n行代码完成初始化功能System.out.println("person对象初始化完成");
}
public void destroy(){System.out.println("person对象被销毁");
}public Person() {System.out.println("person被创建");}public Person(Address address) {this.address = address;}public Person(Integer id, String name, Address address) {this.id = id;this.name = name;this.address = address;}//    public Person(Integer id, String name, Integer age, String gender, Date date) {
//        this.id = id;
//        this.name = name;
//        this.age = age;
//        this.gender = gender;
//        this.date = date;
//    }public Person(Integer id, String name, Integer age, String gender) {this.id = id;this.name = name;this.age = age;this.gender = gender;}public Person(Integer id, String name, String gender) {this.id = id;this.name = name;this.gender = gender;System.out.println("gender... ...");}public Person(Integer id, String name, Integer age) {this.id = id;this.name = name;this.age = age;System.out.println("age... ...");}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;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public String[] getHobbies() {return hobbies;}public void setHobbies(String[] hobbies) {this.hobbies = hobbies;}public Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}public List<Address> getLists() {return lists;}public void setLists(List<Address> lists) {this.lists = lists;}public Set<String> getSets() {return sets;}public void setSets(Set<String> sets) {this.sets = sets;}public Map<String, Object> getMaps() {return maps;}public void setMaps(Map<String, Object> maps) {this.maps = maps;}public Properties getProperties() {return properties;}public void setProperties(Properties properties) {this.properties = properties;}
//    public Date getDate() {
//        return date;
//    }
//
//    public void setDate(Date date) {
//        this.date = date;
//    }@Overridepublic String toString() {return "Person{" +"id=" + id +", name='" + name + '\'' +", age=" + age +", gender='" + gender + '\'' +", hobbies=" + Arrays.toString(hobbies) +", address=" + address +", lists=" + lists +", sets=" + sets +", maps=" + maps +", properties=" + properties +'}';}}
初始化的时候做事情
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;public class MyBeanPostProcessor implements BeanPostProcessor {
//    在每一个对象的初始化方法之前执行public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("postProcessBeforeInitialization:"+beanName);return bean;}/*** 在每一个对象的初始化方法之后执行* @param bean 表示创建的具体对象* @param beanName  表示bean的id属性* @return* @throws BeansException*/public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof Person){System.out.println();}else {System.out.println();}System.out.println("postProcessAfterInitialization:"+beanName);return bean;}
}
工厂

单例模式


import com.zhang.bean.Person;
import org.springframework.beans.factory.FactoryBean;
/*此方式是spring创建bean方式的一种补充,用户可以按照需求创建对象,
* 创建的对象交由spring IOC容器来进行管理,无论是否是单例,都是在
* 用到的时候才会创建该对象,不用该对象不会创建*/
public class MyFactoryBean implements FactoryBean<Person> {/*返回获取的bean*/public Person getObject() throws Exception {Person person=new Person();person.setId(3);person.setName("王五");return person;}
/*获取返回bean的类型*/public Class<?> getObjectType() {return Person.class;}
/*判断当前bean是否是单例的*/public boolean isSingleton() {return true;}
}import com.zhang.bean.Person;
//*实例工厂类*/
public class PersonInstanceFactory {public  Person getInstance(String name){Person person = new Person();person.setId(2);person.setName(name);person.setAge(22);return person;}}import com.zhang.bean.Person;
/*静态工厂类*/
public class PersonStaticFactory {public static Person getInstance(String name){Person person = new Person();person.setId(1);person.setName(name);person.setAge(11);return person;}
}
测试
import com.alibaba.druid.pool.DruidDataSource;
import com.zhang.bean.Address;
import com.zhang.bean.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class MyTest {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("ioc.xml");/*根据bean标签的id来获取对象*/
//        Person person = context.getBean("person", Person.class);
//        Person person1 = context.getBean("person", Person.class);
//        System.out.println(person==person1);
//        System.out.println(person);/*根据bean的类型来获取对象* 注意:当通过类型进行获取的时候,如果存在两个相同类型对象,将无法完成获取工作* */
//        Person bean = context.getBean(Person.class);
//        System.out.println(bean);/*当需要从容器中获取对象的时候,最好要保留无参构造方法,因为底层的实现是反射*Object obj = clazz.newInstance() ;默认调用无参的构造方法,此方法已经被弃用Object obj = clazz.newConstructorInstance();*/
//        Person bean = context.getBean("person6",Person.class);
//        System.out.println(bean);
//        Address address2 = context.getBean("address2", Address.class);
//        System.out.println(address2);
//        Person son = context.getBean("son",Person.class);
//        System.out.println(son);
//        Person parent = context.getBean("parent",Person.class);
//        System.out.println(parent);
//        Person person2 = context.getBean("person2", Person.class);
//        Person person3 = context.getBean("person2", Person.class);
//        System.out.println(person2==person3);
//        Person person = context.getBean("person", Person.class);
//        System.out.println(person);
//        Person person2 = context.getBean("person2", Person.class);
//        System.out.println(person2);
//        Person myFactoryBean = context.getBean("myFactoryBean", Person.class);
//        System.out.println(myFactoryBean);Person person = context.getBean("person2", Person.class);System.out.println(person);
// 关闭ioc容器
//        ((ClassPathXmlApplicationContext) context).close();
//        DruidDataSource dataSource = context.getBean("dataSource2", DruidDataSource.class);
//        System.out.println(dataSource);
//        System.out.println(dataSource.getCloseCount());}
}
配置文件
<?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:p="http://www.springframework.org/schema/p"xmlns:cont="http://www.springframework.org/schema/context"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--7到149一起注释掉--><!--    &lt;!&ndash;在进行框架配置的时候,可以使用xml文件,也可以使用注解的方式--><!--    很多同学觉得xml的方式比较麻烦,但是xml的配置方式还是要学习的,因为在项目开发过程中,--><!--    很多情况下是xml和注解一起工作,而且xml配置的方式比较完整&ndash;&gt;--><!--    &lt;!&ndash;<bean id="person" class="com.zhang.bean.Person" scope="prototype">&ndash;&gt;--><!--    &lt;!&ndash;    scope="prototype"改为分单例&ndash;&gt;--><!--    <bean id="person" class="com.zhang.bean.Person">--><!--        &lt;!&ndash;根据属性值设置的时候,name的名称取决于set方法后面的参数首字符小写的名称&ndash;&gt;--><!--        <property name="id" value="1"></property>--><!--        <property name="name" value="zhangsan"></property>--><!--        <property name="age" value="20"></property>--><!--        <property name="gender" value="男"></property>--><!--        &lt;!&ndash;     <property name="date" ref="now"></property>&ndash;&gt;--><!--        &lt;!&ndash;        <property name="date" value="2020/02/06"></property>&ndash;&gt;--><!--    </bean>--><!--    <bean id="now" class="java.util.Date">--><!--    </bean>--><!--    &lt;!&ndash;使用构造器方法赋值的时候,参数的name属性是由什么来决定的?由构造方法的参数名称决定的--><!--    name:表示参数列表的名称--><!--    value:表示实际的具体值--><!--    type:表示值的类型--><!--    index:表示值的下标,从0开始--><!--    &ndash;&gt;--><!--    <bean id="person2" class="com.zhang.bean.Person">--><!--        <constructor-arg name="id" value="2"></constructor-arg>--><!--        <constructor-arg name="name" value="lisi"></constructor-arg>--><!--        <constructor-arg name="age" value="20"></constructor-arg>--><!--        <constructor-arg name="gender" value="男"></constructor-arg>--><!--    </bean>--><!--    &lt;!&ndash;当通过构造器方法赋值的时候,可以把name属性省略不写,但是要注意必须要保证参数值跟构造器的参数列表的顺序一致,--><!--    如果非要不一致的话,可以通过index的下标方式来标注,从0开始 &ndash;&gt;--><!--    <bean id="person3" class="com.zhang.bean.Person">--><!--        <constructor-arg value="2" index="2"></constructor-arg>--><!--        <constructor-arg value="lisi"></constructor-arg>--><!--        <constructor-arg value="22" index="0"></constructor-arg>--><!--        <constructor-arg value="男"></constructor-arg>--><!--    </bean>--><!--    &lt;!&ndash;当有多个相同参数的构造方法存在的时候,默认情况下是覆盖的过程,后面的构造方法会覆盖前面的构造方法,--><!--    如果非要赋值给另外一个构造方法的话,可以使用type的参数来进行指定&ndash;&gt;--><!--    <bean id="person4" class="com.zhang.bean.Person">--><!--        <constructor-arg value="4"></constructor-arg>--><!--        <constructor-arg value="wangwu"></constructor-arg>--><!--        <constructor-arg value="22" type="java.lang.Integer"></constructor-arg>--><!--    </bean>--><!--    &lt;!&ndash;总结:--><!--    在日常工作中,一般都是用name, value的方式,很少有人去使用index或者type的方式,但是要注意各种情况出现的问题--><!--    &ndash;&gt;--><!--    &lt;!&ndash; 使用p命名空间来给属性命名--><!--    &ndash;&gt;--><!--    <bean id="person5" class="com.zhang.bean.Person" p:id="5" p:name="zhaoliu" p:age="25" p:gender="女"></bean>--><!--    &lt;!&ndash;    给复杂类型进行赋值&ndash;&gt;--><!--    <bean id="person6" class="com.zhang.bean.Person">--><!--        <property name="id" value="6"></property>--><!--        <property name="name" value="zhangsan6"></property>--><!--        <property name="age" value="20"></property>--><!--        <property name="gender" value="男"></property>--><!--        &lt;!&ndash; 给数组赋值 使用array标签&ndash;&gt;--><!--        &lt;!&ndash; <property name="hobbies" value="book,girl,movie"></property>&ndash;&gt;--><!--        <property name="hobbies">--><!--            <array>--><!--                <value>book</value>--><!--                <value>girl</value>--><!--                <value>movie</value>--><!--            </array>--><!--        </property>--><!--        &lt;!&ndash;        引用类型赋值,可以使用ref引入外部bean&ndash;&gt;--><!--        <property name="address" ref="address"></property>--><!--        &lt;!&ndash; 给list 赋值&ndash;&gt;--><!--        &lt;!&ndash;  <property name="lists" value="1,2,3"></property>&ndash;&gt;--><!--        <property name="lists">--><!--            <list>--><!--                &lt;!&ndash;使用内部bean,无法从IOC容器中直接获取对象的值&ndash;&gt;--><!--                <bean id="address2" class="com.zhang.bean.Address">--><!--                    <property name="province" value="北京"></property>--><!--                </bean>--><!--                <bean class="com.zhang.bean.Address">--><!--                    <property name="province" value="上海"></property>--><!--                </bean>--><!--                &lt;!&ndash;使用外部bean,可以随意从IOC容器获取对象的值&ndash;&gt;--><!--                <ref bean="address"></ref>--><!--            </list>--><!--        </property>--><!--        <property name="sets">--><!--            <set>--><!--                <value>zhangsan</value>--><!--                <value>zhangsan</value>--><!--                <value>wangwu</value>--><!--            </set>--><!--        </property>--><!--        <property name="maps">--><!--            <map>--><!--                <entry key="a" value="aaa"></entry>--><!--                <entry key="address" value-ref="address"></entry>--><!--                <entry key="address2">--><!--                    <bean class="com.zhang.bean.Address">--><!--                        <property name="province" value="广东"></property>--><!--                    </bean>--><!--                </entry>--><!--                <entry>--><!--                    <key>--><!--                        <value>hehe</value>--><!--                    </key>--><!--                    <value>haha</value>--><!--                </entry>--><!--                <entry key="list">--><!--                    <list>--><!--                        <value>11</value>--><!--                        <value>22</value>--><!--                    </list>--><!--                </entry>--><!--            </map>--><!--        </property>--><!--        <property name="properties">--><!--            <props >--><!--                <prop key="111">aaa</prop>--><!--                <prop key="222">bbb</prop>--><!--            </props>--><!--        </property>--><!--    </bean>--><!--    <bean id="address" class="com.zhang.bean.Address">--><!--        <property name="province" value="河北省"></property>--><!--        <property name="city" value="邯郸"></property>--><!--        <property name="town" value="武安"></property>--><!--    </bean>--><!--&lt;!&ndash;bean之间的继承关系&ndash;&gt;--><!--&lt;!&ndash;    可以使用abstract标签定义抽象bean,无法进行实例化&ndash;&gt;--><!--    <bean id="parent" class="com.zhang.bean.Person" abstract="false">--><!--    &lt;!&ndash;根据属性值设置的时候,name的名称取决于set方法后面的参数首字符小写的名称&ndash;&gt;--><!--    <property name="id" value="1"></property>--><!--    <property name="name" value="zhangsan"></property>--><!--    <property name="age" value="20"></property>--><!--    <property name="gender" value="男"></property>--><!--    </bean>--><!--&lt;!&ndash;    可以通过parent属性来获取父bean中的某些属性值&ndash;&gt;--><!--<bean id="son" class="com.zhang.bean.Person" parent="parent">--><!--    <property name="name" value="haha"></property>--><!--</bean>--><!-- 创建bean的时候依赖关系当bean对象被创建的时候,是按照xml配置文件定义的顺序创建的,谁在前谁就先被创建,如果需要干扰创建的顺序,可以使用 depends-on属性一般在实际工作中不必在意bean创建的顺序,无论依赖的对象在创建完成之后都会进行赋值操作--><!--    <bean id="person" class="com.zhang.bean.Person" depends-on="address">  </bean>--><!--    <bean id="address" class="com.zhang.bean.Address" ></bean>--><!-- 设置bean对象的生命周期通过scope属性可以指定当前bean的作用域singleton:单例模式、从ioc容器中获取的都是同一个对象,默认的作用域prototype:多例模式、从IOC容器中获取的对象每次都是新创建的在spring4.x的版本中还包括另外两个作用域:request:每次发送请求都会有一个新的对象session:每次会话都会由一个新的对象几乎不用,从来没有用过,因此在5版本的时候就被淘汰了--><!--    注意:如果是单例作用域的话,每次在创建ioc容器完成之前此对象就已经创建完成如果是prototype作用域的话,每次是在需要用到此对象的时候才会创建--><!--    <bean id="person2" class="com.zhang.bean.Person" scope="singleton"></bean>--><!--利用工厂方式创建bean--><!--静态工厂类名.静态方法()--><!--    <bean id="person" class="com.zhang.factory.PersonStaticFactory" factory-method="getInstance">--><!--        <constructor-arg value="zhangsan"></constructor-arg>--><!--    </bean>--><!--实例工厂:先创建工厂实例,然后调用工厂实例的方法factory-bean:表示具体工程类的实例factory-method:表示具体工厂实例方法--><!--    <bean id="instanceFactory" class="com.zhang.factory.PersonInstanceFactory"></bean>--><!--    <bean id="person2" class="com.zhang.bean.Person" factory-bean="instanceFactory" factory-method="getInstance">--><!--        <constructor-arg value="lisi"></constructor-arg>--><!--    </bean>--><!--    <bean id="myFactoryBean" class="com.zhang.factory.MyFactoryBean"></bean>--><!-- spring容器在创建对象的时候可以指定具体的初始化和销毁方法init-method:在对象创建完成之后会调用初始化方法destroy-method:在容器关闭的时候会调用销毁方法--><!-- 初始化和销毁的方法跟scope属性也是相关联的如果是singleton的话,初始化和销毁的方法都存在如果是prototype的话,初始化会调用,但是销毁的方法不会调用--><!--    <bean id="person" class="com.zhang.bean.Person" init-method="init" destroy-method="destroy"></bean>--><!--    <bean id="myBeanPostProcessor" class="com.zhang.bean.MyBeanPostProcessor"></bean>--><!--    <bean id="address" class="com.zhang.bean.Address"></bean>--><!--    &lt;!&ndash;spring管理第三方bean&ndash;&gt;-->
<!--    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">-->
<!--        <property name="username" value="root"></property>-->
<!--        <property name="password" value="1234"></property>-->
<!--        <property name="url" value="jdbc:mysql://localhost:3306/exam"></property>-->
<!--        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>-->
<!--    </bean>-->
<!--    &lt;!&ndash;    当需要引入外部的配置文件的时候,需要导入一些context的命名空间&ndash;&gt;--><!--    <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>-->
<!--    &lt;!&ndash;在配置文件编写属性的时候需要注意,-->
<!--    spring容器在进行启动的时候,会读取当前系统的某些环境变量的配置,-->
<!--    当前系统的用户名是用username来表示的,所以最好的方式是添加前缀来做区分&ndash;&gt;-->
<!--    <bean id="dataSource2" class="com.alibaba.druid.pool.DruidDataSource">-->
<!--        <property name="username" value="${jdbc.username}"></property>-->
<!--        <property name="password" value="${jdbc.password}"></property>-->
<!--        <property name="url" value="${url}"></property>-->
<!--        <property name="driverClassName" value="${driverClassName}"></property>-->
<!--    </bean>-->
<!--    <bean id="person" class="com.zhang.bean.Person">-->
<!--        <property name="name" value="${jdbc.username}"></property>-->
<!--    </bean>-->
<!--    spring中的自动装配--><bean id="address" class="com.zhang.bean.Address"><property name="province" value="河北"></property><property name="city" value="邯郸"></property><property name="town" value="武汉"></property></bean>
<!--    <bean id="address2" class="com.zhang.bean.Address">-->
<!--        <property name="province" value="河北2"></property>-->
<!--        <property name="city" value="邯郸2"></property>-->
<!--        <property name="town" value="武汉2"></property>-->
<!--    </bean>-->
<!--    在spring中,可以使用自动装配的功能,spring会把某些bean注入到另外的bean中
可以使用autowire属性来实现自动装配,有一下几种情况
default/no:不装配
byName:按照id进行装配,根据set方法的后面的名称首字母小写决定的,不是参数列表的名称
byType:按照bean的类型来进行装配,但是如果有多个类型,就会报错,不知道选择哪一个具体的类型
constructor:按照构造器进行装配,首先按照类型进行判断,如果有多个类型相同的bean,再按照id进行判断
--><!--    为什么使用bytype的时候会加载环境变量出来
环境变量中存储的就是key:valve会放到那里面,换一种类型就不会了
--><!--    <bean id="person" class="com.zhang.bean.Person" autowire="constructor"></bean>-->
<!--    SpEL表达式语言的使用--><bean id="person2" class="com.zhang.bean.Person">
<!--可以引入bean对象的属性-->
<property name="name" value="#{address.province}"></property>
<!--可以支持运算符的所有操作--><property name="age" value="#{2*3}"></property>
<!--可以使用外部bean--><property name="address" value="#{address}"></property>
<!-- 可以调用静态方法-->
<property name="hobbies" value="#{T(java.util.UUID).randomUUID().toString().substring(0,4)}"></property>
<!--调用非静态方法--><property name="gender" value="#{address.getCity()}"></property></bean>
</beans>

properties

jdbc.username=root
jdbc.password=1234
url=jdbc:mysql://localhost:3306/test
driverClassName=com.mysql.jdbc.Driver
pom.xml
<?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>com.zhang</groupId><artifactId>spring_study02</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.5</version></dependency><!-- https://mvnrepository.com/artifact/com.alibaba/druid --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.6</version></dependency><!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.48</version></dependency></dependencies>
</project>

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

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

相关文章

elasticsearch 7.17.23 使用spring data es实现高亮分页,scroll查询分页查询

一 介绍 1.1 工程结构 1.2 启动elasticsearch服务 1.3 高亮分页 DeepSeek 代码 效果&#xff1a; 1.4 scroll分页 代码 2.效果 后台日志 1.5 完整代码 https://gitee.com/jurf-liu/es-2.17.x-demo.git

onlyoffice整合springboot+vue实现文档在线编辑保存

项目上需要用到在线word、excel文档编辑功能&#xff0c;通过游览器在线打开一个远程的word文档编辑保存&#xff0c;这里记录下整合思路。 onlyoffice简介 ONLYOFFICE 是一款开源的办公套件&#xff0c;提供了一系列在线文档编辑和协作工具&#xff0c;适用于团队和个人使用…

Linux笔记10——shell编程基础-4

补充$#——取参数个数“$n”,有值取值&#xff0c;无值取空字符&#xff0c;一般都会加引号&#xff0c;在某些情况下避免报语法错误一、read接收键盘输入[rootlocalhost ~]# cat demo.sh #!/bin/bash echo -n "请输入你的姓名&#xff1a;" read nameecho "你…

(Redis)过期删除策略

1. 背景Redis 支持为 Key 设置过期时间&#xff08;TTL&#xff09;&#xff0c;让数据在一定时间后自动失效。 例如&#xff1a;SET session:1001 "userA" EX 60 # 60 秒后过期但是问题来了&#xff1a;Key 到期后&#xff0c;Redis 什么时候、如何删除它&#xf…

nodejs 集成mongodb实现增删改查

初始化项目: npm init -y npm install mongoose -save 安装mongoose 插件 mongoose 链接数据库语法&#xff1a; mongodb://[username:password]host1[:poert1],host2[:port2]…/[databsase]?[options…] userame&#xff1a; 用户名 passwrod: 密码 host1:port1,host2:port…

音视频学习(五十八):STAP-A模式

什么是 STAP-A&#xff1f; STAP-A 是一种特殊的 RTP 封装机制&#xff0c;专为 H.264 和 H.265 这类视频编码协议设计。它的核心目的只有一个&#xff1a;将多个小的 NALU&#xff08;网络抽象层单元&#xff09;打包进一个 RTP 包中&#xff0c;以此来减少网络开销&#xff0…

管理型交换机通过VLAN划分实现不同IP跨网段通信配置方法

管理型交换机应用场景丰富&#xff0c;如果要实现不同IP跨网段通信(比如172.22.106.X和192.168.100.X实现通信)&#xff0c;通过VLAN划分是可以满足&#xff0c;下面分享基于弱三层交换机RTL9301方案核心模块SW-24G4F-301EM配置方法&#xff01; 1. 一般结合交换机的应用场景&a…

什么是高防服务器?如何进行防御?

高防服务器是指能为用户提供防御网络攻击&#xff0c;是主要针对DDOS等流量型攻击能力的服务器&#xff0c;通过部署专业的硬件设备与软件系统&#xff0c;具备高带宽、大流量清洗能力&#xff0c;能有效抵御各类恶意流量冲击&#xff0c;确保服务器稳定运行&#xff0c;保障网…

SW - 增加导出STL数据中的三角面数,增加别人逆向建模的难度

文章目录SW - 增加导出STL数据中的三角面数&#xff0c;增加别人逆向建模的难度概述笔记SW版本导出时&#xff0c;选择STL的导出选项默认导出(精细)导出粗糙自定义导出 - 将误差和角度改为最大自定义导出 - 将误差,角度,三角面数改为最大备注这几天的感想关于我不参考人家零件&…

四十一、【高级特性篇】API 文档驱动:OpenAPI/Swagger 一键导入测试用例

四十一、【高级特性篇】API 文档驱动:OpenAPI/Swagger 一键导入测试用例 前言 准备工作 第一部分:后端实现 - OpenAPI 解析与批量创建 API 1. 创建 OpenAPI 解析服务 2. 创建批量用例导入 API 3. 注册新 API 路由 第二部分:前端实现 - OpenAPI 导入界面 1. 更新 `api/testca…

K8S-Service资源对象

一、概述在kubernetes中&#xff0c;pod是应用程序的载体&#xff0c;我们可以通过pod的ip来访问应用程序&#xff0c;但是pod的ip地址不是固定的&#xff0c;这也就意味着不方便直接采用pod的ip对服务进行访问。为了解决这个问题&#xff0c;kubernetes提供了Service资源&…

【STM32】CubeMX(十三):RT-THREAD

本篇博客描述的是 RT-Thread STM32 CubeMX 的使用方法。本文也为大家提供了基于 STM32 使用 CubeMX 添加 RT-Thread 并创建闪烁 LED 任务 的操作流程。 便于您更好的理解。 一、RT-Thread 是什么&#xff1f; RT-Thread 是一个开源、轻量级的实时操作系统&#xff0c;适用于…

基于Ubuntu22.04系统PaddleX和PaddleClas训练推理MMAFEDB人脸表情识别数据集(详细教程)

目录 基于Ubuntu22.04系统PaddleX和PaddleClas训练推理MMAFEDB人脸表情识别数据集(详细教程) 超实用的Paddle图像分类训练推理教程&#xff0c;助力深度学习研究&#xff01; 1、环境准备(重要⭐⭐⭐) 构建虚拟环境 安装PaddlePaddle 安装PaddleX 安装PaddleClas插件 2…

Mistral AI音频大模型Voxtral解读

1. 引言 传统的语音处理系统(如OpenAI的Whisper)在ASR任务上取得了巨大成功,能将语音高精度地转换为文本。但这只是第一步。真正的“语音理解”意味着: 内容推理:不仅知道说了什么,还能理解话语背后的含义、情感和意图。 长篇摘要:能够听完一段长达数十分钟的播客或会议…

使用Docker+WordPress部署个人博客

一、通过docker compose 自动一键部署WordPress 1. 准备工作 安装 Docker 和 Docker Compose确保服务器有公网 IP&#xff08;如果需要外部访问&#xff09;域名&#xff08;可选&#xff0c;用于绑定网站&#xff09; 2. 创建 Docker Compose 配置文件 创建一个docker-compose…

http与https配置

Web 服务详解&#xff1a;HTTP 与 HTTPS 配置 一、HTTP 服务概述 HTTP&#xff08;Hypertext Transfer Protocol&#xff0c;超文本传输协议&#xff09;是用于在网络上传输网页数据的基础协议&#xff0c;默认使用80 端口&#xff0c;以明文形式传输数据。常见的 HTTP 服务软件…

Python爬虫实战:研究amazon-scrapy,构建亚马逊电商数据采集和分析系统

1 引言 1.1 研究背景 电子商务的高速发展使电商平台成为数据价值的核心载体。亚马逊作为全球领先的电商生态,截至 2024 年第二季度,其平台商品总量突破 1.5 亿,日均活跃用户超 3 亿,每日产生 PB 级的交易数据与用户行为记录。这些数据包含商品特征(价格、规格、品牌)、…

基于ERNIE 4.5的多智能体协作的自动化视频舆情分析报告生成器

多智能体协作的自动化视频舆情分析报告生成器 1. 项目的意义与价值 从“非结构化视频”中挖掘“结构化洞察”的通用挑战 在当今的数字生态中&#xff0c;视频已成为信息传播、知识分享和消费者意见表达的核心媒介。从企业内部的会议录屏、技术培训&#xff0c;到外部的市场宣传…

Java全栈开发面试实录:从基础到实战的深度解析

Java全栈开发面试实录&#xff1a;从基础到实战的深度解析 面试官与应聘者的对话记录 第一轮&#xff1a;基础问题与项目背景 面试官&#xff08;中年男性&#xff0c;穿着整洁&#xff09;&#xff1a; 你好&#xff0c;欢迎来到我们公司。我是今天的面试官&#xff0c;可以先…

如何清除webview138、139版本软键盘占用的区域

好的&#xff0c;这个问题非常具体且关键。在 Android System WebView 的 138 和 139 版本&#xff08;基于 Chromium 113&#xff09;的上下文中&#xff0c;“清除软键盘占用的区域”通常意味着&#xff1a;在软键盘收起后&#xff0c;WebView 的布局或视口没有正确恢复&…