麻绳先生

做一些记录性的工作

maven

目前存在的问题

  1. 一个项目就是一个工程
    如果项目非常庞大,就不适用package来划分模块,最好每一个模块对应一个工程,利于分工协作。借助于maven就可以将一个项目拆分为多个工程。
  2. 项目中需要的jar包需要手动管理
    同样的文件出现在不同的工程中,浪费存储,让文件结构冗余。
  3. jar包来源复杂,难以维护
  4. jar包依赖的其他文件仍需手动管理

什么是maven

是一款服务于java平台的自动化构建工具。

什么是构建

以“java源文件”、“框架配置文件”、JSP、HTML、图片等资源为原材料产生一个可运行的项目的过程。

  • 清理:将之前编译生成的字节码文件删除,为下一次编译做准备
  • 编译:将java源程序编程为class字节码文件
  • 测试:自动测试,自动调用junit程序
  • 报告:测试程序执行的结果
  • 打包:动态web工程war包,java工程jar包
  • 安装:maven特定的概念,将打包得到的文件复制到仓库中指定位置
  • 部署:将动态web工程生成的war包复制到servlet容器的指定目录下

安装maven核心程序

  • 检查JAVA_HOME环境变量
  • 解压maven核心程序压缩包,英文无空格目录
  • 配置maven相关环境变量
    • MAVEN_HOME或M2_HOME(bin目录上一级)
    • path(通常带bin目录)
  • 运行mvn -v验证配置

maven核心概念

约定的目录

  • 根目录:工程名
    • 以配置的方式告诉框架自定义文件:classpath:spring-content.xml
  • src目录:存放源码
  • pom.xml:maven工程核心配置文件
  • main目录:存放主程序
  • test目录:存放测试程序
  • java目录:存放java源码
  • resources目录:存放框架或其他工具的配置文件

约定大于配置,配置大于编码

POM

含义:project object model项目对象模型

坐标(gav)

  • groupid:公司组织域名倒序+项目名
  • artifactid:模块名
  • version:版本

依赖

  • 对于自己的maven工程,使用install命令将其安装到仓库。
  • 依赖的范围
    • compile:对主程序有效,对测试程序有效,参与打包
    • test:对主程序无效,对测试程序有效,不参与打包
    • provided:对主程序有效,对测试程序有效,不参与打包,不参与部署,例如servlet-api.jar
  • scope
  • 只有compile范围的依赖可以传递
  • exclusions用于排除依赖

依赖的原则

  • 作用:解决模块工程之间的jar包冲突
    • 最短路路径优先
    • 路径相同时先声明者优先,指的是dependency标签的声明顺序

统一管理依赖的版本号

  • properties标签,后跟依赖的id
  • 通过${依赖的id}访问版本号
  • 由于test范围的依赖不能传递,所以必然分散在各个模块工程中,导致不一致问题
    • 解决思路:将依赖统一提取到父工程中,在子工程中声明依赖时不指定版本,以父工程中统一的设定为准,方便维护
    1. 创建一个maven工程为父工程,注意打包方式为pom
    2. 在子工程中声明对父工程的引用
    3. 将子工程中的坐标中与父工程坐标中重复的内容删除
    4. 在父工程中统一管理依赖
    5. 子工程中删除依赖的版本号

子工程要首先install父工程

仓库

生命周期/插件/目标

  • 各个构建环节执行的顺序是既定的;
  • maven核心程序中定义了抽象的生命周期;
  • 不论执行哪个命令,maven都会从生命周期最开始的位置执行;

继承

聚合

一键安装各个模块工程
在一个总的聚合工程中配置各个参与聚合的模块

1
2
3
4
5
<modules>
<module></module>
<module></module>
<module></module>
</modules>

常用maven命令

首先进入pom.xml目录

  • mvn clean:清理
  • mvn compile:编译主程序
  • mvn test-compile:编译测试程序
  • mvn test:执行测试
  • mvn package:打包
  • mvn install:安装
  • mvn site:生成站点

自动部署

通过build标签配置当前工程的构建过程中的特殊设置,cargo插件。

spring boot入门

spring简介

简化spring开发流程,J2EE开发的一站式解决方案。

优点

  • 快速创建独立运行spring项目以及与主流框架集成
  • 使用嵌入式servlet容器,应用无需达成war包
  • starters自动依赖与版本控制
  • 大量的自动配置,简化开发,也可以修改默认值
  • 无需配置XML,无代码生成
  • 准生产环境的运行时应用监控
  • 与云计算天然集成

微服务

是一种架构风格,其认为一个应用应该是一组小型服务,可以用过HTTP的方式通信。

每一个功能元素最终都是一个可独立替换和独立升级的软件单元。

环境配置

spring-boot-starter

启动器,spring-boot官方提供了一系列启动器。将所有的功能场景抽取出来,只要在项目里面引入这些starter,相关依赖就会自动导入。

主程序类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* @SpringBootApplication标注这是spring boot应用
*/
@SpringBootApplication
public class HelloWorldMainApplication {

public static void main(String[] args){
//spring应用启动
SpringApplication.run(HelloWorldMainApplication.class, args);
}
}

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration//表示这是一个Spring Boot的配置类
@EnableAutoConfiguration//开启自动配置功能
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication

@SpringBootConfiguration:表示这是一个Spring Boot的配置类;
@Configuration:配置类上,表示配置类也是容器中的一个组件@Component

1
2
@AutoConfigurationPackage//自动配置包
@Import(EnableAutoConfigurationImportSelector.class)

