默认8小时–>没请求,断开连接
修改配置,避免断开连接
sql方式
interactive_timeout wait_timeout
set global
配置文件方式
80小时没请求就断开
[mysqld]
interactive_timeout =288000
wait_timeout=288000
在代码里加入一个日志打印,悄悄的把每个步骤的耗时打印出来,自己看一看,然后看看核心流程的时间耗时多长,有没有优化的空间
线程数默认为
1

java代码方式
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;@Configuration
public class ScheduleConfig {@Beanpublic TaskScheduler getTaskScheduler() {ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();taskScheduler.setPoolSize(5);//taskScheduler.getActiveCount();return taskScheduler;}
}
Spring默认包扫描机制:SpringApplication—>所在包及其子包下的所有目录
@ComponentScan
@ComponentScan(value = {"com.example"})
默认:首字母
小写,其他不变
若开头第一个字母大写,第二个字母也大写,则不变,即名称为原类名
需要成为Spring容器中的实例,才可以@Autowired
@Autowired:默认按类型注入
@Resource:默认byName
@Primary:存在多个相同的Bean,则@Primary用于定义首选项
没办法解决@Autowired
private UserService userService;
无法解决该Bean完成实例化后,对该Bean的操作
对所有的Bean的
postProcessBeforeInitialization、postProcessAfterInitialization进行操作
spring容器创建后,beanFactory代指spring容器
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;@Component
public class TestBean implements InitializingBean {@Override// 当前Bean初始化后,还没有注入属性,只会调用一次 3public void afterPropertiesSet() throws Exception {System.out.println("TestBean------>afterPropertiesSet");}
}@Component
class PostProcessor implements BeanPostProcessor {@Override//在Bean初始化前 2public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (!(bean instanceof TestBean)) return bean;System.out.println("TestBean------>postProcessBeforeInitialization");return bean;}@Override//完成Bean的初始化,并且已经注入属性 4public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (!(bean instanceof TestBean)) return bean;System.out.println("TestBean------>postProcessAfterInitialization");return bean;}}@Component
class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Override//在BeanPostProcessor之前执行 1public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)throws BeansException {BeanDefinition testBean = beanFactory.getBeanDefinition("testBean");// 设置怎样定义beantestBean.setScope(BeanDefinition.SCOPE_SINGLETON);System.out.println("TestBean------>TestBeanFactoryPostProcessor");}
}

org.springframework.boot spring-boot-starter-test 2.7.3
junit junit 4.13 test
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;@SpringBootTest
@RunWith(SpringRunner.class)
class DemoApplicationTests {@Testpublic static void test(String name) {System.out.println(name);}}
org.springframework.boot spring-boot-starter-web
org.springframework spring-tx 5.3.22
import org.springframework.transaction.annotation.Transactional;
@Transactional
被spring容器管理!!@Component必须支持事务,如InnoDB 支持事务,MyISAM不支持!只对抛出的 RuntimeException 异常有效// Exception.class 是所有异常的父类
@Transactional(rollbackFor={RuntimeException.class, Exception.class})
此时事务
不生效
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Component
public class TestBean {public void test() {testTransactional();}@Transactionalpublic void testTransactional() {}}
解决方法
启动类加@EnableAspectJAutoProxy
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@SpringBootApplication
@EnableAspectJAutoProxy //必须加注解
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}
修改后代码
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Component
public class TestBean {public void test() {//事务想要生效,还得利用代理来生效!!!//获取代理对象(proxy)// 启动类加上 @EnableAspectJAutoProxyTestBean proxy = (TestBean) AopContext.currentProxy();proxy.testTransactional();}@Transactionalpublic void testTransactional() {}}
手动回滚import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;@Component
public class TestBean {@Transactionalpublic void testTransactional(User user) {try {save(user);} catch (Exception ex) {ex.printStackTrace();// 手动标记回滚TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}}private void save(User user) {}}
User user=null;
public static void main(String[] args) {List userList = null;testFor(userList);}public static void testFor(List users) {if (users == null) return;for (User user : users) {}}
if(user==null) {return xxx;
}
if(user!=null){//业务代码
}
for (int i = 0; i < 100; i++) { }
//注意判空
for (User user : users) { }
==比较equals判断时,要重写equals方法extends,接口用implements使用 BigDecimal 表示和计算浮点数,且务必使用字符串的构造方法来初始化 BigDecimal:
//加
System.out.println(new BigDecimal("0.1").add(new BigDecimal("0.2")));
//减
System.out.println(new BigDecimal("1.0").subtract(new BigDecimal("0.8")));
//乘
System.out.println(new BigDecimal("4.015").multiply(new BigDecimal("100")));
//除
System.out.println(new BigDecimal("123.3").divide(new BigDecimal("100")));//BigDecimal.valueOf() 初始化也可以!
System.out.println(BigDecimal.valueOf(1.0).subtract(BigDecimal.valueOf(0.8)));
//0.2

//Returns:
//-1, 0, or 1 as this BigDecimal is numerically less than, equal to, or greater than val.
System.out.println(new BigDecimal("1.0").compareTo(new BigDecimal("1"))==0);
//trueSystem.out.println(new BigDecimal("1.0").equals(new BigDecimal("1")))
//结果:false
//long的最大值
System.out.println(Long.MAX_VALUE);
// +1 之后溢出,成为long的最小值-9223372036854775808
System.out.println(Long.MAX_VALUE+1==Long.MIN_VALUE);
//long的最大值+1, 使用 BigInteger 防止溢出!!
System.out.println(new BigInteger(String.valueOf(Long.MAX_VALUE)).add(BigInteger.valueOf(1)));

// scale 需要与小数位匹配BigDecimal bigDecimal = new BigDecimal("12.222");// 若设置的精度 比 以前的高,会自动补0// BigDecimal res = bigDecimal.setScale(12);//ROUND_HALF_UP 为四舍五入BigDecimal res = bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP);System.out.println(res);
//除不尽 会抛异常
// System.out.println(new BigDecimal("2").divide(new BigDecimal("3")));System.out.println(new BigDecimal("2.0").divide(new BigDecimal("3"), 2, BigDecimal.ROUND_HALF_UP));

代码
//时间格式化器DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");//获取 当前时间LocalDateTime localDateTime = LocalDateTime.now();System.out.println(localDateTime);System.out.println(formatter.format(localDateTime));//指定 时间LocalDateTime _1970 = LocalDateTime.of(1970, 1, 1, 0, 0, 0);System.out.println(_1970);//时间格式化器LocalDateTime---->String,调用format方法String _1970_str = formatter.format(_1970);System.out.println(_1970_str);// 获取该月的第几天int dayOfMonth = localDateTime.getDayOfMonth();System.out.println(dayOfMonth);// 将字符串解析为 LocalDateTime对象LocalDateTime _2010 = LocalDateTime.parse("2010-01-01 00:00:00", formatter);System.out.println(_2010);//1970年1月1日 +10日LocalDateTime _1970_plus10days = _1970.plusDays(10);System.out.println(_1970_plus10days);//1970年1月1日 -10日LocalDateTime _1970_minus10days = _1970.minusDays(10);System.out.println(_1970_minus10days);//修改1970年1月1日的DayOfMonth,即为1970年1月20日LocalDateTime _1970_setDayofMonth_10 = _1970.withDayOfMonth(20);System.out.println(_1970_setDayofMonth_10);//LocalDateTime转为LocalDate--->只有年月日// LocalTime--->只有时分秒LocalDate localDate = localDateTime.toLocalDate();System.out.println(localDate);//1970-1-1 00:00:00_1970 = LocalDateTime.of(1970, 1, 1, 0, 0, 0, 0);// 1970年到 现在的时间间隔// 年,一共多少个月,与天数,天数 仅仅在31天Period _1970_now_period = Period.between(_1970.toLocalDate(), localDateTime.toLocalDate());System.out.println(_1970_now_period.toTotalMonths());System.out.println(_1970_now_period.getDays()); //22-1System.out.println(_1970_now_period.getYears());//获取两个时间的间隔,总的天数,Duration between = Duration.between(_1970, LocalDateTime.now());System.out.println(between.toHours());System.out.println(between.toDays());System.out.println(between.toMillis() - 28800000L);System.out.println(System.currentTimeMillis());//isAfter(xx)在xx之后//isBefore(xx)在xx之前System.out.println(localDateTime.isAfter(_1970));System.out.println(localDateTime.isBefore(_1970));
//new 出来一个 格式化器SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");// 当前时间转为字母串String now = format.format(new Date());System.out.println(now);// 将字符串转为时间String date = "2022-12-30";try {Date parseDate = format.parse(date);System.out.println(parseDate);} catch (ParseException e) {e.printStackTrace();}// 时间转为 时间戳long time = format.parse(date).getTime();System.out.println(time);System.out.println(System.currentTimeMillis());
pom
org.springframework.boot spring-boot-starter-web
org.projectlombok lombok
cn.hutool hutool-all 5.8.7
org.apache.httpcomponents httpclient 4.5.13
DateConverter
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;import java.text.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;@Component
public class DateConverter extends SimpleDateFormat implements Converter {public static final List FORMARTS = new ArrayList<>();static {FORMARTS.add("yyyy-MM");FORMARTS.add("yyyy-MM-dd");FORMARTS.add("yyyy-MM-dd HH:mm");FORMARTS.add("yyyy-MM-dd HH:mm:ss");}@Overridepublic Date convert(String source) {String value = source.trim();if ("".equals(value)) {return null;}if (source.matches("^\\d{4}-\\d{1,2}$")) {return parseDate(source, FORMARTS.get(0));} else if (source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")) {return parseDate(source, FORMARTS.get(1));} else if (source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}$")) {return parseDate(source, FORMARTS.get(2));} else if (source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$")) {return parseDate(source, FORMARTS.get(3));} else if (isTimestamp(source)) {//long 时间戳转换return parseDate(source, FORMARTS.get(3));} else {throw new IllegalArgumentException("Invalid boolean value '" + source + "'");}}/*** 格式化日期** @param dateStr String 字符型日期* @param format String 格式* @return Date 日期*/public Date parseDate(String dateStr, String format) {Date date = null;//long 时间戳转换if (isTimestamp(dateStr)) {long time = Long.parseLong(dateStr);date = new Date(time);}try {DateFormat dateFormat = new SimpleDateFormat(format);date = dateFormat.parse(dateStr);} catch (Exception e) {}return date;}public static boolean isNumeric(String str) {Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");return pattern.matcher(str).matches();}public static boolean isTimestamp(String str) {return str != null && str.length() == 13 && isNumeric(str);}@Overridepublic Date parse(String source) throws ParseException {Date convert = this.convert(source);return convert;}//设置所有接口返回的时间为毫秒级的时间戳@Overridepublic StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition pos) {StringBuffer stringBuffer = new StringBuffer("" + date.getTime());return stringBuffer;
// return super.format(date, toAppendTo, pos);}}
DateConverterConfig
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;@Configuration
public class DateConverterConfig {@Autowiredprivate DateConverter dateConverter;@Bean@Primarypublic ObjectMapper objectMapper() {ObjectMapper objectMapper = new ObjectMapper();objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);objectMapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);objectMapper.setDateFormat(dateConverter);return objectMapper;}
}
支持这四种格式 + 13位时间戳

返回的时间为毫秒级的时间戳
getDeclaredMethod获取 不到Method涉及到的 所有对象都
必须实现Serializable接口
@Overrideprotected User clone() throws CloneNotSupportedException {User user = null;try {ByteArrayOutputStream baos = new ByteArrayOutputStream();//ObjectOutputStream是包装流ObjectOutputStream oos = new ObjectOutputStream(baos);//写入到 baos流中oos.writeObject(this);//将流序列化成对象ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bais);User o = (User) ois.readObject();} catch (IOException | ClassNotFoundException e) {e.printStackTrace();}return user;}