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.mzph.cn/news/36451.shtml

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

相关文章

爬虫如何应对网站的反爬机制?如何查找user-agent对应的值

import requestsurl https://movie.douban.com/top250 response requests.get(url) # 查看结果 print(response)在requests使用一文中我们有讲到&#xff0c;当状态码不是200时表示爬虫不可用&#xff0c;也就是说我们获取不到网页源代码。但是我们还是可以挣扎一下&#xff…

一文秒懂HTTP协议到底是什么?原理?

目录 1.什么是http协议&#xff1f; 2.http协议的版本&#xff1f; 3.http文本框架 4.http请求报文 5.http报文格式 6.http响应报文 7.HTTP的状态码 8.HTTP首部介绍 9.什么是URL和URI&#xff1f; 10.CGI是什么&#xff1f; 1.什么是http协议&#xff1f; http&#…

测试架构师如何落地性能测试方案(一)

背景描述&#xff1a; 最近刚接手一个新项目&#xff0c;在最开始的时候要求对这个项目做性能测试&#xff0c;产品经理也给不出性能需求&#xff0c;只因为这个项目是电商项目&#xff0c;可能会有高并发&#xff0c;秒杀的场景&#xff0c;所以产品经理要求我们对这个项目必…

STM32基于CubeIDE和HAL库 基础入门学习笔记:物联网项目开发流程和思路

文章目录&#xff1a; 第一部分&#xff1a;项目开始前的计划与准备 1.项目策划和开发规范 1.1 项目要求文档 1.2 技术实现文档 1.3 开发规范 2.创建项目工程与日志 第二部分&#xff1a;调通硬件电路与驱动程序 第三部分&#xff1a;编写最基础的应用程序 第四部分&…

opencv带GStreamer之Windows编译

目录 1、下载GStreamer和安装2. GSTReamer CMake配置3. 验证是否配置成功 1、下载GStreamer和安装 下载地址如下&#xff1a; gstreamer-1.0-msvc-x86_64-1.18.2.msi gstreamer-1.0-devel-msvc-x86_64-1.18.2.msi 安装目录无要求&#xff0c;主要是安装完设置环境变量 xxx\1…

【css】渐变

渐变是设置一种颜色或者多种颜色之间的过度变化。 两种渐变类型&#xff1a; 线性渐变&#xff08;向下/向上/向左/向右/对角线&#xff09; 径向渐变&#xff08;由其中心定义&#xff09; 1、线性渐变 语法&#xff1a;background-image: linear-gradient(direction, co…

springboot结合element-ui实现增删改查,附前端完整代码

实现功能 前端完整代码 后端接口 登录&#xff0c;注册&#xff0c;查询所有用户&#xff0c;根据用户名模糊查询&#xff0c;添加用户&#xff0c;更新用户&#xff0c;删除用户 前端 注册&#xff0c;登录&#xff0c;退出&#xff0c;用户增删改查&#xff0c;导航栏&#…

Android Sutdio 导入libs文件夹下的jar包没反应

有点离谱&#xff0c;笨笨的脑子才犯的错误 首先发现问题&#xff1a;转移项目的时候 直接复制粘贴libs文件夹下的jar包到新项目&#xff0c;在build.gradle文件下 使用语句并应用也没反应&#xff08;jar包没有出现箭头且代码报错&#xff0c;找不到&#xff09; implementa…

什么样的 PLC 可以算是高端 PLC?

针对问题本身&#xff0c;有的回答里都提到了。可靠性&#xff0c;扫描时间&#xff0c;带离散量点数&#xff0c;带模拟量输出点数&#xff0c;扩展性&#xff0c;这些都可以看作PLC系统级别划分的依据。比如说&#xff0c;有相应安全完整性等级认证的LOGIC SOLVER为核心的PLC…

五个独特且有趣的ChatGPT指令

今天分享5个很实用的指令&#xff0c;这几个指令很多时候对我们输出内容的连贯性、文章风格、创意性等方面有着决定性的作用。 目录 第一个&#xff1a;Max tokens&#xff08;最大令牌&#xff09; 第二个&#xff1a;Top_p(控制采样) 第三个&#xff1a;Presence_penalty …

