框架简介
framework:框架 ,根据一些编程思想, 把一些功能封装起来,帮助更好的,更快的做软件开发, 发布为jar包, 供其他程序员使用,这样的一些软件,被称为框架, 比如spring , spring mvc , mybatis, hibernate , spring boot 等。
1、spring
spring简介
Spring框架是一个开放源代码的J2EE应用程序框架,由Rod Johnson发起,是针对bean的生命周期进行管理的轻量级容器(lightweight container)。
- spring框架的的主要特点:
- Inversion of Control (IoC) : 控制反转 , spring框架创建对象,管理对象,以及管理对象之间的依赖关系。
- dependency injection (DI) :依赖注入 , 通过构造函数,或set方法, 给对象的属性赋值。IoC是通过DI来实现的。
- bean: java类型 , 由spring框架创建的对象,就被称为bean . (pojo: 纯java类(私有的属
性,公开的get/set方法这种类。))
Aspect-Oriented Programming (AOP): 面向切面编程 , 对比OOP(面向对象编程)
- The IoC Container: IoC容器
- 容器
- Interface BeanFactory
- Interface ApplicationContext 实现 BeanFactory
- Class ClassPathXmlApplicationContext 实现ApplicationContext
1.1、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">
<!-- ** id : 唯一标志
** class : 类型
init-method: 初始化方法的执行
destroy-method: 销毁方法的执行
scope: 设置bean是否为单例, 默认就是单例
lazy-init: 设置bean的创建时机,默认是false.
* true: 表示当需要第一次使用这个对象的时候,才创建这个对象
* false: 表示创建spring的容器的时候,就创建对象。
-->
<!--先定义一个类(如:Phone),配置id="a1"的bean对象-->
<bean id="a1" class="com.hqyj.entity.Phone">
<!--<constructor-arg name="pinPai":类的属性名
index="0":类的属性第一个
ref="":引用容器中存在的对象
value="":值
type="":类型
></constructor-arg>-->
<!--constructor 构造器-->
<constructor-arg name="pinPai" value="三星"></constructor-arg>
<!-- set注入: 调用set方法,给属性赋值
property : 属性, 表示给对象的属性赋值。 name是属性名, value/ref是对应的属性值
-->
<property name="price" value="1000.0"></property>
<constructor-arg index="2" value="64"></constructor-arg>
<!--
<constructor-arg name="pinPai" value="1"/>也可以改成<constructor-arg index="0" value="1"/>方式;
boolean的值既可以用0/1填充,也可以用true/false填充。
-->
</bean>
</beans>
1.2、spring中创建bean对象的3种 配置
java中创建对象的方式,对应为在spring中bean的配置:
<!-- 创建对象方式:1. 调用构造函数-->
<bean id="date" class="java.util.Date"></bean>
<!-- 创建对象方式:2. 调用自己的静态方法:
factory-method="getInstance" ,factory-method属性,用于指定需要调用的静态方法的名字
-->
<bean id="cal" class="java.util.Calendar" factory-method="getInstance">
</bean>
<!-- 创建对象方式:3. 调用容器中的其他bean的方法,创建对象:
factory-bean="cal" , factory-bean指定调用的容器中的其他bean的名字。
factory-method="getTime" ,factory-method属性,用于指定需要调用的bean的方法的名字
-->
<bean id="date1" class="java.util.Date" factory-bean="cal" factory-
method="getTime"></bean>
1.3、bean的autowire属性
autowire:自动装配, 为了减少构造器函数初始化对象和set注入初始化对象, 可以使用autowire ,让spring框架的容器对象,自动匹配容器中的其他bean对象,然后给bean进行初始化
- autowire: 自动装配, 根据spring容器中的对象的id 或对象的类型 ,按照自动装配的规则,给对象的属性初始化。
- constructor :按构造器函数进行匹配
- byType : set注入 ,调用无参构造函数,然后根据容器中的对象的类型和类的属性的类型,调用set方法 ,如果有多个符号条件的类型,则抛出异常
- byName : set注入 ,调用无参构造函数,然后根据容器中的对象的id和类的属性的属性名 ,调用set方法, 如果id匹配成功,但是类型不正确,则抛出异
常。 - byType , byName使用的时候,对于容器中的jdk提供的类型不能自动装配
xml:
<!-- <bean id="p1" class="com.hqyj.entity.Phone" autowire="constructor">
</bean>-->
<!-- <bean id="p1" class="com.hqyj.entity.Phone"-->
<!-- autowire="byType"></bean>-->
<bean id="p1" class="com.hqyj.entity.Phone" autowire="byName"></bean>
<bean id="phoneShell" class="com.hqyj.entity.PhoneShell">
<!--set注入 -->
<property name="color" value="绿色"></property>
<property name="size" value="10"></property>
</bean>
</beans>
<bean id="mem" class="java.lang.Integer">
<!--构造器注入 -->
<constructor-arg index="0" value="256"></constructor-arg>
</bean>
<!-- p1: autowire="byType": 根据(com.hqyj.entity.PhoneShell)
autowire="byName": 根据类的属性名(phoneShell)
autowire="constructor": 根据构造器-->
1.4、aop面向切面编程
jar包:
<!-- 导入aop相关的jar包-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.9.4</version>
</dependency>
aop详解,博主讲的详细:https://blog.youkuaiyun.com/q982151756/article/details/80513340
概念定义:
- Aspect(切面): Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的 Advice。
- Joint point(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它 joint point。
- Pointcut(切点):表示一组 joint point,这些 joint point 或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。
- Advice(增强):Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。
- Target(目标对象):织入 Advice 的目标对象.。
Weaving(织入):将 Aspect 和其他对象连接起来, 并创建 Adviced object 的过程
例子:
- 目标类
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
// 要求: ① dao中的每个方法执行之前,记录执行的信息: updateEmp方法开始执行:2022-9-16 14:08:39
// ② dao中的每个方法,执行时间的统计。
// 解决方式1 : 在每个方法内部,添加这一段功能相关的代码
// 解决方式2 : 把公共的功能,封装成方法, 然后在需要这个公共功能的地方,就调用这个方法。
// aop的思想: 面向切面编程 , 抽取项目中的公共的功能,单独封装。然后使用aop的配置 ,
// 通过动态代理的方式,实现封装的功能的调用。
@Component
public class EmpDao {
public Integer addEmp(){
System.out.println("addEmp ...... ");
return 1;
}
public Integer updateEmp(){
System.out.println("updateEmp ...... ");
return 1;
}
public Integer deleteEmp(){
System.out.println("deleteEmp ...... ");
return 1;
}
public List<String> queryEmp(){
System.out.println("queryEmp ...... ");
return null;
}
}
- logging
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
public class Logging {
// *** 公共功能: 希望在方法执行之前,显示方法执行的时间。
// -- Joinpoint 连接点 (可以理解为正在调用showTime的方法相关的对象)
public void showTime(JoinPoint joinpoint){
String methodName = joinpoint.getSignature().getName();// 正在被执行的方法的
名字
Date time = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String info = sdf.format(time);
System.out.println( methodName + "方法开始执行:" + info);
}
// ** 公共功能: 统计出每个方法执行消耗的时长。
public Object exeTime(ProceedingJoinPoint joinPoint) throws Throwable {
long begin = System.currentTimeMillis();
// 调用正在执行的方法
Object proceed = joinPoint.proceed();
long end = System.currentTimeMillis();
long cha = end - begin;
System.out.println(joinPoint.getSignature().getName() + ":执行消耗时间" +
cha + "毫秒");
//return proceed;
return proceed;
}
// 练习: 方法执行结束之后,输出方法的返回值
public void returnVal(JoinPoint joinPoint , Object obj){
// obj表示方法的返回值
System.out.println(joinPoint.getSignature().getName()
+ "返回值:" + obj);
}
}
- aop的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"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 开启组件扫描功能: 指定扫描的包-->
<context:component-scan base-package="com.hqyj"></context:component-scan>
<context:annotation-config/>
<aop:config>
<!--aspect: 切面 , 配置的是封装公共功能的对象。-->
<aop:aspect ref="logging">
<!-- pointcut: 切入点 , 通过一个表达式配置需要调用公共方法的类的方法。
execution(public * com.hqyj.dao.*.*(..)) : 通过这个表达式,找到要
调用的方法
第一个* :表示方法的返回值
com.hqyj.dao.* : 这个星号表示所有类。
com.hqyj.dao.*.*: 第二个星号表示所有方法。
(..) :表示任意参数
-->
<aop:pointcut id="all"
expression="execution(public * com.hqyj.dao.*.*
(..))"/>
<!-- pointcut-ref="all" : 表示切入点引用all.
before: 表示前置通知,当方法执行之前,先执行这个前置通知对应的method.
-->
<aop:before method="showTime" pointcut-ref="all"></aop:before>
<aop:around method="exeTime" pointcut-ref="all"></aop:around>
<aop:after-returning method="returnVal"
pointcut-ref="all"
returning="obj"/>
</aop:aspect>
</aop:config>
</beans>
- aop的注解
package com.hqyj.dao;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
@Aspect // 切面的设置
@EnableAspectJAutoProxy // 开启aop的自动代理功能
public class Logging1 {
// *** 公共功能: 希望在方法执行之前,显示方法执行的时间。
// public * com.hqyj..*.*(..) --- com.hqyj包
// public * com.hqyj.dao.*.*(..) --- com.hqyj.dao包
@Before("execution(public * com.hqyj.dao.*.*(..))")
public void showTime(JoinPoint joinpoint){
String methodName = joinpoint.getSignature().getName();// 正在被执行的方法的
名字
Date time = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String info = sdf.format(time);
System.out.println( methodName + "方法开始执行:" + info);
}
@Around("execution(public * com.hqyj.dao.*.*(..))") // ** 公共功能: 统计出每个
方法执行消耗的时长。
public Object exeTime(ProceedingJoinPoint joinPoint) throws Throwable {
long begin = System.currentTimeMillis();
Object proceed = joinPoint.proceed(); // 调用正在执行的方法
long end = System.currentTimeMillis();
long cha = end - begin;
System.out.println(joinPoint.getSignature().getName() + ":执行消耗时间" +
cha + "毫秒");
return proceed;
}
@AfterReturning(value = "execution(public * com.hqyj.dao.*.*(..))"
,returning = "obj")
public void returnVal(JoinPoint joinPoint , Object obj){
// obj表示方法的返回值
System.out.println(joinPoint.getSignature().getName() + ":" + obj);
}
}
2、springmvc
SpringMVC是一种基于Java,实现了Web MVC设计模式,请求驱动类型的轻量级Web框架,即使用了MVC(Model-View-Controller)架构模式的思想,将Web层进行职责解耦。基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,SpringMVC也是要简化我们日常Web开发。
SpringMVC就是一个Spring内置的MVC框架。采用了松散耦合可插拔组件结构,比其他 MVC 框架更具扩展性和灵活性,解决页面代码和后台代码的分离。
具体流程:
(1)首先浏览器发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
(2)DispatcherServlet——>HandlerMapping,处理器映射器将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器对象、多个HandlerInterceptor拦截器)对象;
(3)DispatcherServlet——>HandlerAdapter,处理器适配器将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
(4)HandlerAdapter——>调用处理器相应功能处理方法,并返回一个ModelAndView对象(包含模型数据、逻辑视图名);
(5)ModelAndView对象(Model部分是业务对象返回的模型数据,View部分为逻辑视图名)——> ViewResolver, 视图解析器将把逻辑视图名解析为具体的View;
(6)View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构;
(7)返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。
3、mybatis
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
mybatis是一个数据库相关的框架,主要为了简化jdbc的操作
mybatis使用了ORM, ORM是对象关系映射的英文缩写,ORM是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换 。
例子:
实体类:
entity:
@Data
@ToString
public class Hero {
private Integer id;
private String name;
private String sex;
private String position;
private Integer price;
private Date shelf_date;
}
repository
// 定义数据库操作的方法
public interface HeroDao {
public abstract int addHero(Hero hero);
public abstract int deleteHero(Integer id);
public abstract int updateHero(Hero hero);
public abstract List<Hero> queryAll();
}
resources文件下的mybatis-config.xml配置:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 设置控制台日志输出-->
<!-- 配置数据库连接的环境 : 默认使用id为"development"的环境-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url"
value="jdbc:mysql://localhost:3306/gamedb?serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 引用存在的mapper.xml文件-->
<mappers>
<!--<mapper resource="mapper/HeroMapper.xml"/>-->
</mappers>
</configuration>
resources/mapper文件下,HeroMapper.xml的根据持久层接口编写sql语句配置
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace: 命名空间 , 设置mapper.xml文件中的sql 对应的 interface。 -->
<mapper namespace="com.hqyj.dao.HeroDao">
<!-- insert:表示这是一个插入的sql语句
id: 对应dao(interface)中方法的名字
parameterType: 设置的dao(interface)中方法的参数
insert标签的内部: sql语句
sql语句中的#{属性名} , 就是在获取参数对象的属性的值 -->
<insert id="addHero" parameterType="com.hqyj.entity.Hero">
insert into hero values(null, #{name} , #{sex}
, #{position} , #{price} , #{shelf_date})
</insert>
<!-- 方法的参数是一个,并且属于8种类型 ,就可以省略。
也可以设置parameterType="int" ,这里的int就是简写
#{id} ,这里的id和方法参数名完全一致, deleteHero(Integer id)-->
<delete id="deleteHero">
delete from hero where id = #{id}
</delete>
<!-- price=#{price} , price是列名(table的列名),
#{price}(实体类的属性) ,这里是属性值的获取。-->
<update id="updateHero" parameterType="com.hqyj.entity.Hero">
update hero set `name` = #{name} , sex=#{sex},
`position` =#{position } , price=#{price} ,
shelf_date=#{shelf_date} where id=#{id}
</update>
<!-- resultType="com.hqyj.entity.Hero":返回值是一个实体,或者泛型为实体的集合,
设置的返回值类型都是这个实体类。-->
<select id="queryAll" resultType="com.hqyj.entity.Hero">
select * from hero
</select>
</mapper>
在mybatis-config.xml文件中引用HeroMapper.xml
<mappers>
<mapper resource="mapper/HeroMapper.xml"/>
</mappers>
4、mybatis-plus
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 -Sequence),可自由配置,完美解决主键问题
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、Service 、 Controller 层代码,支持模板引擎
- 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
- 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
- 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
MyBatis:作用是操作数据库的框架,提供一种Mapper类,支持让你用java代码进行增删改查的数据库操作,省去了每次都要手写sql语句的麻烦。但是需要先在mapper文件中对应的xml写好sql语句。所以有了Mybatis Generator,自动为Mybatis生成简单的增删改查sql语句的工具。
Mybatis-Plus是一个Mybatis的增强工具,它在Mybatis的基础上做了增强,却不做改变。我们在使用Mybatis-Plus之后既可以使用Mybatis-Plus的特有功能,又能够正常使用Mybatis的原生功能。Mybatis-Plus(以下简称MP)是为简化开发、提高开发效率而生,但它也提供了一些很有意思的插件,比如SQL性能监控、乐观锁、执行分析等。