SpringBoot学习笔记

核心


idea配置热重启服务器
  1. pom.xml添加
    <dependency>
    	<groupId>org.springframework.boot</groupId>
    	<artifactId>spring-boot-devtools</artifactId>
    	<scope>runtime</scope>
    	<optional>true</optional>
    </dependency>
    
  2. 组合键Ctrl+Shift+Alt+/,选择Registry,勾选complier.automake.allow.when.app.running
  3. File-Settings-Compiler-Build Project automatically
开闭原则 OCP 扩展开放 修改封闭

面向抽象编程实现可维护代码
面向对象主要做两件事:实例化对象调用方法

解决方法优缺点
inteface接口统一方法的调用不能统一对象的实例化
工厂模式不稳定是常态,把不稳定的代码隔离在一起,保证其他代码是稳定的 简单普通抽象工厂
IOC/DI当处理不稳定的代码非常强大,我们就认为这个容器是稳定的.我们向工厂要依赖对象,容器直接给我们一个对象通过反射实现任意类的实例化
View层常用注解

@Lazy延迟注入
@ResponseBody 将JavaBean对象序列化为json对象写入responseBody返回给前端
@ConfigurationProperties 指定前缀 默认注入到类中Map类型字段
@PathVariable 获取url中参数{xxx}
@RequestParam 获取url中?xxx参数
@RequestBody获取Post请求中body
@RequestHeader 获取请求头 value=“请求头名”

发现机制

注入方式
  1. 属性注入
  2. 构造函数注入
  3. setter注入,可以在静态方法中注入Bean对象
    @Component
    public class GenericAndJson {
        private static ObjectMapper mapper;
        @Autowired
        public void setMapper(ObjectMapper mapper) {
            GenericAndJson.mapper = mapper;
        }
    
  4. @Configuration注解 xml变为注解方式
    @Configuration
    public class HeroConfiguration{
      @Bean
      public ISkill camille(){
          return new Camille();
      }
    }
    
多个实现类选择机制
  • 被动注入法方式 先根据类型 后根据名字
  • 主动注入方式 策略模式 @Qualifier @Primary
  • 条件注解 @Conditional+org.springframe.Condition接口
    常用成品提供注解有@ConditionalOnProperty
特殊注入方法
  • component+实现特定接口

    @Component
    public class AutoPrefixConfiguration implements WebMvcRegistrations {
        @Override
        public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
            return new AutoPrefixUrlMapping();
        }
    }
    
  • 添加特定注解 eg.@ControllerAdvice

  • @Autowtred属性注入不能注入静态属性,要想在静态方法中调用Ioc当中的对象,采用setter注入

    @Component
    public class GenericAndJson {
        private static ObjectMapper mapper;
        @Autowired
        public void setMapper(ObjectMapper mapper) {
            GenericAndJson.mapper = mapper;
        }
    
配置文件注入方法
  • 在配置类中@PropertySource(value = “classpath:config/exception-code.properties”) 将配置文件和类进行关联
  • @ConfigurationProperties(prefix = “li”) 指定配置文件中字段的前缀
    @ConfigurationProperties(prefix = "li")
    @PropertySource(value = "classpath:config/exception-code.properties")
    @Component
    public class ExceptionCodeConfiguration {
        private Map<Integer,String> codes = new HashMap<>();
    }
    
  • @Value("${}") 直接从application.properties读取配置
统一异常处理 已知异常 未知异常
  1. 实现类上打上@ControllerAdvice注解
  2. 方法打上@ExceptionHandler(value = Exception.class)指定监控异常类
    @ControllerAdvice
    public class GlobalExceptionAdvice {
        @ExceptionHandler(value = Exception.class)
        public UnifyResponse handleException(HttpServletRequest req, Exception e) {}
    }
    UnifyResponse响应实体结构为
    {
    	code:10001
    	message:XXXX
    	request:GET url
    }
    
根据目录结构自动生成路由前缀

实现类是AutoPrefixConfiguration和AutoPrefixUrlMapping
通过反射获取类绝对路径,配置文件指定api根目录,在映射url时注入AutoPrefixUrlMapping干预

public class AutoPrefixUrlMapping extends RequestMappingHandlerMapping {
    @Value("${missyou.api-package}")
    private String apiPackagePath;
    @Override
    protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
        RequestMappingInfo mappingInfo = super.getMappingForMethod(method, handlerType);
        if (mappingInfo != null) {
            String prefix = getPrefix(handlerType);
            return RequestMappingInfo.paths(prefix).build().combine(mappingInfo);
        }
        return mappingInfo;
    }
    private String getPrefix(Class<?> handleType) {
        String packageName = handleType.getPackage().getName();
        String dotPath = packageName.replaceAll(this.apiPackagePath, "");
        return dotPath.replace(".", "/");
    }
}
注入的类类型

