springboot 基础

巩固基础,砥砺前行 。
只有不断重复,才能做到超越自己。
能坚持把简单的事情做到极致,也是不容易的。

SpringBoot JavaEE 简介

JavaEE的局限性:
1、过于复杂,JavaEE正对的是复杂的分布式企业应用,然而现实情况是大部分应用都是比较简单,复杂的架构带来了复杂的开发方式和部署方式。

2、最求分布式,大部分引用并非都是JavaEE 嘉定的分布式系统,Spring曾经反对过这种分布式架构,并只提供了容器管理,名词获得了成功,大型应用采用分布式架构不可避免,Spring提供了其他的技术支持,eg:RestFul架构

3、不能及时和流行开源技术整合,比如消息处理,除了有了标准的JMS支持,现在还有新能更好的RabbitMQ和kalfa。JavaEE 并没有与之相对应的标准,方二十Spring,具有统一的实现消息处理模式

4、JavaEE 应用服务器都有商业公司提供价格不菲,少有公司采用管理引用服务器和部署应用对初学者和自学者有一定门槛

Spring
Spring通过ioc管理bean,通过Aop方式增强bean功能,它没有像JavaEE那样纤细规定容器提供的是何种服务和容器运行的具体组件类型。

Spring的缺点
尽管Spring很强大,但是他也有JavaEE的缺点:

1、使用门槛升高,要入门spring需要较长时间

2、对过时技术支持,导致使用复杂度升高

3、xml配置已经不再是流行的系统配置方式

4、集成第三方工具的时候,程序员还要考虑工具之间的兼容性

5、系统启动慢,不具备热部署功能,完全依赖虚拟机或者web服务器的热部署

SpringBoot
springboot简化了spring应用配置,不需要配置就能就能运行spring应用,springboot管理spring容器、第三方插件,并提供了许多默认系统级的服务。大部分的spring应用,无论是简单还是复杂,都只需要少量的配置和代码就能完成。springboot通过starter来提供系统级别的服务。在使用的时候,在pom.xml中引入对应的starter即可使用。

相比于spring,springboot优点:

1、实现约定大于配置,是一个低配置的应用系统架构,不像spring那样需要大量的配置。仅仅需要少量的配置就能完成大量的功能

2、提供了内置的tomcat或者jetty功能

3、通过加载jar包管理、自动装配技术,容易支持与其他技术体系、工具集成

4、支持热加载,开发体检好,也支持springboot监控,方便了解系统运行情况。

springboot 配置、加载

加载外部类的几种方式

  1. 使用@Configuration + @Bean 的方式引入
  2. 使用@Configuration + @ImportResource 方式引入
  3. 使用@Configuration + @Import 方式引入

加载配置文件中的属性的方式

  1. @Value(“${}”) 加载单一的配置文件
person.last-name=张三3333333333${random.uuid}
application.properties 文件中
@Value("${person.last-name}")
private String lastName;
  1. 使用@Component、@ConfigurationProperties(prefix = “person”) 从全局的默认配置文件中加载属性
@Component
@ConfigurationProperties(prefix = "person")
public class Person {}application.properties文件中
person.last-name=张三3333333333${random.uuid}
person.age=${random.int}
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=${person.hello:hello}_dog
person.dog.age=15
  1. 使用 @Component、@ConfigurationProperties 、@PropertySource 三个注解 从指定位置加载属性
@PropertySource(value = {"classpath:person.properties"})
@Component
@ConfigurationProperties(prefix = "person")
public class Person {private String lastName;private Integer age;private Boolean boss;private Date birth;private Map<String,Object> maps;private List<Object> lists;private Dog dog;
}
classPath 路径下 person.properties 文件中
person.last-name=李四
person.age=12
person.birth=2017/12/15
person.boss=false
person.maps.k1=v1
person.maps.k2=14
person.lists=a,b,c
person.dog.name=dog
person.dog.age=15

profiles

application.yml 中的文档块模式


server:port: 8081
spring:profiles:active: prod  # 激活指定配置文件---
server:port: 8083
spring:profiles: dev---server:port: 8084
spring:profiles: prod  # 该文件被激活

在启动jar包的时候 动态指定jar的端口号

java -jar demo.jar --spring.profiles.active=dev

配置虚拟机参数

-Dspring.profiles.active=dev

在启动jar的时候指定外部的配置文件

 java -jar demo.jar --spring.config.location=G:/application.properties

配置文件的加载顺序

  1. 在相同位置的application.properties 和application.yml 配置文件的加载顺序:从上到下加载,谁在上就加载谁
application.propertiesserver.port=8082application.ymlserver:port: 8081

application.properties 在 application.yml 之上,所以启动的端口号 是8082

在这里插入图片描述

maven简介

maven实现的目标

  1. 是构建项目变得同意,maven屏蔽了构建的复杂过程
  2. 统一了构建下项目的方式,不同人、不同公司的羡慕都有同样的描述和构建项目的方式。maven通过pom.xml来描述项目,并提供了一系列插件来构建项目。
  3. 提出了一套开发项目的最佳实践。而不用每个项目都有不同机构和构建方式。比如源代码出现在scr/main/java中,测试代码出现在scr/main/test中,项目需要的配置文件放在scr/main/resources中
  4. 包含不同环境项目的构建方式
  5. 解决了依赖的问题,只要申明使用的类库,maven会自动冲仓库下载依赖的jar包,并能协助你管理jar之间的冲突

pom中元素介绍

groupId

表示项目所属的组,通常是一个公司或者组织的名称。如。org.springframework

artifactId

项目的唯一标识,如。spring-boot-start-web。groupId 和 artifactId 能唯一标识一个项目或者一个库,通常称之为项目坐标。

packaging

项目类型,常用的有jar和war两种

version

项目的版本号。通常来说,项目版本号分为三段,主版本、此版本、修订版本

主版本:代表脚骨变动或者不见同实现

次版本:是兼容性修改,功能增强

修订版:bug修复

modelVersion

代表pom文件的maven版本。

scope

scope 代表次类库和项目的关系,默认是compile,也就是编译和打包都需要此类库。

test:仅仅在单元测试的时候需要

provided:标识在编译阶段需要词此类库,但是打包不需要,因为项目的目标环境已经提供了

runtime:标识在编译和打包的时候都不需要,但是在运行的时候需要

build

此项目在pom中可选,build包含多个插件plugin,用来辅助构建项目


