Spring ---IOC容器和DI的具体应用

spring Framework详解

spring Framework介绍

Spring Framework(Spring框架)是Spring生态系统的核心,它是一个开源的Java应用程序框架,由SpringSource公司开发,旨在简化企业级应用程序的开发。Spring Framework提供了依赖注入(DI)、面向切面编程(AOP)、声明式事务管理(TX)等功能,以解决企业级开发中的常见问题。它不仅使开发过程更加高效和便捷,还被广泛应用于Java企业开发领域。Spring全家桶中的其他框架,如Spring Boot、Spring Data、Spring Security等,都是基于Spring Framework构建的,依赖其核心功能来实现各自的扩展和增强。

spring Framework主要功能模块

功能模块 功能介绍
Core Container 核心容器,在 Spring 环境下使用任何功能都必须基于 IOC 容器。
AOP&Aspects 面向切面编程
TX 声明式事务管理。
Spring MVC 提供了面向Web应用程序的集成功能。

IOC容器和核心概念

  • IoC容器

    Spring IoC 容器,负责实例化、配置和组装 bean(组件)核心容器。容器通过读取配置元数据来获取有关要实例化、配置和组装组件的指令。

  • IoC(Inversion of Control)控制反转

    IoC 主要是针对对象的创建和调用控制而言的,也就是说,当应用程序需要使用一个对象时,不再是应用程序直接创建该对象,而是由 IoC 容器来创建和管理,即控制权由应用程序转移到 IoC 容器中,也就是"反转"了控制权。这种方式基本上是通过依赖查找的方式来实现的,即 IoC 容器维护着构成应用程序的对象,并负责创建这些对象。

  • DI (Dependency Injection) 依赖注入

    DI 是指在组件之间传递依赖关系的过程中,将依赖关系在容器内部进行处理,这样就不必在应用程序代码中硬编码对象之间的依赖关系,实现了对象之间的解耦合。在 Spring 中,DI 是通过 XML 配置文件或注解的方式实现的。它提供了三种形式的依赖注入:构造函数注入、Setter 方法注入和接口注入。

Spring框架提供了多种配置方式:XML配置方式、注解方式和Java配置类方式

  1. XML配置方式:是Spring框架最早的配置方式之一,通过在XML文件中定义Bean及其依赖关系、Bean的作用域等信息,让Spring IoC容器来管理Bean之间的依赖关系。该方式从Spring框架的第一版开始提供支持。
  2. 注解方式:从Spring 2.5版本开始提供支持,可以通过在Bean类上使用注解来代替XML配置文件中的配置信息。通过在Bean类上加上相应的注解(如@Component, @Service, @Autowired等),将Bean注册到Spring IoC容器中,这样Spring IoC容器就可以管理这些Bean之间的依赖关系。
  3. Java配置类方式:从Spring 3.0版本开始提供支持,通过Java类来定义Bean、Bean之间的依赖关系和配置信息,从而代替XML配置文件的方式。Java配置类是一种使用Java编写配置信息的方式,通过@Configuration、@Bean等注解来实现Bean和依赖关系的配置。

基于XML方式整合三层框架

  1. 准备数据库
xml 复制代码
create database studb;

use studb;

CREATE TABLE students (
  id INT PRIMARY KEY,
  name VARCHAR(50) NOT NULL,
  gender VARCHAR(10) NOT NULL,
  age INT,
  class VARCHAR(50)
);

INSERT INTO students (id, name, gender, age, class)
VALUES
  (1, '张三', '男', 20, '高中一班'),
  (2, '李四', '男', 19, '高中二班'),
  (3, '王五', '女', 18, '高中一班'),
  (4, '赵六', '女', 20, '高中三班'),
  (5, '刘七', '男', 19, '高中二班'),
  (6, '陈八', '女', 18, '高中一班'),
  (7, '杨九', '男', 20, '高中三班'),
  (8, '吴十', '男', 19, '高中二班');

编写数据库连接的信息

xml 复制代码
nie.url=jdbc:mysql://localhost:3306/studb
nie.Driver=com.mysql.cj.jdbc.Driver
nie.username=root
nie.password=123456
  1. 导入依赖
java 复制代码
<dependencies>
      <!--spring context依赖-->
      <!--当你引入SpringContext依赖之后,表示将Spring的基础依赖引入了-->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>6.0.6</version>
      </dependency>

      <!-- 数据库驱动和连接池-->
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.25</version>
      </dependency>

      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid</artifactId>
          <version>1.2.8</version>
      </dependency>

      <!-- spring-jdbc -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>6.0.6</version>
      </dependency>

