1 Java EE与Jakarta EE
Java EE是Java Enterprise Edition的缩写,它是甲骨文提出的一套完整的开发规范。Java平台最早由sun公司开发,后来甲骨文兼并了Sun。
Java EE以前一直由甲骨文维护,直到2018年3月,Java EE被Jakarta EE,以后由开源组织Eclipse基金会来维护。
2022年11月,VMware发布了Spring Framework 6.0,它的依赖环境是JDK17+、Jakarta EE 9+(Tomcat 10/Jetty 11)。JDK17是甲骨文2021年9月14日发布的一个LTS(长期支持)版。Jakarta EE已经发布到10版本,正在提议11版本。
1.1 Jakarta EE是什么
Jakarta EE是Eclipse基金在Java EE基础上发布的一套Java开发规范。
规范是什么?比如说,冯·诺依曼定义了计算机架构,由输入设备、输出设备、运算器、控制器、内存、外存组成,这就可以看成一套high-level(高级)的规范。规范就是一组约定,其他人按照约定实现。它相当于工业标准,协议也可以看成某种具体的规范。
Jakarta EE的大量规范性文档是由一系列的JSR组成的。JSR是Java Specification Requests的缩写,意思是Java规范提案。
1.2 Jakarta EE文档
下载地址:https://jakarta.ee/learn/docs/jakartaee-tutorial/current/web/webapp/webapp.html
2. Spring介绍
2.1 相关网站
- 官网:https://spring.io/
- 中文网站:https://springdoc.cn/docs/
- Sping仓库:https://repo.spring.io/ui/repos/tree/General/libs-milestone
2.2 Spring概述
-
Spring Framework是Java平台的明星框架,Spring Framework必须依赖Jakarta EE(Java EE)。
-
Spring是第三方框架,Jakarta EE是规范,Spring的所有开发者必须满足Jakarta EE平台的要求。
-
Spring是轻量级框架,Jakarta EE中的EJB(Enterprise Java Bean)是重量级框架。
-
Spring最为核心的理念的是控制反转(Inversion of Control,IoC)和面向切面编程(Aspect Oriented Programming,AOP)。
-
IoC是Spring的基础,它支撑着Spring对JavaBean的管理功能;AOP是Spring 的重要特性,AOP是通过预编译方式和运行期间动态代理实现程序功能,也就是说可以在不修改源代码的情况下,给程序统一添加功能。
-
Spring贯穿于表现层(Web层)、业务逻辑层(Service层)和持久层(Dao层)。
- 在表现层提供了Spring MVC框架,并且Spring还可以与Struts框架整合。
- 业务逻辑层可以管理事务、记录日志等。
- 持久层可以整合MyBatis、Hibernate、JdbcTemplate等技术。
2.3 Spring的体系结构
3. Spring入门程序
环境说明:
- JDK 21
- Maven 3.9.6
- Spring 6.1.5
- IDEA 2024.1
3.1 环境搭建
-
导入相关依赖
<dependencies> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>6.1.5</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> </dependency> </dependencies>
-
创建名称为HelloSpring的类
public class HelloSpring { private String userName; public void setUserName(String userName) { this.userName = userName; } public void show() { System.out.println(userName + ":欢迎来到Spring"); } }
-
编写Spring的配置文件
参考文档:https://docs.spring.io/spring-framework/reference/core/beans/basics.html
-
配置文件的放置位置:任意位置
-
配置文件的命名:没有要求,建议applicationContext.xml
-
<bean id="helloSpring" class="com.jxzz.HelloSpring">
<property name="userName" value="张三"></property>
</bean>
-
测试
public class MyTest { @Test public void TestNew() { HelloSpring helloSpring = new HelloSpring(); helloSpring.setUserName("张三"); helloSpring.show(); } @Test public void TestHelloSpring() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext.xml"); // HelloSpring helloSpring = (HelloSpring)applicationContext.getBean("helloSpring"); // HelloSpring helloSpring = applicationContext.getBean("helloSpring", HelloSpring.class); //推荐 HelloSpring helloSpring = applicationContext.getBean(HelloSpring.class); helloSpring.show(); } }
4. 控制反转(IoC)
控制:对于成员变量赋值的控制权
反转控制:把对于成员变量赋值的控制权,从应用代码中反转(转移)到Spring容器中完成
好处:降低程序代码之间的耦合度(解耦合)
底层实现:工厂设计模式
传统面向对象编程中,获取对象的方式是用关键字“new”主动创建对象,即应用程序掌握着对象的控制权。
Spring框架:对象的实例不再由调用者创建,而是由Spring的IoC容器来创建,IoC容器负责控制程序之间的关系,而不是由调用者的程序代码直接控制。
控制权由应用代码转移到了IoC容器,控制发生了反转,这就是Spring的控制反转。
由Spring容器创建对象特称为Bean或者组件(Componet)。
5. 依赖注入(DI)
注入:通过Spring容器,为对象(bean,组件)的成员变量赋值
依赖注入:当一个类需要另一个类时,就意味着依赖,一旦出现依赖,就可以把另一个类作为本类的成员变量,最终通过Spring容器进行注入(赋值)。
好处:解耦合
5.1 构造方法注入
Spring容器调用构造方法为实例的成员变量赋值。
Spring在读取配置信息后,会通过反射方式调用实例的构造方法。
5.1.1 开发步骤
-
编写用户类
public class User1 { private int id; private String name; private String password; public User1(int id, String name, String password) { this.id = id; this.name = name; this.password = password; } @Override public String toString() { return "User1{" + "id=" + id + ", name='" + name + '\'' + ", password='" + password + '\'' + '}'; } }
-
编写applicationContext.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"> <bean id="user1" class="com.jxzz.User1"> <constructor-arg name="id" value="1"></constructor-arg> <constructor-arg name="name" value="张三"></constructor-arg> <constructor-arg name="password" value="123"></constructor-arg> </bean> </beans>
-
测试
@Test public void TestUser1() { // User1 user1 = new User1(1, "张三", "123"); ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext-User.xml"); User1 user1 = applicationContext.getBean("user1", User1.class); System.out.println(user1); }
5.1.2 <constructor-arg>元素属性
一个<constructor-arg>元素表示构造方法的一个参数,且定义时不区分顺序。
构造方法可以重载
-
确定参数的:
-
index:通过参数的索引确定参数。
-
name:通过参数的名字确定参数。推荐
-
type:通过参数的类型确定参数
-
-
给属性赋值的:
-
ref:给引用类型赋值
-
value:给基本类型赋值
-
5.2 属性setter方法注入(推荐)
8种基本类型
String类型
集合类型:数组、List、Set、Map、ProPerties
用户自定义类型
5.2.1 JDK内置类型开发步骤
-
编写用户类
@Data @NoArgsConstructor public class User2 { private int id; private String name; private String password; private String[] emails; private Set<String> tels; private List<String> addresses; private Map<String,String> qqs; private Properties pros; }
-
编写applicationContext.xml配置文件
<bean id="user2" class="com.jxzz.User2"> <property name="id" value="2"></property> <property name="name" value="李四"></property> <property name="password" value="456"></property> <property name="emails"> <list> <value>lisi@qq.com</value> <value>zhangsan@qq.com</value> <value>wanger@qq.com</value> </list> </property> <property name="addresses"> <list> <value>jxzz</value> <value>nanchang</value> <value>jiujiang</value> <value>ganzhou</value> </list> </property> <property name="tels"> <set> <value>12345678900</value> <value>12345678901</value> <value>12345678902</value> <value>12345678903</value> <value>12345678903</value> </set> </property> <property name="qqs"> <map> <entry> <key><value>lisi</value></key> <value>6666666</value> </entry> <entry> <key><value>zhangsan</value></key> <value>7777777</value> </entry> <entry> <key><value>wanger</value></key> <value>8888888</value> </entry> </map> </property> <property name="pros"> <props> <prop key="key1">value1</prop> <prop key="key2">value2</prop> </props> </property> </bean>
-
测试
@Test public void TestUser2() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext-User.xml"); User2 user2 = applicationContext.getBean("user2", User2.class); // System.out.println(user2); // 测试8种基本类型+String类型 System.out.println("id=" + user2.getId()); System.out.println("name=" + user2.getName()); System.out.println("password=" + user2.getPassword()); //测试数组类型 for (String email : user2.getEmails()) { System.out.println("email=" + email); } //测试List类型 for (String address : user2.getAddresses()) { System.out.println("address=" + address); } //测试Set类型 for (String tel : user2.getTels()) { System.out.println("tel=" + tel); } //测试Map类型 Map<String, String> qqs = user2.getQqs(); for (String key : qqs.keySet()) { System.out.println("key=" + key + ", value=" + qqs.get(key)); } //测试ProPerties类型 Properties pros = user2.getPros(); System.out.println(pros.getProperty("key1")); System.out.println(pros.getProperty("key2")); }
5.2.2 用户自定义类型开发步骤
-
编写Mapper层
UserMapper接口
public interface UserMapper { public boolean login(String name, String password); }
UserMapper接口实现类
public class UserMapperImpl implements UserMapper { @Override public boolean login(String name, String password) { if (name.equals("张三") && password.equals("123")) { return true; } return false; } }
-
编写Server层
UserService接口
public interface UserService { public boolean login(String name, String password); }
UserService接口实现类
public class UserServiceImpl implements UserService { UserMapper userMapper; public void setUserMapper(UserMapper userMapper) { this.userMapper = userMapper; } @Override public boolean login(String name, String password) { return userMapper.login(name, password); } }
-
编写applicationContext.xml配置文件
<!--<bean id="userService" class="com.jxzz.service.impl.UserServiceImpl"> <property name="userMapper"> <bean class="com.jxzz.mapper.impl.UserMapperImpl"></bean> </property> </bean>--> <bean id="userMapper" class="com.jxzz.mapper.impl.UserMapperImpl"></bean> <bean id="userService" class="com.jxzz.service.impl.UserServiceImpl"> <property name="userMapper" ref="userMapper"></property> </bean>
name属性的值可以通过ref属性或者value属性指定。当使用ref属性时,表示对Spring IoC容器中某个Bean实例的引用。这里引用了前一个<bean>元素中创建的UserMapperImpl类的实例userMapper,并将该实例赋值给UserServiceImpl类型中userMapper属性,从而实现了依赖关系的注入。
-
编写测试类
@Test public void TestSpring() { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext.xml"); UserService userService = applicationContext.getBean("userService", UserService.class); boolean flag = userService.login("张三", "123"); if (flag) { System.out.println("登陆成功"); } else { System.out.println("登陆失败"); } }
参考
- 教材:《Java EE企业级应用开发教程(Spring+Spring MVC+MyBatis)(第2版)》
- https://www.bilibili.com/video/BV185411477k/?spm_id_from=333.999.0.0&vd_source=c68309cbc3b530cccc4946c705035b62