面试的时候,问过scope

spring boot 发送邮件

1.引入jar

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId>
</dependency>

2.application.yml配置

spring: mail: #发送消息的邮箱配置username: XXX@qq.com#password是QQ邮箱的授权码 password: snnaaprastgfdebghost: smtp.qq.comproperties: mail: smtp: ssl: enable: true

3.发送简单文本信息

@Autowired
JavaMailSenderImpl mailSender;public void testContext() {SimpleMailMessage message = new SimpleMailMessage();//邮件设置message.setSubject("Topic主题");message.setText("Message……");//发送到哪里message.setTo("XXX@163.com");//从哪里发送message.setFrom("XXX@qq.com");mailSender.send(message);
}

4.发送带有附件的


public void testAA() throws  Exception{//1、创建一个复杂的消息邮件MimeMessage mimeMessage = mailSender.createMimeMessage();MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);//邮件设置helper.setSubject("XXXX");helper.setText("<b style='color:red'>CCCC</b>",true);helper.setTo("15513@163.com");helper.setFrom("291506@qq.com");//上传文件helper.addAttachment("1.jpg",new File("C:\\Users\\DELL\\Pictures\\1.jpg"));helper.addAttachment("2.mp4",new File("C:\\\\Users\\\\DELL\\\\Pictures\\\\2.mp4"));mailSender.send(mimeMessage);}

springboot和redis缓存

redis缓存

1)在pom中新增

	<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>

2)在application.yml中新增redis配置.ookk

	spring: redis: host: localhost

3)配置redis序列化

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;@Configuration
public class MyRedisConfig {@Beanpublic RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(redisConnectionFactory);// 使用Jackson2JsonRedisSerialize 替换默认序列化Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper objectMapper = new ObjectMapper();objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(objectMapper);// 设置value的序列化规则和 key的序列化规则redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);redisTemplate.setKeySerializer(new StringRedisSerializer());redisTemplate.afterPropertiesSet();return redisTemplate;}
}
  1. java操作redis工具类
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
@SuppressWarnings(value = { "unchecked", "rawtypes" })
@Component
public class RedisCache
{@Autowiredpublic RedisTemplate redisTemplate;/*** 缓存基本的对象,Integer、String、实体类等** @param key 缓存的键值* @param value 缓存的值*/public <T> void setCacheObject(final String key, final T value){redisTemplate.opsForValue().set(key, value);}/*** 缓存基本的对象,Integer、String、实体类等** @param key 缓存的键值* @param value 缓存的值* @param timeout 时间* @param timeUnit 时间颗粒度*/public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit){redisTemplate.opsForValue().set(key, value, timeout, timeUnit);}/*** 设置有效时间** @param key Redis键* @param timeout 超时时间* @return true=设置成功;false=设置失败*/public boolean expire(final String key, final long timeout){return expire(key, timeout, TimeUnit.SECONDS);}/*** 设置有效时间** @param key Redis键* @param timeout 超时时间* @param unit 时间单位* @return true=设置成功;false=设置失败*/public boolean expire(final String key, final long timeout, final TimeUnit unit){return redisTemplate.expire(key, timeout, unit);}/*** 获得缓存的基本对象。** @param key 缓存键值* @return 缓存键值对应的数据*/public <T> T getCacheObject(final String key){ValueOperations<String, T> operation = redisTemplate.opsForValue();return operation.get(key);}/*** 删除单个对象** @param key*/public void deleteObject(final String key){redisTemplate.delete(key);}/*** 删除集合对象** @param collection 多个对象* @return*/public void deleteObject(final Collection collection){redisTemplate.delete(collection);}/*** 缓存List数据** @param key 缓存的键值* @param dataList 待缓存的List数据* @return 缓存的对象*/public <T> long setCacheList(final String key, final List<T> dataList){Long count = redisTemplate.opsForList().rightPushAll(key, dataList);return count == null ? 0 : count;}/*** 获得缓存的list对象** @param key 缓存的键值* @return 缓存键值对应的数据*/public <T> List<T> getCacheList(final String key){return redisTemplate.opsForList().range(key, 0, -1);}/*** 缓存Set** @param key 缓存键值* @param dataSet 缓存的数据* @return 缓存数据的对象*/public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet){BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);Iterator<T> it = dataSet.iterator();while (it.hasNext()){setOperation.add(it.next());}return setOperation;}/*** 获得缓存的set** @param key* @return*/public <T> Set<T> getCacheSet(final String key){return redisTemplate.opsForSet().members(key);}/*** 缓存Map** @param key* @param dataMap*/public <T> void setCacheMap(final String key, final Map<String, T> dataMap){if (dataMap != null) {redisTemplate.opsForHash().putAll(key, dataMap);}}/*** 获得缓存的Map** @param key* @return*/public <T> Map<String, T> getCacheMap(final String key){return redisTemplate.opsForHash().entries(key);}/*** 往Hash中存入数据** @param key Redis键* @param hKey Hash键* @param value 值*/public <T> void setCacheMapValue(final String key, final String hKey, final T value){redisTemplate.opsForHash().put(key, hKey, value);}/*** 获取Hash中的数据** @param key Redis键* @param hKey Hash键* @return Hash中的对象*/public <T> T getCacheMapValue(final String key, final String hKey){HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();return opsForHash.get(key, hKey);}/*** 获取多个Hash中的数据** @param key Redis键* @param hKeys Hash键集合* @return Hash对象集合*/public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys){return redisTemplate.opsForHash().multiGet(key, hKeys);}/*** 获得缓存的基本对象列表** @param pattern 字符串前缀* @return 对象列表*/public Collection<String> keys(final String pattern){return redisTemplate.keys(pattern);}
}

springboot本地缓存

缓存