</dependencies> 
  1. 准备实体类
java 复制代码
package com.nie.pojo;

public class Student {
    private int id;
    private String name;
    private String gender;
    private int age;
    private String classes;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getClasses() {
        return classes;
    }

    public void setClasses(String classes) {
        this.classes = classes;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", age=" + age +
                ", classes='" + classes + '\'' +
                '}';
    }

}
  1. 业务层
java 复制代码
package com.nie.Services;

import com.nie.pojo.Student;

import java.util.List;

public interface StudentService {

    List<Student> QU();
}
java 复制代码
package com.nie.Services;

import com.nie.dao.StudentDao;
import com.nie.pojo.Student;

import java.util.List;

public class StudentServiceIml implements  StudentService{

    private StudentDao studentDao;

    public void setStudentDao(StudentDao studentDao) {
        this.studentDao = studentDao;
    }

    @Override
    public List<Student> QU() {
        List<Student> students = studentDao.queryAll();

        System.out.println(students);

        return students;
    }
}
  1. 持久层
java 复制代码
package com.nie.dao;

import com.nie.pojo.Student;

import java.util.List;

public interface StudentDao {
    List<Student> queryAll();
}
java 复制代码
package com.nie.dao;

import com.nie.pojo.Student;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;

public class StudentDaoIml implements  StudentDao{


    private JdbcTemplate jdbcTemplate;

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public List<Student> queryAll() {

        String sql ="select id,name,gender,age,class as classes  from students";

        List<Student> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Student.class));

        return query;
    }
}
  1. 表述层
java 复制代码
package com.nie.Controller;

import com.nie.Services.StudentService;
import com.nie.pojo.Student;

import java.util.List;

public class StudentController {
    private StudentService studentService;

    public void setStudentService(StudentService studentService) {
        this.studentService = studentService;
    }

    public  void queryALL(){
        List<Student> qu = studentService.QU();
        System.out.println(qu);
    }
}
  1. 三层架构的IOC配置
java 复制代码
<?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:context="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">


    <!-- 导入外部属性文件 -->
    <context:property-placeholder location="classpath:jdbc.properties" />

    <!-- 配置数据源 -->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${atguigu.url}"/>
        <property name="driverClassName" value="${atguigu.driver}"/>
        <property name="username" value="${atguigu.username}"/>
        <property name="password" value="${atguigu.password}"/>
    </bean>

    <!-- 配置 JdbcTemplate -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!-- 装配数据源 -->
        <property name="dataSource" ref="druidDataSource"/>
    </bean>


    <bean id="studentDao" class="com.atguigu.dao.impl.StudentDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate" />
    </bean>

    <bean id="studentService" class="com.atguigu.service.impl.StudentServiceImpl">
        <property name="studentDao" ref="studentDao" />
    </bean>

    <bean id="studentController" class="com.atguigu.controller.StudentController">
        <property name="studentService" ref="studentService" />
    </bean>

</beans>
  1. 测试代码
java 复制代码
import com.nie.Controller.StudentController;
import com.nie.pojo.Student;
import org.junit.jupiter.api.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

import java.util.List;

public class Test2 {

    @Test
    public void queryall(){
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("springn-03.xml");
        StudentController bean = classPathXmlApplicationContext.getBean(StudentController.class);
        bean.queryALL();

    }
}

基于XML IOC方式总结

  1. 注入的属性必须添加setter方法、代码结构乱!
  2. 配置文件和Java代码分离、编写不是很方便!
  3. XML配置文件解析效率低

基于注解+XML方式整合三层架构

  1. 准备数据库
xml 复制代码
create database studb;

use studb;

CREATE TABLE students (
  id INT PRIMARY KEY,
  name VARCHAR(50) NOT NULL,
  gender VARCHAR(10) NOT NULL,
  age INT,
  class VARCHAR(50)
);

INSERT INTO students (id, name, gender, age, class)
VALUES
  (1, '张三', '男', 20, '高中一班'),
  (2, '李四', '男', 19, '高中二班'),
  (3, '王五', '女', 18, '高中一班'),
  (4, '赵六', '女', 20, '高中三班'),
  (5, '刘七', '男', 19, '高中二班'),
  (6, '陈八', '女', 18, '高中一班'),
  (7, '杨九', '男', 20, '高中三班'),
  (8, '吴十', '男', 19, '高中二班');

编写数据库连接的信息