SpringBean注入默认为单例类型,用法类似于静态方法。要注入多例对象
将业务类作为一个普普通通的java类,不加上@Component注解,使用的时候手动new出来,需要的对象通过构造函数传过来。这样很多Spring特性就无法使用,不推荐这种方法。还可以用

在类上调用的时候
加@Scope(value = “prototype”)多个实例注入
加@Scope(value = “prototype”)参数注入
加@Scope(value = “prototype”)@Autowired private ObjectFactory t
加@Scope(value = “prototype”, proxyMode = ScopedProxyMode.TARGET_CLASS)@Autowired private T t

加入IOC容器的类默认调用的是无参构造方法,即便是有参的构造函数,参数也是加入到IOC容器的对象,Spring不能管理不在IOC容器中的对象。

自动配置原理

SPI思想 Service Provider Interface 模块装配

  1. @SpringBootApplication注解主要有@ComponentScan包扫描注解和@EnableAutoConfiguration自动装配注解
  2. 在@EnableAutoConfiguration中有@Import(AutoConfigurationImportSelector.class)
    他实现了selectImportspublic String[] selectImports(AnnotationMetadata annotationMetadata)方法
  3. 根据spring.factories使用条件注解加载模块从而实现自动装配

业务调用模式
业务实现基于interface 策略模式+配置文件
自动装配解决的是如何将SDK作为Bean加入到容器中

Ioc容器中Bean的生命周期

BeanPostProcessor 在bean的生命周期间做一些操作。
postProcessBeforeInitialization()在初始化之前
postProcessAfterInitialization()在初始化之后 例如对权限注解上的信息进行收集
执行构造方法
注入BeanName
注入BeanFactory
注入ApplicationContext
@Autowired(依赖注入)
执行BeanPostProcessor的postProcessBeforeInitialization方法
执行postConstruct注解方法
执行InitializingBean的afterPropertiesSet方法
执行bean定义的initMethod方法
执行BeanPostProcessor的postProcessAfterInitialization方法

ApplicationContext事件监听

ApplicationListener 初始化或者刷新是,权限发生了变化进行更新

AOP

@Transactional注解
声明式事务管理,使用在类或接口实现方法上,实际使用了JDBC的事务DataSourceTransactionManager 来进行事务控制的。Spring 关闭数据库中自动提交:在方法执行前关闭自动提交,方法执行完毕后再开启自动提交,若超过一定时间没有提交,就回滚。
事务的隔离级别:是指若干个并发的事务之间的隔离程度。
事务传播行为:如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。

Lombok常用注解


注解名作用
@Getter@Setter生成属性的get和set
@RequiredArgsConstructor生成属性加了@NonNull的构造方法
@NoArgsConstructor无参构造方法
@Buildernew对象可以链式传参,一定配合@Getter
@AllArgsConstructor生成带有所有属性的构造方法

参数校验 BeanValidation


Hibernate-Validator实现了JSR-303

命名用法
@Validjava规范命名Controller类和参数为DTO类前
@ValidatedHibernate实现命名级联私有属性上

一些基础注解 @Max(value=10) @Range(min=1,max=10) @Positive检查元素是否严格为正
自定义校验器

对象关系设计


实体类常用注解
  1. @Entity(name=“sql语句表名的别名,默认为类名”)
  2. @Table(name=“数据库中表名,默认为类名”)
  3. @GeneratedValue(strategy="主键的生成方式mysql一定用GenerationType.IDENTITY")
  4. @Column(name=“数据库中列名,默认会把驼峰命名变为小写下划线”,
  5. columnDefinition=“字段约束直接放在sql语句中”)
  6. @ColumnDefault(“设置默认值”) 这只是约束.实体类还要设置默认值
  7. @JoinColumn(name=“外键在表中的名字”,referencedColumnName=“关联表主键在表中的名字”)
  8. @MappedSuperclass 指定此类是实体类的基类,其中的字段可以查询映射到model
  9. @Column(insertable = false,updatable = false) 加上此注解的字段在更新和插入时会忽略此字段。create_time,update_time是有数据库进行赋值的,程序不应该更改他,程序虽然没管它但给数据库传null他也认为是一个值,造成错误