本地缓存
1)启动类增加注解 @EnableCaching // 开启缓存
2)在service层代码中增加注解,进行测试
本地缓存使用的是currentHashMap

	```import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cache.annotation.CacheEvict;import org.springframework.cache.annotation.CachePut;import org.springframework.cache.annotation.Cacheable;import org.springframework.stereotype.Service;import com.ttzz.bean.Dog;import com.ttzz.mapper.DataDemo;@Service/*** @CacheConfig(cacheNames = {},cacheManager=AAAA,cacheResolver = {})*/public class DogService {@Autowiredprivate DataDemo dataDemo;/*** @Cacheable:先在缓存中查找,如果没有该缓存,则创建,查询数据,放入缓存,并返回数据* 			 参数:1)cacheNames/value:* 				 2)key:* 				 3)keyGenerator:* 				 4)cacheManager:* 				 5)condition:* 				 6)unless:	* 				 7)sync:*/@Cacheable(value = "dog",/*cacheNames = ,keyGenerator = ,condition = ,unless =  ,sync = true*/key = "#id")public Dog getById(String id) {return dataDemo.getById(id);}/*** @CachePut: 先调用目标方法,然后调用缓存信息*/@CachePut(value = "dog",key="#dog.id")public void save(Dog dog) {dataDemo.save(dog);}@CachePut(value = "dog",key="#dog.id")public void update(Dog dog) {dataDemo.update(dog);}/*** @CacheEvict:* allEntries:删除整个缓存中的数据* beforeInvocation:执行方法前删除还是执行方法后删除*/@CacheEvict(value = "dog" /* allEntries = true, beforeInvocation = true*/,key="#id")public void delete(String id) {dataDemo.delete(id);}/*** @Caching:复合注解* @Caching(cacheable = {@Cacheable(value = )},put = {@CachePut()})*/}```

SpringBoot以jar启动加载外部配置文件

SpringBoot以jar启动加载外部配置文件

通常需要将SpringBoot打成jar的方式来启动,有时候也需要将配置文件放到项目(jar)外。如何访问外部的配置文件呢?


使用以下命令来操作
命令1
java -jar XXX.jar -Dspring.config.location=D:\workspace-test\work02\seed-java\seed-framework\target\_config\application.yml
命令2
java -jar D:\workspace-test\work02\seed-java\seed-framework\target\XXX.jar -Dspring.config.location=D:\workspace-test\work02\seed-java\seed-framework\target\_config\application.yml -Dspring.profiles.active=test

SpringBoot 读取应用配置文件

springboot读取配置文件有三种方式
  1. 使用environment类,可以通过key-value的方式读取到application.properties中的数据
  2. 使用@value注解,使用spel表达式,注入属性值
  3. 使用@configurationProperties注解
environment

environment是一个通用的读取应用运行时的环境变量的类,可以读取application。properties,命令函输入参数、系统属性、操作系统环境变量等

@Autowired
private Environment env;

使用方法:env.getProperty(XXXX)

@value

直接通过@value注入一个配置信息到bean

@configurationProperties

该注解可以将同样类型的配置映射成为一个类,方便使用。一般和@Configuration注解配合使用。它和@value功能差不多,它不能读取yml文件中的属性信息,@value可以,@value支持spel表达式。

SpringBoot之Jackson注解

Jackson有多个注解,用来在序列化和反序列化操作

@JsonProperty("XXXX") //为key指定一个别名
private String aa;
@JsonIgnore("XXXX") //忽略此属性
private String aa;
@JsonIgnoreProperties({"XXXX","BBBB"}) //忽略多个属性,作用在类上
private class aa{}
@JsonFormat(pattern = "yyyy-mm-dd") //忽略此属性
private Date aa;

Jackson支持三种序列化和反序列化的方式

  1. 使用JsonParser来解析json,解析结果是一串tokens,采用jsonGenerator来生成json,这是最底层的方式
  2. 采用树遍历的方式 json被读入到jsonnode对象中,可以像操作xmldom那样读取json
  3. 采用dataBind方式,将实体类对象序列化成json,或者反序列化成实体对象,这是最简单的一种。对于应用程序来说最常用的是第三种。

SpringBoot Mock代码测试

增删改查代码