xml 复制代码
nie.url=jdbc:mysql://localhost:3306/studb
nie.Driver=com.mysql.cj.jdbc.Driver
nie.username=root
nie.password=123456
  1. 导入依赖
java 复制代码
<dependencies>
      <!--spring context依赖-->
      <!--当你引入SpringContext依赖之后,表示将Spring的基础依赖引入了-->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>6.0.6</version>
      </dependency>

      <!-- 数据库驱动和连接池-->
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.25</version>
      </dependency>

      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid</artifactId>
          <version>1.2.8</version>
      </dependency>
      
      <dependency>
            <groupId>jakarta.annotation</groupId>
            <artifactId>jakarta.annotation-api</artifactId>
            <version>2.1.1</version>
       </dependency>

      <!-- spring-jdbc -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>6.0.6</version>
      </dependency>

</dependencies> 
  1. 准备实体类
java 复制代码
package com.nie.entity;

public class Student {

    private Integer id;
    private String name;
    private String gender;
    private Integer age;
    private String classes;

    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 String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getClasses() {
        return classes;
    }

    public void setClasses(String classes) {
        this.classes = classes;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", age=" + age +
                ", classes='" + classes + '\'' +
                '}';
    }
}
  1. 持久层
java 复制代码
package dao;

import com.nie.entity.Student;

import java.util.List;

public interface StudentDao {

    List<Student> fandAll();
}
java 复制代码
package dao;

import com.nie.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public class StudentDaoIml implements  StudentDao{

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public List<Student> fandAll() {

        String sql="select id , name , age , gender , class as classes from students";

        List<Student> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Student.class));

        return query;
    }
}
  1. 业务层
java 复制代码
package service;

import com.nie.entity.Student;

import java.util.List;




public interface StudentService {

    List<Student> QueryALL();
}
java 复制代码
package service;

import com.nie.entity.Student;
import dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;


@Service
public class StudentServiceIml implements  StudentService{

    @Autowired
    private StudentDao studentDao;

    @Override
    public List<Student> QueryALL() {

        List<Student> students = studentDao.fandAll();


        return students;
    }
}
  1. 表述层
java 复制代码
package controllor;

import com.nie.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
import service.StudentService;

import java.util.List;

@Controller
public class StudentControllor {

    @Autowired
    private StudentService studentService;

    public void Cha(){
        List<Student> students = studentService.QueryALL();
        System.out.println(students);
    }

}
  1. 三层架构IOC配置
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:context="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">

    <context:component-scan base-package="com.nie.entity,controllor,dao,service"/>

    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="url" value="jdbc:mysql://localhost:3306/studb"/>
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
            <property name="username" value="root"/>
            <property name="password" value="123456"/>
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

</beans>
  1. 测试
java 复制代码
import com.nie.entity.Student;
import controllor.StudentControllor;
import dao.StudentDao;
import dao.StudentDaoIml;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

public class Test {

    @org.junit.jupiter.api.Test
    public void Query(){
        ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("sprinng-01.xml");
        StudentControllor bean = classPathXmlApplicationContext.getBean(StudentControllor.class);

        bean.Cha();
    }
}

运行结果如下

注解+XML IoC方式总结

  1. 自定义类可以使用注解方式,但是第三方依赖的类依然使用XML方式!
  2. XML格式解析效率低!

基于注解和配置类

  1. 准备数据库
xml 复制代码
create database studb;

use studb;

CREATE TABLE students (
  id INT PRIMARY KEY,
  name VARCHAR(50) NOT NULL,
  gender VARCHAR(10) NOT NULL,
  age INT,
  class VARCHAR(50)
);

INSERT INTO students (id, name, gender, age, class)
VALUES
  (1, '张三', '男', 20, '高中一班'),
  (2, '李四', '男', 19, '高中二班'),
  (3, '王五', '女', 18, '高中一班'),
  (4, '赵六', '女', 20, '高中三班'),
  (5, '刘七', '男', 19, '高中二班'),
  (6, '陈八', '女', 18, '高中一班'),
  (7, '杨九', '男', 20, '高中三班'),
  (8, '吴十', '男', 19, '高中二班');

编写数据库连接的信息

xml 复制代码
nie.url=jdbc:mysql://localhost:3306/studb
nie.Driver=com.mysql.cj.jdbc.Driver
nie.username=root
nie.password=123456
  1. 导入依赖