Android Studio System.out.println()中文乱码

第一步&#xff1a; 打开studio64.exe.vmoptions加入-Dfile.encodingUTF-8 第二步&#xff1a; File-Settings-Editor-File Encodings 把所有的编码格式改为UTF-8 尝试跑一下代码&#xff0c;如果还不行&#xff0c;重启IDE 再试试。

UI美工设计岗位的工作职责

UI美工设计岗位的工作职责1 职责&#xff1a; 1、负责软件界面的美术设计、创意工作和制作工作; 2、根据各种相关软件的用户群&#xff0c;提出构思新颖、有高度吸引力的创意设计; 3、对页面进行优化&#xff0c;使用户操作更趋于人性化; 4、维护现有的应用产品; 5、收集和…

NLP文本匹配任务Text Matching [无监督训练]:SimCSE、ESimCSE、DiffCSE 项目实践

NLP文本匹配任务Text Matching [无监督训练]&#xff1a;SimCSE、ESimCSE、DiffCSE 项目实践 文本匹配多用于计算两个文本之间的相似度&#xff0c;该示例会基于 ESimCSE 实现一个无监督的文本匹配模型的训练流程。文本匹配多用于计算两段「自然文本」之间的「相似度」。 例如…

一百五十三、Kettle——Linux上安装的kettle9.3启动后说缺少libwebkitgtk-1.0(真是坑爹啊,刚龟速下载又忍痛卸载)

一、问题 在kettle9.3可以在本地连接hive312后&#xff0c;在Linux中安装了kettle9.3&#xff0c;结果启动时报错WARNING: no libwebkitgtk-1.0 detected, some features will be unavailable 而且如果直接下载libwebkitgtk的话也没有用 [roothurys22 data-integration]# yu…

在线吉他调音

先看效果&#xff08;图片没有声&#xff0c;可以下载源码看看&#xff0c;比这更好~&#xff09;&#xff1a; 再看代码&#xff08;查看更多&#xff09;&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8&quo…

【第二阶段】kotlin的函数类型作为返回类型

fun main() {//调用,返回的是一个匿名类型&#xff0c;所以info就是一个匿名函数val infoshow("",0)//info接受的返回值为匿名类型&#xff0c;此时info就是一个匿名函数println(info("kotlin",20)) }//返回类型为一个匿名函数的返回类型fun show(name:Str…

01 - 工作区、暂存区、版本库、远程仓库 - 以一次连贯的提交操作为例

查看所有文章链接&#xff1a;&#xff08;更新中&#xff09;GIT常用场景- 目录 文章目录 1. 工作区、暂存区、版本库、远程仓库1.1 工作区1.2 工作区 > 暂存区&#xff1a;git add1.3 暂存区 > 版本库&#xff1a;git commit1.4 push到远程仓库 1. 工作区、暂存区、版本…

【生成式AI】ProlificDreamer论文阅读

ProlificDreamer 论文阅读 Project指路&#xff1a;https://ml.cs.tsinghua.edu.cn/prolificdreamer/ 论文简介&#xff1a;截止2023/8/10&#xff0c;text-to-3D的baseline SOTA&#xff0c;提出了VSD优化方法 前置芝士:text-to-3D任务简介 text-to-3D Problem text-to-3D…

解决校园网使用vmware桥接模式,虚拟机与物理机互相ping通,但是虚拟机ping不通百度的问题

遇到的问题 使用校园网时&#xff0c;桥接模式下&#xff0c;物理机可以ping通虚拟机&#xff0c;但是虚拟机ping不通主机 解决方法 在物理机中查看网络相关信息 ipconfig 修改虚拟机网卡信息 vim /etc/sysconfig/network-scripts/ifcfg-ens33 注意 /ifcfg-ens33需要根据…

C++ QT(一)

目录 初识QtQt 是什么Qt 能做什么Qt/C与QML 如何选择Qt 版本Windows 下安装QtLinux 下安装Qt安装Qt配置Qt Creator 输入中文配置Ubuntu 中文环境配置中文输入法 Qt Creator 简单使用Qt Creator 界面组成Qt Creator 设置 第一个Qt 程序新建一个项目项目文件介绍项目文件*.pro样式…