import java.net.URI;
import javax.annotation.Resource;import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.WebApplicationContext;@RunWith(SpringRunner.class)
@SpringBootTest(classes = XXXX.class)
@WebAppConfiguration
//配置事务的回滚,对数据库的增删改都会回滚,便于测试用例的循环利用
@Transactional(transactionManager = "transactionManager")
@Rollback(value = true)
public class BySpecimenControllerTest {@Autowiredprivate WebApplicationContext webApplicationContext;private MockMvc mockMvc;public String token;@Resourceprivate SysLoginService loginService;@Beforepublic void setupMockMvc() {mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
//        token = }@Testpublic void testDeleteBySpecimen () throws Exception{String id = "1";mockMvc.perform(MockMvcRequestBuilders.delete("/bySpecimens/delete/"+id)
//    		.header("Authorization", "Bearer "+token+"")).andExpect(MockMvcResultMatchers.status().isOk()).andDo(MockMvcResultHandlers.print());}@Testpublic void testFindBySpecimenById() throws Exception {String id = "1";mockMvc.perform(MockMvcRequestBuilders.get(new URI("/bySpecimens/info")).param("opertationId", id)).andExpect(MockMvcResultMatchers.status().isOk()).andDo(MockMvcResultHandlers.print());}@Testpublic void testFindBySpecimens () throws Exception{mockMvc.perform(MockMvcRequestBuilders.get("/bySpecimens/list")
//    			 .header("Authorization", "Bearer "+token+"")).andExpect(MockMvcResultMatchers.status().isOk()).andDo(MockMvcResultHandlers.print());}@Testpublic void testSaveBySpecimen() throws Exception {mockMvc.perform(MockMvcRequestBuilders.post("/bySpecimens/save")
//    	 		.header("Authorization", "Bearer "+token+"")// 标本标识.param("specimenId", "value") .param("status", "0") ).andExpect(MockMvcResultMatchers.status().isOk()).andDo(MockMvcResultHandlers.print());}@Testpublic void testUpdateBySpecimen () throws Exception {mockMvc.perform(MockMvcRequestBuilders.put("/bySpecimens/save")
//   	 			.header("Authorization", "Bearer "+token+"")// 标本标识.param("specimenId", "1") .param("status", "1") ).andExpect(MockMvcResultMatchers.status().isOk()).andDo(MockMvcResultHandlers.print());}}
使用实体作为参数,需要在Controller 的参数 使用@RequestBody 标记A domain = new A();//设置参数//domain.setString jsonStr = JSONObject.toJSONString(domain);mockMvc.perform(MockMvcRequestBuilders.put("/As/save").header("Authorization", "Bearer "+token+"").accept(MediaType.APPLICATION_JSON_UTF8).contentType(MediaType.APPLICATION_JSON_UTF8).content(jsonStr)).andExpect(MockMvcResultMatchers.status().isOk()).andDo(MockMvcResultHandlers.print());

SpringBoot+Mybatis 实现多数据源配置(基于分包管理)、Swagger配置

1.本文主要是基于分包管理来实现多数据源的方式,简单易用
2.Swagger配置

pom.xml配置

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>XXX</groupId><artifactId>XXX</artifactId><version>0.0.1-SNAPSHOT</version><name>sXXX</name><description>XXX</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.13.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><java.version>1.8</java.version><mybatis-plus.version>3.1.2</mybatis-plus.version><pagehelper.spring.boot.starter.version>1.2.5</pagehelper.spring.boot.starter.version><druid.version>1.1.17</druid.version><jwt.version>0.9.1</jwt.version><fastjson.version>1.2.60</fastjson.version><swagger.version>2.9.2</swagger.version><commons.version>2.6</commons.version><bitwalker.version>1.19</bitwalker.version><guava.version>26.0-jre</guava.version><commons.io.version>2.5</commons.io.version><oshi.version>3.9.1</oshi.version><seed.common.version>0.0.1-SNAPSHOT</seed.common.version><oracle.version>12.1.0.2</oracle.version></properties><dependencies><!-- https://mvnrepository.com/artifact/org.apache.clerezza.ext/org.json.simple --><dependency><groupId>org.apache.clerezza.ext</groupId><artifactId>org.json.simple</artifactId><version>0.4</version></dependency><!--常用工具类 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><!--io常用工具类 --><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId></dependency><!-- poi --><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.15</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.15</version></dependency><!-- 解析客户端操作系统、浏览器等 --><dependency><groupId>eu.bitwalker</groupId><artifactId>UserAgentUtils</artifactId></dependency><!-- 获取系统信息 --><dependency><groupId>com.github.oshi</groupId><artifactId>oshi-core</artifactId></dependency><dependency><groupId>net.java.dev.jna</groupId><artifactId>jna</artifactId></dependency><dependency><groupId>net.java.dev.jna</groupId><artifactId>jna-platform</artifactId></dependency><!--Spring框架基本的核心工具--><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></dependency><!-- pagehelper 分页插件 --><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><exclusions><exclusion><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId></exclusion><exclusion><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId></exclusion></exclusions></dependency><!-- oracle 驱动 --><dependency><groupId>com.oracle</groupId><artifactId>ojdbc7</artifactId><version>12.1.0.2</version></dependency><!-- mysql 驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.46</version></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-core</artifactId><version>5.1.8.RELEASE</version><scope>compile</scope></dependency><!-- 引入freeMarker的依赖包. --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency><dependency><groupId>net.hasor</groupId><artifactId>hasor-spring</artifactId><version>4.1.3</version></dependency><dependency><groupId>net.hasor</groupId><artifactId>hasor-dataway</artifactId><version>4.1.3-fix20200414</version><!-- 4.1.3 包存在UI资源缺失问题 --></dependency><!-- 集成SpringMvc框架并实现自动配置 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><!-- Redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-pool2</artifactId></dependency><!-- mybatis-plus --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>${mybatis-plus.version}</version></dependency><!-- druid --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>${druid.version}</version></dependency><!-- json --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>${fastjson.version}</version></dependency><!-- oracle驱动 --><!--<dependency><groupId>com.oracle</groupId><artifactId>ojdbc7</artifactId><version>${oracle.version}</version></dependency>--><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- Swagger API文档 --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>${swagger.version}</version><exclusions><exclusion><groupId>io.swagger</groupId><artifactId>swagger-annotations</artifactId></exclusion><exclusion><groupId>io.swagger</groupId><artifactId>swagger-models</artifactId></exclusion></exclusions></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>${swagger.version}</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-bean-validators</artifactId><version>${swagger.version}</version></dependency><!-- 防止进入swagger页面报类型转换错误,排除2.9.2中的引用,手动增加1.5.22版本 --><dependency><groupId>io.swagger</groupId><artifactId>swagger-annotations</artifactId><version>1.5.22</version></dependency><dependency><groupId>io.swagger</groupId><artifactId>swagger-models</artifactId><version>1.5.22</version></dependency><!-- 测试单元 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><!-- pagehelper 分页插件 --><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>${pagehelper.spring.boot.starter.version}</version></dependency><!--io常用工具类 --><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>${commons.io.version}</version></dependency><!-- 解析客户端操作系统、浏览器等 --><dependency><groupId>eu.bitwalker</groupId><artifactId>UserAgentUtils</artifactId><version>${bitwalker.version}</version></dependency><!-- 获取系统信息 --><dependency><groupId>com.github.oshi</groupId><artifactId>oshi-core</artifactId><version>${oshi.version}</version></dependency></dependencies></dependencyManagement></project>

多数据源配置代码

1.主数据源配置

@Primary 标注的是主数据源

import javax.sql.DataSource;import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;@Configuration
@MapperScan(basePackages = {"包路径.mapper.数据库标识1mapper" }, annotationClass = Mapper.class, sqlSessionFactoryRef = "数据库标识1SqlSessionFactory")
public class 数据库标识1MybatisConfig {/*** @return 返回DataSource对象*/@Bean(name = "数据库标识1DataSource")@Qualifier("数据库标识1DataSource")@ConfigurationProperties(prefix = "spring.datasource.数据库标识1")@Primarypublic DataSource cmsDataSource() {return DataSourceBuilder.create().build();}@Bean(name = "数据库标识1SqlSessionFactory")@Primarypublic SqlSessionFactory sqlSessionFactory(@Qualifier("数据库标识1DataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSource);sqlSessionFactoryBean.setMapperLocati数据库标识1(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/数据库标识1mapper/*.xml"));return sqlSessionFactoryBean.getObject();}@Bean(name = "数据库标识1PlatformTransactionManager")public PlatformTransactionManager transactionManager(@Qualifier("数据库标识1DataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}@Bean("数据库标识1SqlSessionTemplate")// 表示这个数据源是默认数据源@Primarypublic SqlSessionTemplate test1sqlsessiontemplate(@Qualifier("数据库标识1SqlSessionFactory") SqlSessionFactory sessionfactory) {return new SqlSessionTemplate(sessionfactory);}
}

2.第二个数据源配置

如何扩展 第三、第四数据源呢?
(1)复制第二数据源配置类,简单修改注解中的名称
(2)在resource的mapper文件夹下创建XXXmapper,用来存放XXXXMapper.xml文件
特别注意没有primary修饰了哦

import javax.sql.DataSource;import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;@Configuration
@MapperScan(basePackages = {"包路径.mapper.数据库标识2mapper" }, annotationClass = Mapper.class, sqlSessionFactoryRef = "数据库标识2SqlSessionFactory")
public class 数据库标识2MybatisConfig {/*** @return 返回DataSource对象*/@Bean(name = "数据库标识2DataSource")@Qualifier("数据库标识2DataSource")@ConfigurationProperties(prefix = "spring.datasource.数据库标识2")public DataSource cmsDataSource() {return DataSourceBuilder.create().build();}@Bean(name = "数据库标识2SqlSessionFactory")@Primarypublic SqlSessionFactory sqlSessionFactory(@Qualifier("数据库标识2DataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSource);sqlSessionFactoryBean.setMapperLocati数据库标识2(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/数据库标识2mapper/*.xml"));return sqlSessionFactoryBean.getObject();}@Bean(name = "数据库标识2PlatformTransactionManager")public PlatformTransactionManager transactionManager(@Qualifier("数据库标识2DataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}@Bean("数据库标识2SqlSessionTemplate")// 表示这个数据源是默认数据源@Primarypublic SqlSessionTemplate test1sqlsessiontemplate(@Qualifier("数据库标识2SqlSessionFactory") SqlSessionFactory sessionfactory) {return new SqlSessionTemplate(sessionfactory);}
}

resource下application.yml 中的数据源信息配置信息

spring:profiles: active: devmvc: static-path-pattern: /**resource: static-locations: classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/datasource:
#数据库标识1数据源配置数据库标识1: jdbc-url: jdbc:mysql://ip:3306/d1?useUnicode=true&characterEncoding=utf8&useSSL=falseusername: XXXpassword: XXXmaxActive: 50initialSize: 10maxWait: 60000minIdle: 1timeBetweenEvictionRunsMillis: 60000minEvictableIdleTimeMillis: 300000maxOpenPreparedStatements: 2type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.jdbc.Driverfilters: statvalidationQuery: select version()testWhileIdle: truetestOnBorrow: falsetestOnReturn: falsepoolPreparedStatements: true
#数据库标识2数据源配置数据库标识2:jdbc-url: jdbc:oracle:thin:@ip:1521:XXXusername: XXXpassword: XXXmaxActive: 50initialSize: 5maxWait: 60000minIdle: 1timeBetweenEvictionRunsMillis: 60000minEvictableIdleTimeMillis: 300000maxOpenPreparedStatements: 2type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: oracle.jdbc.OracleDriverfilters: statvalidationQuery: select * from dualtestWhileIdle: truetestOnBorrow: falsetestOnReturn: falsepoolPreparedStatements: true

Swagger类配置 SwaggerConfig.java

import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.Contact;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableSwagger2
public class SwaggerConfig {/*** 创建API*/@Beanpublic Docket createRestApi() {return new Docket(DocumentationType.SWAGGER_2).enable(true).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)).paths(PathSelectors.any()).build()/* 设置安全模式,swagger可以设置访问token */.securitySchemes(securitySchemes()).securityContexts(securityContexts());}/*** 安全模式,这里指定token通过Authorization头请求头传递*/private List<ApiKey> securitySchemes() {List<ApiKey> apiKeyList = new ArrayList<ApiKey>();apiKeyList.add(new ApiKey("Authorization", "Authorization", "header"));return apiKeyList;}/*** 安全上下文*/private List<SecurityContext> securityContexts() {List<SecurityContext> securityContexts = new ArrayList<>();securityContexts.add(SecurityContext.builder().securityReferences(defaultAuth()).forPaths(PathSelectors.regex("^(?!auth).*$")).build());return securityContexts;}/*** 默认的安全上引用*/private List<SecurityReference> defaultAuth() {AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];authorizationScopes[0] = authorizationScope;List<SecurityReference> securityReferences = new ArrayList<>();securityReferences.add(new SecurityReference("Authorization", authorizationScopes));return securityReferences;}/*** 添加摘要信息*/private ApiInfo apiInfo() {// 用ApiInfoBuilder进行定制return new ApiInfoBuilder()// 设置标题.title("XXXX_接口文档")// 描述.description("XXXX所有API接口")// 作者信息.contact(new Contact("XXXX", null, null))// 版本.version("版本号:1.0" ).build();}
}

SpringBoot引入外部jar,并将项目打包成jar包,引发项目运行失败的问题

SpringBoot引入外部jar,并将项目打包成jar包

正常打包操作
  • 在src/main/resource 目录下创建一个lib文件夹,将需要打如到项目中的jar放在这里
  • 通过build path 将这些jar加入到工程中,以方便调用
  • 在pom.xml中增加,其中xxx看实际情况而定
	<dependencies><dependency><groupId>XXX</groupId><artifactId>XXX</artifactId><version>XXX</version><scope>system</scope><systemPath>${project.basedir}/src/main/resources/lib/XXX.jar</systemPath></dependency></dependencies>
  • 在pom.xml中增加build 逻辑
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><includeSystemScope>true</includeSystemScope></configuration></plugin></plugins><resources><resource><directory>lib</directory><targetPath>BOOT-INF/lib/</targetPath><includes><include>**/*.jar</include></includes></resource><resource><directory>src/main/resources</directory><targetPath>BOOT-INF/classes/</targetPath></resource></resources></build>
特别注意: 上面的build中的代码仅仅是在打包的时候打开,在运行项目的时候,需要将上面的代码注释掉。不然会报错:找不到XXXMapper.xml mybatis对应的xml文件。

【转载】springboot引入外部依赖jar包


今天项目(springboot项目)中需要导入外部的jar包,在打包的时候需要将外部jar打到项目中。就这一个问题,CSDN中有好多的提示的文章。真TM傻逼啊,发文章之前,自己就不测试一下吗?自己在网上随便找一个案例,正好满足自己的要求,就直接用了,标题都TM不调整一下,也不看看人家的标题和你自己写的是不是一个意思。误人子弟。

正解文件连接:

springboot引入外部依赖jar包_springboot引入外部jar包_半山惊竹的博客-CSDN博客

RestTemplateUtil 工具类

两个系统之间做数据交互,一般都是使用接口的方式,在SpringBoot中提供了一个RestTemplate类,方便调用。

以下是一个简单封装,方便使用
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;import com.alibaba.fastjson.JSONObject;import lombok.extern.slf4j.Slf4j;@Slf4j
public class RestTemplateUtil {/*** restTemplate 发送post请求* @param restTemplate* @param url* @param json* @return*/public static ResponseEntity<String> getRestTemplatePost(RestTemplate restTemplate,String url,String json){HttpHeaders headers = new HttpHeaders();headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));headers.setContentType(MediaType.APPLICATION_JSON_UTF8);HttpEntity<String> requestEntity = new HttpEntity<String>(json,headers);ResponseEntity<String> entity = restTemplate.postForEntity(url, requestEntity, String.class);return entity;}/*** restTemplate 发送get请求* @param restTemplate* @param url* @param json* @return*/public static ResponseEntity<String> getRestTemplateGet(RestTemplate restTemplate,String url,String json){HttpHeaders headers = new HttpHeaders();headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));headers.setContentType(MediaType.APPLICATION_JSON_UTF8);HttpEntity<String> requestEntity = new HttpEntity<String>(json,headers);ResponseEntity<String> entity = restTemplate.getForEntity(url, String.class,json);return entity;}public static Map<String, String> parseResponseEntity(ResponseEntity<String> entity) {Map<String,String> map = new HashMap<String,String>();log.info("ResponseEntity="+JSONObject.toJSONString(entity));Integer code = entity.getStatusCodeValue();if(entity.getStatusCodeValue()==200) {JSONObject obj = JSONObject.parseObject(entity.getBody());map.put("code", code+"");map.put("data", obj.getString("data").toString());}log.info(JSONObject.toJSONString(map));return map;}}