对象关系注解
  1. @OneToMany@ManyToOne("mappedBy=“双向关系中维持关系的实体类对象字段名,剔除关系的实体类对象字段上加此注解”)
DTO VO

DO、VO、PO,POJO,DTO
DTO 前端传给后端
VO 后端传给前端
PO 业务层向控制层传输可以外延成业务层对象
DAO 数据层向业务层返回的数据

Bean对象拷贝

实际开发中,会有大量的DTO,VO等Bean对象互相转换,用setter方法一个个设值太麻烦,可以使用DozerMapper,BeanUtils等工具

  1. 使用BeanUtils.copyProperties(Object source, Object target)浅拷贝
  2. 使用DozerMapper深拷贝
    <dependency>
                <groupId>com.github.dozermapper</groupId>
                <artifactId>dozer-spring-boot-starter</artifactId>
                <version>6.5.0</version>
    </dependency>
    
    注入后就可以直接使用mapper.map(Object source, Class destinationClass)
fastjson序列化和双向关系JPA导致Infinite recursion (StackOverflowError)

在使用SpringDataJpa或者hibernate框架时,向前端返回Json数据,序列化时会造成循环调用导致栈溢出,解决的方法有

  1. 双方都有@Entity注解,在One方类加上@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,property = "id"),property默认是@id,要改为id,即主键的名字
  2. 增加VO视图模型层,将要序列化的字段重新实例化,就可以切断JPA的影响,这样数据重复性可能很大,
  • 以后尝试@JsonView

网上有很多说用@JsonIgnore@JsonManagedReference@JsonBackReference但这些都要忽略某个属性不进行序列化,但我的项目需要所有属性序列化
hibernate中因双向依赖而造成的json怪相
Jackson JSON - Using @JsonIdentityInfo to handle circular references

Jackson小写下划线与驼峰格式转换

在application.properties增加

spring.jackson.property-naming-strategy=SNAKE_CASE

@JsonProperty(“属性序列化别名”)#

双向关系使用Lombok注解会导致StackOverflowError

使用@ToString @EqualsAndHashCode @Data导致栈溢出
在@Many方或子方添加@ToString(exclud={“指向父方或@One方属性名”})

SpringDataJpa分页设计
  1. 使用start和count算出显示第几页,一页有多少数据,
  2. 使用PageRequest.of()创建分页对象,第一个参数是页码,第二个是一页有多少条数据,第三个是按照某字段进行倒叙排列,返回的是实现Pageable接口的对象
  3. Page为分页结果,他包含当前数据有多少条,总数量,当前页码,一共有多少页
  4. 构造VO层Paging对象返回前端,利用属性拷贝将数据库对象转换成VO对象
Pageable page = PageRequest.of(pageNum,size, Sort.by("createTime").descending());
return spuRepository.findAll(page);

SpringDataJpa使用手册

实体属性类型转换器

插入数据库时,转为json字符串,查询出来后转为对象

  1. 主要实现AttributeConverter类和使用@Converter@Convert注解
  2. 另一种方法覆盖属性的get和set方法,使用工具类GenericAndJson进行转换

部署jar到Linux

https://github.com/nodejs/help/wiki/Installation
https://www.cnblogs.com/linck/p/11574704.html

事务不等于加锁

IDEA快捷键

###IDEA快捷键
ctrl+H 查看类层级关系
ctrl+p 参数列表
ctrl+alt+v 类型推断
ctrl+o 覆盖或实现方法
alt+7 类结构视图 ctrl+r12
ctrl+alt+鼠标左键 跳转到实现
idea properties文件乱码
ctrl+ 减号 折叠代码
idea database插件和jpa关联
idea自动生成jpa实体类
logging.level.com.li.missyou=debug 控制台开启debug指定包范围
ctrl+W 选中单词 行

待办

  • 内联 懒加载
  • 查询
  • Optional 类
  • 静态资源服务器
  • 源码阅读Spring Data Jpa 分页类 Page
  • 模板校验jsr303
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值