spring-boot的注释没事可以看看。

spring的声明式事务控制

基于XML的声明式事务控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!--配置步骤-->
<!--配置事务管理器-->
<bean id="tansactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置事务的通知,此时需要导入事务的约束-->
<tx:advice id="txAdvice" transaction-manager="transactionManger"></tx:advice>
<!--配置事务的属性
isolation:用于指定事务的隔离等级,默认是DEFAULT,表示使用数据库的默认隔离等级;
propagation:用于指定事务的
-->
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" read-only="false"/></tx:method>
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/></tx:method>
</tx:attributes>
</tx:advice>
<!--配置AOP-->
<!--配置AOP中的通用切入点表达式-->
<!--建立食物通知和切入点表达式的对应关系-->
<!--配置事务的属性,在事物的通知tx:advice标签内-->
<aop:config>
<!--配置切入点表达式-->
<aop:pointcout id="pt1" execution(* com.service.impl.*.*(..))"></aop:pointcut>
<!--建立切入点表达式和事务通知的对应关系-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
</aop:config>

基于纯注解的声明式事务控制

  1. 配置事务管理器;
  2. 开启spring对注解事务的支持;
    • <tx:annotation-driven transaction-manager=”transactionManager”>
  3. 在需要事物支持的地方使用@Transactional

基于编程式事务控制

不够灵活

spring5新特性

  • 与JDK相关升级;
  • 核心容器更新;
  • JetBrains Kotlin语言支持;
    • 运行于在JVM上,独立语言;
  • 响应式编程风格;
  • Junit5支持;
  • 依赖类库的更新;

spring中的JdbctTemplate

是spring框架中提供的一个对象,是对原始Jdbc API对象的简单封装,spring框架提供了许多操作模板类。

  • 操作关系型数据
    • JdbcTemplate
    • HibernateTemplate
  • 操作nosql数据库
    • RedisTemplate
  • 操作消息队列
    • JmsTemplate

JdbcTemplate作用

和数据库交互的模板类

JdbcTemplate基本用法

首先通过XML文件配置必要信息,这块是spring框架必要的IOC手法;

1
2
3
4
5
6
7
8
9
10
11
<!--配置JdbcTemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/databasename"></property>
<property name="username" value="username"></property>
<property name="password" value="password"></property>
</bean>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//获取容器
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
//获取对象
JdbcTemplate jt = ac.getBean("jdbcTemplate", JdbcTemplate.class);
//执行操作
jt.execute("insert into account(name, money) values ('name', 222)");
//保存
jt.update("insert into account(name, money) values (?, ?)", "name", 333);
//更新
jt.update("update account set name=?, money=?, where id=?","test",2345,3);
//删除
jt.update("delete from account where id=?", 3);
//查询所有
List<Account> accounts = jt.query("select * from account where money > ?", new AccountRowMapper(), 1000f);
List<Account> accounts = jt.query("select * from account where money > ?", new BeanPropertyRowMapper<Account>(Account.class), 1000f);
for(Account account : accounts){
System.out.println(account);
}
//查询一个
List<Account> accounts = jt.query("select * from account where id = ?", new BeanPropertyRowMapper<Account>(Account.class), 1);
//查询返回一行一列(使用聚合函数,但是不加group by子句
Long count = jt.queryForObject("select count(*) from account where money > ?", Long.class, 1000f);

spring基于XML的AOP

配置步骤

  1. 把通知bean也交给spring管理;
  2. 使用aop:config标签表明开始AOP配置;
  3. 使用aop:aspect标签表明配置切面;
    • id属性:给切面提供一个唯一标识
    • ref属性:指定通知类bean的id
  4. 在aop:aspect标签的内部使用对应标签配置通知的类型;
    • aop:before:表示配置前置通知
      • method:用于指定切面中哪个方法是前置通知;
      • pointcut:用于指定切入点表达式,该表达式的含义是指对业务层中哪些方法进行增强
    • 切入点表达式的写法:
      • 关键字:execution(表达式)
      • 表达式:访问修饰符 返回值 类名.方法名(参数列表)
        • 访问修饰符可以省略
        • 返回值可以使用通配符,表示任意返回类型
        • 包名可以使用通配符,但包的层级需要和通配符一致
        • 包名可以使用..表示包名及其子包
        • 类名和方法名可以使用通配符
        • 全通配写法:* *..*.*(..)
1
2
3
4
5
6
7
8
9
<beans>
<bean id="accountService" class="com.service.impl.AccountServiceImpl></bean>
<bean id="logger" class="com.utils.Logger"></bean>
<aop:config>
<aop:aspect id="logAdvice" ref="logger">
<aop:before method="printlog" pointcut="execution(public void com.service.AccountServiceImpl.saveAccount())"></aop:before>
</aop:aspect>
</aop:config>
</beans>

四种常用通知类型

  • aop:before:前置通知,再切入点方法之前执行;
  • aop:after-returning:后置通知,在切入点方法正确执行之后执行,它和异常通知永远只有一个执行;
  • aop:after-throwing:异常通知,在切入点方法执行产生异常之后执行,它和后置通知永远只能执行一个;
  • aop:after:最终通知,无论切入点方法是否正确执行它都会在其后面执行;
  • aop:pointcut:配置切入点表达式,id属性用于指定表达式的唯一标识,expression属性用于指定表达式的内容;此标签写在aop:aspect内部时只能当前切面使用,将其写在aop:aspect外面时,所有前面可用;
  • aop:around:配置环绕通知;