关于@Transactional 的sao操作

关于@Transactional 作用的一些测试

    • SpringBoot JavaEE 简介
    • springboot 配置、加载
      • 加载外部类的几种方式
      • 加载配置文件中的属性的方式
      • profiles
        • 在启动jar包的时候 动态指定jar的端口号
        • 配置虚拟机参数
        • 在启动jar的时候指定外部的配置文件
      • 配置文件的加载顺序
    • maven简介
        • maven实现的目标
        • pom中元素介绍
          • groupId
          • artifactId
          • packaging
          • version
        • modelVersion
        • scope
        • build
    • spring boot 发送邮件
      • 1.引入jar
      • 2.application.yml配置
      • 3.发送简单文本信息
      • 4.发送带有附件的
    • springboot和redis缓存
      • redis缓存
    • springboot本地缓存
      • 缓存
    • SpringBoot以jar启动加载外部配置文件
  • SpringBoot以jar启动加载外部配置文件
          • 使用以下命令来操作
            • 命令1
            • 命令2
    • SpringBoot 读取应用配置文件
          • springboot读取配置文件有三种方式
            • environment
            • @value
            • @configurationProperties
    • SpringBoot之Jackson注解
        • Jackson支持三种序列化和反序列化的方式
    • SpringBoot Mock代码测试
    • SpringBoot+Mybatis 实现多数据源配置(基于分包管理)、Swagger配置
      • pom.xml配置
      • 多数据源配置代码
        • 1.主数据源配置
        • 2.第二个数据源配置
        • resource下application.yml 中的数据源信息配置信息
      • Swagger类配置 SwaggerConfig.java
    • SpringBoot引入外部jar,并将项目打包成jar包,引发项目运行失败的问题
            • 正常打包操作
            • **特别注意:** 上面的build中的代码仅仅是在打包的时候打开,在运行项目的时候,需要将上面的代码注释掉。不然会报错:找不到XXXMapper.xml mybatis对应的xml文件。
    • 【转载】springboot引入外部依赖jar包
    • RestTemplateUtil 工具类
            • 以下是一个简单封装,方便使用
    • 关于@Transactional 的sao操作
      • case1 无try catch、无嵌套,没有加 rollbackFor = Exception.class 事务正常回滚
      • case2 无try catch、无嵌套,加 rollbackFor = Exception.class 事务正常回滚
      • case3 没有加 rollbackFor = Exception.class 事务没有回滚
      • case4 有try catch、无嵌套,加 rollbackFor = Exception.class 事务没有回滚
      • case5 有try catch、无嵌套,加 rollbackFor = Exception.class ,抛出异常 。 事务正常回滚
      • case6 有try catch、无嵌套,加 rollbackFor = Exception.class ,抛出异常。方法调用,事务没有回滚
      • case7 事务没有回滚
      • case8 事务回滚
      • case9 事务回滚
      • case10 事务未回滚
      • case11 事务回滚
      • case12 事务未回滚
      • case13 事务回滚
      • case14 事务回滚
      • case15 事务回滚
    • dynamic-datasource 使用