java 复制代码
<dependencies>
      <!--spring context依赖-->
      <!--当你引入SpringContext依赖之后,表示将Spring的基础依赖引入了-->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>6.0.6</version>
      </dependency>

      <!-- 数据库驱动和连接池-->
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.25</version>
      </dependency>

      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid</artifactId>
          <version>1.2.8</version>
      </dependency>
      
      <dependency>
            <groupId>jakarta.annotation</groupId>
            <artifactId>jakarta.annotation-api</artifactId>
            <version>2.1.1</version>
       </dependency>

      <!-- spring-jdbc -->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>6.0.6</version>
      </dependency>

</dependencies> 
  1. 准备实体类
java 复制代码
package com.nie.entity;

public class Student {

    private Integer id;
    private String name;
    private String gender;
    private Integer age;
    private String classes;

    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 String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getClasses() {
        return classes;
    }

    public void setClasses(String classes) {
        this.classes = classes;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", age=" + age +
                ", classes='" + classes + '\'' +
                '}';
    }
}
  1. 持久层
java 复制代码
package dao;

import com.nie.entity.Student;

import java.util.List;

public interface StudentDao {

    List<Student> fandAll();
}
java 复制代码
package dao;

import com.nie.entity.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public class StudentDaoIml implements  StudentDao{

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public List<Student> fandAll() {

        String sql="select id , name , age , gender , class as classes from students";

        List<Student> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Student.class));

        return query;
    }
}
  1. 业务层
java 复制代码
package service;

import com.nie.entity.Student;

import java.util.List;




public interface StudentService {

    List<Student> QueryALL();
}
java 复制代码
package service;

import com.nie.entity.Student;
import dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;


@Service
public class StudentServiceIml implements  StudentService{

    @Autowired
    private StudentDao studentDao;

    @Override
    public List<Student> QueryALL() {

        List<Student> students = studentDao.fandAll();


        return students;
    }
}
  1. 表述层
java 复制代码
package com.nie.controller;

import com.nie.entity.Student;
import com.nie.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import java.util.List;

@Controller
public class StudentController {

    @Autowired
    private StudentService studentService;

    public void  findAll(){
        List<Student> studentList =  studentService.QueryALL();
        System.out.println("studentList = " + studentList);
    }

}
  1. IOC配置类
jaba 复制代码
package com.nie.entity;


import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.*;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

@Configuration
@ComponentScan(value = "com.nie")
@PropertySource("classpath:jdbc.properties")
public class Config {

    @Value("${nie.url}")
    private String url;
    @Value("${nie.Driver}")
    private String driver;
    @Value("${nie.username}")
    private String username;
    @Value("${nie.password}")
    private String password;

    @Bean(destroyMethod = "close")
    public DruidDataSource dataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setDriverClassName(driver);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }

    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource){
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }
}
  1. 测试
java 复制代码
import com.nie.entity.Config;


import com.nie.controller.StudentController;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class Test {

    @org.junit.jupiter.api.Test
    public  void testRun(){

        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Config.class);
        StudentController bean = annotationConfigApplicationContext.getBean(StudentController.class);

        bean.findAll();
    }
}

基于注解+配置类Ioc方式总结

  1. 完全摒弃了XML配置文件
  2. 自定义类使用IoC和DI注解标记
  3. 第三方类使用配置类声明方法+@Bean方式处理
  4. 完全注解方式(配置类+注解)是现在主流配置方式
相关推荐
寒士obj7 分钟前
类加载的过程
java·开发语言
无名之逆10 分钟前
大三自学笔记:探索Hyperlane框架的心路历程
java·开发语言·前端·spring boot·后端·rust·编程
yang_xiao_wu_10 分钟前
springboot+mybatis面试题
spring boot·后端·mybatis
Chuck1sn12 分钟前
我把 Cursor AI 整合到 Ruoyi 中,从此让 Java 脚手架脱离人工!
java·vue.js·后端
广州山泉婚姻13 分钟前
智慧零工平台后端开发进阶:Spring Boot 3结合MyBatis-Flex的技术实践与优化【无标题】
人工智能·爬虫·spring
水木石画室15 分钟前
Spring Boot 常用注解面试题深度解析
java·spring boot·后端
阿杆17 分钟前
想体验出海应用赚钱?试试这个一年免费的香港服务器
后端·产品·创业
hweiyu0032 分钟前
tomcat指定使用的jdk版本
java·开发语言·tomcat
百锦再35 分钟前
.NET 类库开发详细指南c
java·log4j·.net·net·dot
汤圆和烟灰儿36 分钟前
Linux 防火墙工具 iptables 入门与常用命令整理
后端