Spring
Spring框架是一个用于构建企业级应用程序的开源Java框架。它提供了一个全面的编程和配置模型,用于开发现代化的Java应用程序。
Spring从早期的大量XML配置逐渐演变为采用注解和自动配置的方式,显著减少了配置的工作量。同时,Maven的引入解决了jar包版本管理的问题,使开发人员更专注于业务代码的开发。这些变化大大简化了Java应用程序的开发和维护过程。
Spring Boot
Spring Boot的设计原则是约定优于配置,它默认提供了许多常见的配置,以减少开发人员的配置工作。它还提供了一个内嵌的Servlet容器(如Tomcat、Jetty),简化了应用程序的部署过程。
Spring Boot简化了Spring应用的开发过程,提供了自动配置和快速启动的能力。
Spring MVC
MVC是一种软件架构模式,它将应用程序划分为三个主要组件:模型(Model)、视图(View)和控制器(Controller)。
Spring MVC是Spring框架提供的一种用于开发基于MVC模式的Web应用程序的模块。它通过将请求的处理与视图的渲染分离,帮助开发人员更好地组织和管理Web应用程序的代码。
Maven项目搭建
全局配置文件:settings.xml
解压Maven的jar包,找到路径下conf文件夹里的settings.xml配置文件:
settings.xml配置文件是Maven的全局配置文件,它定义了Maven的行为和属性。
1.本地库的保存位置:
2.下载镜像源:这里使用阿里云
新建Maven项目
在IDEA中新建通过Maven构建的项目
点Settings找到Maven配置Maven相关的路径:
项目配置文件:pom.xml
项目基本信息
- groupId: com.easy
- 这是项目的组织或团体的唯一标识符。它通常公司或组织的域名反向有关
- artifactId:
EasySpringA
- 这是项目的唯一标识符,用于标识项目的具体模块或应用。在Maven仓库中,
groupId
和artifactId
一起唯一确定了一个项目。
- 这是项目的唯一标识符,用于标识项目的具体模块或应用。在Maven仓库中,
- version:
1.0-SNAPSHOT
- 这是项目的版本号。
SNAPSHOT
通常表示这是一个开发中的版本,可能随时会更改。与之相对的是RELEASE
或具体的版本号,表示这是一个稳定版本。
- 这是项目的版本号。
属性配置
- maven.compiler.source 和 maven.compiler.target: 都设置为
8
- 这两个属性指定了Java源代码和目标字节码的JDK版本。在这个例子中,它们都被设置为
8
,意味着项目将使用Java 8进行编译和运行。
- 这两个属性指定了Java源代码和目标字节码的JDK版本。在这个例子中,它们都被设置为
- project.build.sourceEncoding:
UTF-8
- 这个属性指定了项目构建过程中使用的源文件的编码格式。
UTF-8
是一种广泛使用的编码,能够表示世界上几乎所有的字符。
- 这个属性指定了项目构建过程中使用的源文件的编码格式。
Maven仓库中流行的库、框架、工具下载及其最新发布信息:https://mvnrepository.com/
找到所需的Spring Boot依赖库:
依赖配置
配置好后,Maven会自动下载所需的jar包
<dependencies><!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.6.6</version></dependency></dependencies>
- spring-boot-starter-web
- 这是一个Spring Boot的起步依赖项,它包含了构建Web应用所需的所有核心库。这包括Spring MVC和Tomcat(或其他嵌入式Servlet容器),以及用于RESTful Web服务的Jackson等库。
- groupId:
org.springframework.boot
- 这是Spring Boot项目的组织标识符。
- artifactId:
spring-boot-starter-web
- 这是具体的依赖项标识符,表示我们想要包含Spring Boot的Web起步依赖。
- version:
2.6.6
- 这是我们想要使用的Spring Boot版本的版本号。选择这个版本号意味着我们将使用Spring Boot 2.6.6版本的所有特性和修复。
这一步配置结束后IDEA可能仍会报错:
这通常是因为 IDEA 的 Maven 插件或者项目配置没有正确地识别或下载 Maven 依赖。可以尝试下面的方案解决这个问题:
- 更新 Maven 项目:
- 在 IDEA 中,你可以通过点击右侧的 Maven 工具栏中的 "Reload All Maven Projects"(或者点击项目名旁边的刷新按钮)来强制 IDEA 重新加载 Maven 项目并下载缺失的依赖。
- 另一个方法是,在 Maven 面板中找到你的项目,右键点击并选择 "Maven" -> "Reload Project"。
- 检查 Maven 设置:
- 打开 IDEA 的设置(Preferences 或 Settings),导航到
Build, Execution, Deployment
->Build Tools
->Maven
。 - 确保
Maven home directory
指向了正确的 Maven 安装目录。 - 检查
User settings file
是否指向了正确的settings.xml
文件,这个文件通常用于配置 Maven 仓库等。 - 确认
Local repository
路径是否正确,并且 IDEA 有足够的权限访问这个目录。
- 打开 IDEA 的设置(Preferences 或 Settings),导航到
- 检查网络问题:
- 确保你的网络连接是正常的,并且 Maven 仓库(如 Maven Central)可以被访问。
- 可能需要配置 Maven 仓库镜像,如阿里云 Maven 仓库,以提高下载速度和稳定性。
父项目配置:
Maven项目中的父项目配置用于指定当前项目的父项目。在Maven中,父项目可以提供一些公共的配置和依赖项,供子项目继承和使用。
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-parent</artifactId><version>2.6.6</version></parent>
在示例中,父项目的坐标为org.springframework.boot:spring-boot-parent
,版本号为2.6.6
。
此时再配置依赖时可以省略版本号,统一为相同的版本。
编写项目启动类
在源文件夹java下创建包,通常与组织标识符一致:如com.easy
编写启动类:项目名Application
运行起该类就运行了整个项目,使用注解 @SpringBootApplication
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class EasySpringAApplication {//项目启动类 运行起该类就运行了整个项目public static void main(String[] args) {SpringApplication.run(EasySpringAApplication.class,args);}
}
如下图日志表示,Tomcat服务器已启动,端口号8080;启动类已启动。
浏览器输入:http://localhost:8080,此时缺少对前台请求的处理,还无法正常访问
HTML状态码是指在HTTP协议中服务器返回给浏览器的状态码,用于表示请求的结果。以下是一些常见的HTML状态码及其含义:
200 OK:请求成功。表示服务器成功处理了请求。
301 Moved Permanently:永久重定向。表示请求的资源已被永久移动到新的URL。
302 Found:临时重定向。表示请求的资源暂时被移动到其他URL。
304 Not Modified:未修改。表示请求的资源未发生变化,浏览器可以使用本地缓存的副本。
400 Bad Request:请求无效。表示服务器无法理解请求的语法。
401 Unauthorized:未授权。表示请求要求身份验证。
403 Forbidden:禁止访问。表示服务器拒绝请求访问所请求的资源。
404 Not Found:未找到。表示服务器无法找到请求的资源。
500 Internal Server Error:服务器内部错误。表示服务器在执行请求时遇到了错误。
503 Service Unavailable:服务不可用。表示服务器当前无法处理请求,通常因为服务器过载或维护。
这些状态码是HTTP协议中常见的一部分,它们用于指示请求的结果和可能的错误原因。通过查看状态码,可以帮助开发者了解请求的执行情况并进行相应的处理。
编写访问层控制类
在前面com.easy包下创建controller包,包内编写访问层控制类,表示该类用于接收前台访问。
类前使用注解 @RestController 表示该类是一个RESTful风格的控制器,主要用于处理HTTP请求并返回RESTful风格的响应。
编写方法响应请求,使用请求映射注解@RequestMapping
//接收前台访问
@RestController
public class EasyController {//请求映射@RequestMapping("hello")public String hello(){return "java so easy";}
}
此时再通过浏览器访问8080,地址栏跟上/hello,能够正常访问
@Controller 注解也是Spring MVC框架中的一个注解,表示该类是一个普通的控制器,主要用于处理HTTP请求并返回视图。
@Controller
public class EasyBController {@RequestMapping("testm")public ModelAndView testM(){System.out.println("-----------");ModelAndView mav=new ModelAndView();mav.setViewName("index");mav.addObject("username","zhangsan");return mav;}
}
在resource文件夹下创建应该templates文件夹,新建一个index.html文件:
<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
index page
<h1 th:text="${username}"></h1>
</body>
</html>
运行项目后在浏览器中可以得到:
控制反转 IOC
Spring IOC(Inversion of Control)是Spring框架的核心特性之一。它是一种软件设计原则,旨在实现对象之间的解耦和灵活性。用于管理项目中java bean的生命周期
在传统的开发中,对象的创建和依赖管理通常由开发人员手动完成。这种方式可能会导致代码的耦合度高、可测试性差以及难以扩展和维护。而Spring IOC通过将对象的创建和依赖注入的工作交给框架来完成,实现了控制反转。
控制反转意味着对象的创建和依赖关系的管理由框架来处理,而不是由开发人员显式地编码实现。开发人员只需要声明该类需要什么类型的对象,只需要定义对象和它们之间的依赖关系,而无需关心对象的创建和管理细节。这样可以提高代码的可维护性、扩展性和测试性。
Spring IOC通过以下方式实现控制反转:
- 依赖注入(Dependency Injection):通过注入依赖对象,实现了对象之间的解耦。开发人员只需要定义依赖关系,而不需要手动创建依赖的对象。
- Bean容器(Bean Container):Spring框架提供了一个容器,称为应用上下文(Application Context),用于管理对象的生命周期和依赖关系。它负责创建、初始化和销毁对象,同时将对象注入到需要它们的地方。
- 配置文件:开发人员可以使用XML、注解或Java配置等方式来配置对象和它们之间的依赖关系。通过配置文件,Spring可以根据配置来创建和管理对象。
通过Spring IOC,我们可以实现解耦和模块化开发,减少代码的重复和冗余,提高系统的可维护性和扩展性。同时,它还可以方便地进行单元测试和集成测试,提高开发效率。
Spring框架中常用的注解组件
在项目运行阶段,程序中需要很多的对象来完成整体业务,SpringBoot提供了很多的注解标注类,这些注解能把对象加入到IOC容器,让Spring来管理这些类的对象的生命周期:
@Controller
@Controller注解用于在访问层定义一个控制器类,在Spring MVC中用于接收前台的请求并进行处理。通常配合@RequestMapping注解使用,用于接收前台访问,将请求映射到相应的处理方法,并返回相应的视图或数据。Controller类中的方法可以返回视图页面,也可以返回JSON或XML格式的数据。
@RestController
@RestController是@Controller的一个特殊版本,用于定义RESTful风格的控制器类。它是Spring MVC 4.0之后新增的注解,可以简化代码,提供更多的方便特性。@RestController注解相当于@Controller注解和@ResponseBody注解的结合,表示该类中的所有方法都会返回JSON数据,而不是视图页面。
@Service
@Service注解用于定义一个服务类,在Spring中用于表示业务逻辑层。通常在Service类上添加@Service注解,使其成为Spring容器中的Bean,然后可以通过依赖注入的方式在其他地方使用该服务类。Service类中通常包含一些业务处理的方法,可以调用Dao层的方法来操作数据库,完成相应的业务逻辑。
@Repository
@Repository注解用于定义一个数据访问类,在Spring中用于表示数据访问层(DAO,Data Access Object)。通常在Repository类上添加@Repository注解,使其成为Spring容器中的Bean,然后可以通过依赖注入的方式在Service层使用该数据访问类。Repository类中通常定义一些数据库操作的方法,通过调用底层数据库访问技术(如JDBC、Hibernate等)来实现对数据库的访问。(Dao数据访问,访问数据库)
@Component
@Component注解是Spring中通用的注解,用于表示一个普通的Bean类,没有明确的角色。在Spring中,它可以作为通用的容器管理对象,被其他注解所扩展和衍生。通常@Component注解用于表示一个普通的组件类,可以被其他类依赖注入使用。
@Bean
@Bean注解用于在配置类中定义一个Bean对象,并将其注册到Spring容器中。通常在Java配置类(使用@Configuration注解的类)中使用@Bean注解来定义一个Bean对象,代替XML配置文件中的<bean>标签。通过@Bean注解,可以定义一些特殊的Bean对象、第三方库的对象等,并指定其创建过程和依赖关系。
依赖注入 DI
依赖注入(Dependency Injection):通过注入依赖对象,实现了对象之间的解耦。开发人员只需要定义依赖关系,而不需要手动创建依赖的对象。
依赖注入使用注解@Autowired ,通过识别依赖关系注入对应的对象
//依赖注入DI 通过识别依赖关系注入对应的对象@AutowiredEasyService easyS;@RequestMapping("easya")public String easya(){System.out.println(easyS);return "new Service";}
Spring Bean的作用域
在Spring框架中,有以下几种常用的Bean作用域:
类型 | 详解 |
---|---|
Singleton(单例) | 每个Spring容器中只会存在一个实例,所有对该Bean的请求都会返回同一个实例。这是Spring默认的作用域。 |
Prototype(原型) | 每次对该Bean的请求都会创建一个新的实例。 |
Request(请求) | 每个HTTP请求都会创建一个新的实例,且在当前请求范围内共享。 |
Session(会话) | 每个HTTP Session都会创建一个新的实例,且在当前会话范围内共享。 |
GlobalSession(全局会话) | 只在基于Portlet的Web应用中有意义,每个全局会话都会创建一个新的实例,且在全局会话范围内共享。 |
这里演示两种作用域:使用注解@Scope传入字符串类型的value值设置不同的作用域。
单例模式:
@Component
@Scope(value = "singleton")
public class TestA {public void test(){System.out.println(this);System.out.println("text method");}
}
刷新页面多次请求,发现控制台输出地址相同,返回的都是同一个对象。
设置原型模式作用域的注解:
@Scope(value = "prototype")
多次请求发现,每次对该对象的请求,都会创建一个新的对象
Spring Bean的生命周期
1)根据配置情况调用 Bean 构造方法或工厂方法实例化 Bean。
public EasyBean(){System.out.println("1----构造方法");}
2)利用依赖注入完成 Bean 中所有属性值的配置注入。
TestA testa;@Autowiredpublic void setTesta(TestA testa){System.out.println("2----注入属性");this.testa=testa;}
3) 如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值。
@Overridepublic void setBeanName(String name) {System.out.println("3----BeanNameAware接口的setBeanName方法"+name);//叫什么}
4)如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂实例的引用。
@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("4----BeanFactoryAware接口的setBeanFactory方法"+beanFactory);//什么工厂创建}
5) 当一个 Bean 实现了 ApplicationContextAware 接口并在 Spring 容器中被实例化时,Spring 容器会自动调用该 Bean 的 setApplicationContext 方法,并将应用程序上下文ApplicationContext作为参数传递进来
@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {//在什么项目下System.out.println("5----ApplicationContextAware接口的setApplicationContext方法"+applicationContext);}
6)BeanPostProcessor 是 Spring 框架中的一个重要接口,它允许开发者在 Spring 容器创建和初始化 bean 的过程中,对 bean 进行自定义处理。这包括在 bean 实例化之后、属性设置之前(postProcessBeforeInitialization 方法),以及在 bean 初始化之后(postProcessAfterInitialization 方法)执行自定义逻辑
Spring 容器在创建和初始化每一个 bean 时,都会调用 CustomBeanPostProcessor 中的这两个方法,允许你进行自定义处理
@Component
public class EasyBeanPostProcessor implements BeanPostProcessor {//初始化处理器@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("easyBean")){System.out.println("6----BeanPostProcessor接口的Before方法");//设置属性之前}return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);}}
7)InitializingBean 是 Spring 框架中的一个接口,它定义了一个 afterPropertiesSet 方法。当 Spring 容器创建 bean 的所有属性都被设置完成后,会调用这个方法。
@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("7----InitializingBean接口的afterPropertiesSet方法");//所有属性设置完成之后}
8)如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法。
public void init(){System.out.println("8----init method");//初始化方法}
9)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的初始化方法 postProcessAfterInitialization()。此时,Bean 已经可以被应用系统使用了。
@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (beanName.equals("easyBean")){System.out.println("9----BeanPostProcessor接口的After方法");//初始化属性之后}return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);}
10)如果在 <bean> 中指定了该 Bean 的作用范围为 scope="singleton",则将该 Bean 放入 Spring IoC 的缓存池中,将触发 Spring 对该 Bean 的生命周期管理;如果在 <bean> 中指定了该 Bean 的作用范围为 scope="prototype",则将该 Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 Bean。
//配置类
@Configuration
public class EasyConfig {//把一个对象加入到IOC容器管理的方式@Bean(initMethod = "init")//@Scope("prototype")//交给调用者管理,spring不再bean的管理生命周期public EasyBean easyBean(){return new EasyBean();//会把返回值加入到容器内,名字就是方法名}}
11)如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory() 方法将 Spring 中的 Bean 销毁;如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁方法,则 Spring 将调用该方法对 Bean 进行销毁。
@Overridepublic void destroy() throws Exception {System.out.println("easybean被回收了");//回收}