在使用@Transactional  关键字的时候,总会有这样 或者 那有的问题。一下做一些测试来验证问题

case1 无try catch、无嵌套,没有加 rollbackFor = Exception.class 事务正常回滚

@Transactionalpublic int testSave()  {User user = new User();user.setName("岳不群2");user.setAge(70);user.setEmail("lucy@qq.com");userMapper.insert(user);int m = 1/0;return 1;}

case2 无try catch、无嵌套,加 rollbackFor = Exception.class 事务正常回滚

@Transactional(rollbackFor = Exception.class)public int testSave()  {User user = new User();user.setName("岳不群2");user.setAge(70);user.setEmail("lucy@qq.com");userMapper.insert(user);int m = 1/0;return 1;}

case3 没有加 rollbackFor = Exception.class 事务没有回滚

@Transactionalpublic int testSave()  {try {User user = new User();user.setName("岳不群2");user.setAge(70);user.setEmail("lucy@qq.com");userMapper.insert(user);int m = 1/0;return 1;} catch (Exception e) {// TODO: handle exception}return 0;}

case4 有try catch、无嵌套,加 rollbackFor = Exception.class 事务没有回滚

@Transactional(rollbackFor = Exception.class)public int testSave()  {try {User user = new User();user.setName("岳不群2");user.setAge(70);user.setEmail("lucy@qq.com");userMapper.insert(user);int m = 1/0;return 1;} catch (Exception e) {// TODO: handle exception}return 0;}

case5 有try catch、无嵌套,加 rollbackFor = Exception.class ,抛出异常 。 事务正常回滚

@Transactional(rollbackFor = Exception.class)public int testSave() throws Exception  {try {User user = new User();user.setName("岳不群2");user.setAge(70);user.setEmail("lucy@qq.com");userMapper.insert(user);int m = 1/0;return 1;} catch (Exception e) {throw new Exception(e.getMessage());}}

case6 有try catch、无嵌套,加 rollbackFor = Exception.class ,抛出异常。方法调用,事务没有回滚

public int testSave() throws Exception {return testSave2();}@Transactional(rollbackFor = Exception.class)public int testSave2() throws Exception  {try {User user = new User();user.setName("岳不群2");user.setAge(70);user.setEmail("lucy@qq.com");userMapper.insert(user);int m = 1/0;return 1;} catch (Exception e) {System.out.println(e.getMessage());throw new Exception(e.getMessage());}}

case7 事务没有回滚

@Transactionalpublic int testSave() throws Exception {return testSave2();}@Transactional(rollbackFor = Exception.class)public int testSave2() throws Exception  {try {User user = new User();user.setName("岳不群2");user.setAge(70);user.setEmail("lucy@qq.com");userMapper.insert(user);int m = 1/0;return 1;} catch (Exception e) {System.out.println(e.getMessage());throw new Exception(e.getMessage());}}

case8 事务回滚

@Transactional(rollbackFor = Exception.class)public int testSave() throws Exception {return testSave2();}public int testSave2() throws Exception  {try {User user = new User();user.setName("岳不群2");user.setAge(70);user.setEmail("lucy@qq.com");userMapper.insert(user);int m = 1/0;return 1;} catch (Exception e) {System.out.println(e.getMessage());throw new Exception(e.getMessage());}}

case9 事务回滚

@Transactional(rollbackFor = Exception.class)public int testSave() throws Exception {return testSave2();}@Transactional(rollbackFor = Exception.class)public int testSave2() throws Exception  {try {User user = new User();user.setName("岳不群2");user.setAge(70);user.setEmail("lucy@qq.com");userMapper.insert(user);int m = 1/0;return 1;} catch (Exception e) {System.out.println(e.getMessage());throw new Exception(e.getMessage());}}

case10 事务未回滚

@Transactionalpublic int testSave() throws Exception {return testSave2();}@Transactional(rollbackFor = Exception.class)public int testSave2() throws Exception  {try {User user = new User();user.setName("岳不群2");user.setAge(70);user.setEmail("lucy@qq.com");userMapper.insert(user);int m = 1/0;return 1;} catch (Exception e) {System.out.println(e.getMessage());throw new Exception(e.getMessage());}}

case11 事务回滚

@Transactional(rollbackFor = Exception.class)public int testSave() throws Exception {return testSave2();}@Transactionalpublic int testSave2() throws Exception  {try {User user = new User();user.setName("岳不群2");user.setAge(70);user.setEmail("lucy@qq.com");userMapper.insert(user);int m = 1/0;return 1;} catch (Exception e) {System.out.println(e.getMessage());throw new Exception(e.getMessage());}}

case12 事务未回滚

@Transactional(rollbackFor = Exception.class)public int testSave() throws Exception {return testSave2();}@Transactionalpublic int testSave2()  {try {User user = new User();user.setName("岳不群2");user.setAge(70);user.setEmail("lucy@qq.com");userMapper.insert(user);int m = 1/0;return 1;} catch (Exception e) {System.out.println(e.getMessage());}return 0;}

case13 事务回滚

@Transactional(rollbackFor = Exception.class)public int testSave() throws Exception {int m =  testSave2();int n = 1/0;return m;}@Transactionalpublic int testSave2()  {try {User user = new User();user.setName("岳不群2");user.setAge(70);user.setEmail("lucy@qq.com");userMapper.insert(user);return 1;} catch (Exception e) {System.out.println(e.getMessage());}return 0;}

case14 事务回滚

@Transactional(rollbackFor = Exception.class)public int testSave() throws Exception {int m =  testSave2();int n = 1/0;return m;}public int testSave2()  {try {User user = new User();user.setName("岳不群2");user.setAge(70);user.setEmail("lucy@qq.com");userMapper.insert(user);return 1;} catch (Exception e) {System.out.println(e.getMessage());}return 0;}

case15 事务回滚

@Transactional(rollbackFor = Exception.class)public int testSave() throws Exception {int m =  testSave2();int n = 1/0;return m;}@Transactional(rollbackFor = Exception.class)public int testSave2()  {try {User user = new User();user.setName("岳不群2");user.setAge(70);user.setEmail("lucy@qq.com");userMapper.insert(user);return 1;} catch (Exception e) {System.out.println(e.getMessage());}return 0;}

dynamic-datasource 使用

1)在项目中引入dynamic-datasource该modul
2)在application.yml中添加

dynamic:datasource:slave1: driver-class-name: oracle.jdbc.OracleDriverurl: jdbc:oracle:thin:XXX:orcl_tjhusername: XXpassword: XXvalidation-query: SELECT 1 FROM DUALslave2: driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/XXX?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghaiusername: XXXXpassword: XXXX
  1. 在项目中使用,dynamic 配置的都是子数据源。
    在访问的service 方法上 使用@DataSource(数据源表示);如上的slave1

【临渊羡鱼不如退而结网】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/88589.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

现代无人机技术

目录 1.发展 2.应用领域 3.对战争的影响 4.给人类带来的福利 5.给人类带来的坏处 1.发展 无人机的发展可以分为以下几个关键步骤&#xff1a; 1. 早期试验和研究&#xff1a;20世纪初&#xff0c;飞行器的概念开始出现&#xff0c;并进行了一些早期的试飞和实验。这些尝试包…

马来西亚的区块链和NFT市场调研

马来西亚的区块链和NFT市场调研 基本介绍 参考&#xff1a; https://zh.wikipedia.org/wiki/%E9%A9%AC%E6%9D%A5%E8%A5%BF%E4%BA%9A zz制度&#xff1a;联邦议会制 语言文字&#xff1a; 马来语 民族&#xff1a; 69.4%原住民&#xff08;土著&#xff09;&#xff0c;23.2%…

[HDLBits] Exams/m2014 q3

Consider the function f shown in the Karnaugh map below. Implement this function. d is dont-care, which means you may choose to output whatever value is convenient. //empty

【网络基础实战之路】实现RIP协议与OSPF协议间路由交流的实战详解

系列文章传送门&#xff1a; 【网络基础实战之路】设计网络划分的实战详解 【网络基础实战之路】一文弄懂TCP的三次握手与四次断开 【网络基础实战之路】基于MGRE多点协议的实战详解 【网络基础实战之路】基于OSPF协议建立两个MGRE网络的实验详解 PS&#xff1a;本要求基于…

Labview控制APx(Audio Precision)进行测试测量(七)

处理集群控制子集 大多数用户不会想要设置所有的控制包括在一个大的控制集群&#xff0c;如水平和增益配置控制。例如&#xff0c;假设您只在 APx 中使用模拟不平衡输出连接器&#xff0c;而您想要做的就是控制发电机的电平和频率。在这种情况下&#xff0c;水平和增益配置集群…

一休休的面试题

重点面试题(今天又看了很多的博客大概有个三十来篇吧所以总结了一休休的面试题)&#xff1a; ps:已经入秋了为什么还是这么热&#xff01;&#xff01;&#xff01; 1、受管 bean 的生命周期 对于普通的 Java 对象&#xff0c;new 的时候会去创建对象&#xff0c;而当它没有…

记录--用css画扇形菜单

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 1、效果图 用手机录屏再用小程序转换的gif&#xff0c;可能精度上有点欠缺。 2、实现过程 1、观察及思考 开始编码前我们首先观察展开后的结构&#xff1a;两个四分之一的圆加三个圆形菜单项。 文章名…

Tomcat的动静分离以及多实例部署

一、动静分离 Nginx实现负载均衡的原理&#xff1a; Nginx实现负载均衡是通过反向代理实现Nginx服务器作为前端&#xff0c;Tomcat服务器作为后端&#xff0c;web页面请求由Nginx服务来进行转发。 但不是把所有的web请求转发&#xff0c;而是将静态页面请求Ncinx服务器自己来处…

【C++起飞之路】初级—— auto、范围for循环、宏函数和内联函数

auto、范围for、内联函数、宏函数和nullptr 一、auto — 类型推导的魔法&#xff08;C 11)1、auto 是什么&#xff1f;2、工作原理3、优势4、限制和注意事项 二、范围for (C11)1、基本语法2、优势3、工作原理4、注意事项5、C11&#xff1a; 范围 for 循环的扩展&#xff1a; 三…

如何预防ssl中间人攻击?

当我们连上公共WiFi打开网页或邮箱时&#xff0c;殊不知此时可能有人正在监视着我们的各种网络活动。打开账户网页那一瞬间&#xff0c;不法分子可能已经盗取了我们的银行凭证、家庭住址、电子邮件和联系人信息&#xff0c;而这一切我们却毫不知情。这是一种网络上常见的“中间…

刨根问底,不再纠结Linux 文件权限问题

Linux 与Windows的区别 与Windows 系统不一样&#xff0c;在Linux系统中&#xff0c;无论是系统内核还是应用程序&#xff0c;都是文件。正如此&#xff0c;当你学习Linux中遇到问题时&#xff0c;总能看到热心网友的解决方法&#xff1a; rm -rf * 一旦运行此命令&#x…

Maven 基础学习及使用

Maven1 Maven简介1.1 Maven模型1.2 仓库 2 Maven安装配置3 Maven基本使用3.1 Maven 常用命令3.2 Maven 生命周期 4 IDEA使用Maven4.1 IDEA配置Maven环境4.2 Maven 坐标详解4.3 IDEA 创建 Maven项目4.4 IDEA 导入 Maven项目 5 依赖管理5.1 使用坐标引入jar包5.2 依赖范围 Maven …

STM32的电动自行车信息采集上报系统(学习)

摘要 针对电动自行车实时监管不便的问题&#xff0c;设计了一种基于STM32的电动自行车信息采集系统&#xff0c;通过获取电池、位置和行驶状态信息并上报到服务器中&#xff0c;实现实时监管。 通过多路串口请求电池、行驶状态和位置信息&#xff0c;以并发方式进行数据接收、…

块、行内块水平垂直居中

1.定位实现水平垂直居中 <div class"outer"><div class"test inner1">定位实现水平垂直居中</div></div><style>.outer {width: 300px;height: 300px;border: 1px solid gray;margin: 100px auto 0;position: relative;}.te…

Redis集群(三十七)

部署搭建Redis主从复制、哨兵模式、集群部署 目录 一、Redis主从复制 &#xff08;一&#xff09;概念 &#xff08;二&#xff09;作用 &#xff08;三&#xff09;缺点 &#xff08;四&#xff09;流程 &#xff08;五&#xff09;搭建 二、Redis哨兵模式 &#xff0…

软件测试基础篇——MySQL

MySQL 1、数据库技术概述 数据库database&#xff1a;存放和管理各种数据的仓库&#xff0c;操作的对象主要是【数据data】&#xff0c;科学的组织和存储数据&#xff0c;高效的获取和处理数据SQL&#xff1a;结构化查询语言&#xff0c;专为**关系型数据库而建立的操作语言&…

ORB-SLAM2第二节---双目地图初始化

比起单目初始化&#xff0c;而双目实现地图的初始化非常简单&#xff0c;只需要一帧&#xff08;左右目图像&#xff09;即可完成初始化。 行特征点统计。考虑用图像金字塔尺度作为偏移量&#xff0c;在当前点上下正负偏移量&#xff08;r)内的纵坐标值都认为是匹配点可能存在…

【MySQL】并发执行事务可能存在的问题, 事务的四种隔离级别

文章目录 前言一、并发执行事务可能存在的问题1, 脏读问题2, 不可重复读3, 幻读 二、MySQL 的四种隔离级别1, READ UNCOMMITTED 读未提交2, READ COMMITTED 读已提交3, REPEATABLE READ 可重复读 (MySQL 的默认事务隔离级别)4, SERIALIZABLE 串行化 总结 前言 各位读者好, 我是…

web会话跟踪以及JWT响应拦截机制

目录 JWT 会话跟踪 token 响应拦截器 http是无状态的&#xff0c;登录成功后&#xff0c;客户端就与服务器断开连接&#xff0c;之后再向后端发送请求时&#xff0c;后端需要知道前端是哪个用户在进行操作。 JWT Json web token (JWT), 是为了在网络应用环境间传递声明而…

WebAPIs 第三天

DOM 事件进阶 事件流事件委托其他事件元素尺寸与位置 一.事件流 事件流与两个阶段说明事件捕获事件冒泡阻止冒泡解绑事件 1.1 事件流与两个阶段说明 ① 事件流&#xff1a;指的是事件完整执行过程中的流动路径 ② 事件流分为捕获阶段和冒泡阶段 1.2 事件捕获 从DOM根元素…