天天看点

后端备忘录

idea常用插件

lomdok

restfultoolkit

database tools and sql

easycode

Rainbow Brackets

Alibaba Java Coding Guidelines

plantuml integration

Maven Helper

FindBugs

free mybatis

sonarlint

jsonFormat

Key promoter X

lomdok

import lombok.Data;
import lombok.ToString;
@Setter
@Getter
@ToString
@EqualsAndHashCode
构造函数
		@NoArgsConstructor, 
	@RequiredArgsConstructor 
	(@NonNull将标注这个字段不应为null)

@Data
	等于同时使用
	@Getter, @Setter, @ToString, @EqualsAndHashCode,@RequiredArgsConstructor
//常用@Data, @ToString


Spring注解
	@Null  被注释的元素必须为null
	@NotNull  被注释的元素不能为null
	@AssertTrue  被注释的元素必须为true
	@AssertFalse  被注释的元素必须为false
	@Min(value)  被注释的元素必须是一个数字,其值必须大于等于指定的最小值
	@Max(value)  被注释的元素必须是一个数字,其值必须小于等于指定的最大值
	@DecimalMin(value)  被注释的元素必须是一个数字,其值必须大于等于指定的最小值
	@DecimalMax(value)  被注释的元素必须是一个数字,其值必须小于等于指定的最大值
	@Size(max,min)  被注释的元素的大小必须在指定的范围内。
	@Digits(integer,fraction)  被注释的元素必须是一个数字,其值必须在可接受的范围内
	@Past  被注释的元素必须是一个过去的日期
	@Future  被注释的元素必须是一个将来的日期
	@Pattern(value) 被注释的元素必须符合指定的正则表达式。
	@Email 被注释的元素必须是电子邮件地址
	@Length 被注释的字符串的大小必须在指定的范围内
	@NotEmpty  被注释的字符串必须非空
	@Range  被注释的元素必须在合适的范围内
           

Spring映射

@GetMapping 用于将HTTP get请求映射到特定处理程序的方法注解

具体来说,@GetMapping是一个组合注解,是@RequestMapping(method = RequestMethod.GET)的缩写。

@PostMapping 用于将HTTP post请求映射到特定处理程序的方法注解

具体来说,@PostMapping是一个组合注解,是@RequestMapping(method = RequestMethod.POST)的缩写。

@PutMapping 更新

@DeleteMapping 删除

添加@RestController,默认类的方法都会以json返回

Spring concept

Spring Cloud 构建于 Spring Boot 之上,在 Spring Boot 中有两种上下文,一种是 bootstrap, 另外一种是 application, bootstrap 是应用程序的父上下文,也就是说 bootstrap 加载优先于 applicaton。bootstrap 主要用于从额外的资源来加载配置信息,还可以在本地外部配置文件中解密属性。这两个上下文共用一个环境,它是任何Spring应用程序的外部属性的来源。bootstrap 里面的属性会优先加载,它们默认也不能被本地相同配置覆盖。

对比 application 配置文件,bootstrap 配置文件具有以下几个特性。

boostrap 由父 ApplicationContext 加载,比 applicaton 优先加载

boostrap 里面的属性不能被覆盖

MVC模式(Model–view–controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)

DAO(data access object,DAO) 数据访问对象 是为某种类型的数据库或其他持久性机制提供一个抽象介面的对象。

DTO(Data Transfer Object) 数据传输对象

Mybatis

jdbc

JDBC代表Java数据库连接(Java Database Connectivity),它是用于Java编程语言和数据库之间的数据库无关连接的标准Java API,换句话说:JDBC是用于在Java语言编程中与数据库连接的API

#{} 默认会用引号将参数引起来
#{id, jdbcType=Integer}
${} 单纯替代
使用#{}可以预防sql攻击,而${}却不能
使用${}的场景:
作为in条件时,
参数为int类型并且数据库中字段的类型是number,
表名
order by ${},排序字段
           
//spropertites配置
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/DbName?verifyServerCertificate=true&useSSL=true&requireSSL=true
spring.datasource.driver=com.mysql.jdbc.Driver
spring.datasource.username= 
spring.datasource.password= 
    
mybatis.type-aliases-package=com.neo.model
spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
           
Mysql limit offset

代码示例:
select * from student limit #{offset}, #{limit}
语句1:select * from student limit 9,4
// 语句1和2均返回表student的第10、11、12、13行 
select * from student limit #{limit} offset #{offset}
语句2:slect * from student limit 4 offset 9
//语句2中的4表示返回4行,9表示从表的第十行开始

例2,通过limit和offset 或只通过limit可以实现分页功能。
假设 numberperpage 表示每页要显示的条数,pagenumber表示页码,那么 返回第pagenumber页,每页条数为numberperpage的sql语句:
           
<!--demo-->
<insert id="insertAuthor" useGeneratedKeys="true"
    keyProperty="id">
  insert into Author (username, password, email, bio) values
  <foreach item="item" collection="list" separator=",">
    (#{item.username}, #{item.password}, #{item.email}, #{item.bio})
  </foreach>
</insert>
           
mysql:
select * from t_user where name like concat("%",#{zhang},"%")
oracle:
select * from t_user where name like "%" || #{zhang} || "%"
           

resultType、resultMap区别

MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap.
 resultType是直接表示返回类型的(对应着我们的model对象中的实体),而resultMap则是对外部ResultMap的引用(提前定义了db和model之间的隐射key-->value关系),但是resultType跟resultMap不能同时存在。
           

postgreSQL

Mysql

CURRENT_TIMESTAMP

CURRENT_TIMESTAMP 自动更新时间

update_time

timestamp(0) NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0)

count()

select count(表达式)

对每一行累计求和表达式,表达式不为null即为1,否则为0。

mysql递归查询

后端备忘录
后端备忘录

被构造环而造成拒绝服务攻击

with recursive r as 
(select * from test_table t1
where t1."id" = #{testId}
union all
select t2.* from test_table t2
inner join r t1 on t2.parent_id=t1.id)
select id from r
           

mysql索引

单列索引

多个单列索引

组合索引

一个索引包含多个列

创建索引

CREATE INDEX indexName ON mytable(username(length)); 
           

如果是CHAR,VARCHAR类型,length可以小于字段实际长度;如果是BLOB和TEXT类型,必须指定 length。

修改表结构(添加索引)

ALTER table tableName ADD INDEX indexName(columnName)
           

创建表的时候直接指定

CREATE TABLE mytable(  
ID INT NOT NULL,   
username VARCHAR(16) NOT NULL,  
INDEX [indexName] (username(length))  
);  
           

删除索引的语法

DROP INDEX [indexName] ON mytable; 
           

Swagger

@Api(value="demo", description="这是一个Swagger demo的服务")
@ApiOperation:对方法进行描述,说明方法作用`
 `@ApiResponses:表示一组响应`
 `@ApiImplicitParams:对方法的多个参数进行描述`
 `@ApiImplicitParam:对单个的参数进行描述(name:参数名,value:参数的描述,dataType:参数类型,required:是否必须,paramType:参数来源方式)`
 `@ApiModel:对复杂类型参数进行说明`
 `@ApiModelProperty:对复杂类型字段进行说明
 
 //demo
 //Controller
 @Api(tags="")
 @RestController
 ...
 
 //Controller method
 @ApiOperation(value="", notes="")
 
 //model
 @ApiModel(value="")
 public class DataModel {
 	@ApiModelProperty(value="", required=true)
 	private String info;
 }
           

事务

事务是一组操作的执行单元,相对于数据库的单条操作而言,事务管理的是一组SQL指令,如增删改查等,事务的特性体现在事务内包含的SQL指令必须全部执行成功,如果其中一条指令发生错误,那么整个事务内的一组操作都要进行回滚。

事务有四个特性:

  • 原子性 Atomic ,事务是一个不可再拆分的最小单位,要么整个执行,要么整个回滚.
  • 一致性 Consistent,事务要保证数据库整体数据的完整性和业务的数据的一致性,事务成功提交整体数据修改,事务错误则回滚到数据回到原来的状态。
  • 隔离性 Isolate,两个事务的执行都是独立的,事务之前不会相互影响,多个事务操作一个对象时会以串行等待的方式保证事务相互之间处于隔离。
  • 持久性 Durable,一旦事务成功提交后,数据将会保存到数据库,不能再进行回滚,以后的操作都将在当前数据库状态上继续进行。

事务回滚

@transactional(rollbackfor = exception.class)

Spring框架的事务基础架构代码将默认地 只 在抛出运行时和unchecked exceptions时才标识事务回滚。 也就是说,当抛出个RuntimeException 或其子类例的实例时。(Errors 也一样 - 默认地 - 标识事务回滚。)从事务方法中抛出的Checked exceptions将 不 被标识进行事务回滚。

1 让checked例外也回滚:在整个方法前加上 @Transactional(rollbackFor=Exception.class)

2 让unchecked例外不回滚: @Transactional(notRollbackFor=RunTimeException.class)

3 不需要事务管理的(只查询的)方法:

@Transactional(propagation=Propagation.NOT_SUPPORTED)

注意: 如果异常被try{}catch{}了,事务就不回滚了,如果想让事务回滚必须再往外抛try{}catch{throw Exception}。

Java Bean

1、所有属性为private

2、提供默认构造方法

3、提供getter和setter

4、实现serializable接口

定时任务

@SpringBootApplication
@EnableScheduling
public class Application {
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

//定时任务1:
@Component
public class SchedulerTask {
    private int count=0;
    
    @Scheduled(cron="*/6 * * * * ?")
    private void process(){
        System.out.println("this is scheduler task runing  "+(count++));
    }

}

//定时任务2:
@Component
public class Scheduler2Task {
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

    @Scheduled(fixedRate = 6000)
    public void reportCurrentTime() {
        System.out.println("现在时间:" + dateFormat.format(new Date()));
    }

}
           

@Scheduled

参数可以接受两种定时的设置,一种是我们常用的

cron="*/6 * * * * ?"

,一种是

fixedRate = 6000

,两种都表示每隔六秒打印一下内容。

fixedRate 说明

  • @Scheduled(fixedRate = 6000)

    :上一次开始执行时间点之后6秒再执行
  • @Scheduled(fixedDelay = 6000)

    :上一次执行完毕时间点之后6秒再执行
  • @Scheduled(initialDelay=1000, fixedRate=6000)

    :第一次延迟1秒后执行,之后按 fixedRate 的规则每6秒执行一次

@Async

@Configuration
@EnableAsync
public class SpringAsyncConfig { ... }


@Async  //标注使用
public void asyncMethodWithVoidReturnType() {
    System.out.println("Execute method asynchronously. "
      + Thread.currentThread().getName());
}
           

Java传参

java中方法参数传递方式是按值传递。

如果参数是基本类型,传递的是基本类型的字面量值的拷贝。

如果参数是引用类型,传递的是该参量所引用的对象在堆中地址值的拷贝,因为对于对象参数,值的内容是对象的引用。

函数式编程

函数式编程的好处

由于命令式编程语言也可以通过类似函数指针的方式来实现高阶函数,函数式的最主要的好处主要是不可变性带来的。没有可变的状态,函数就是引用透明(Referential transparency)和没有副作用(No Side Effect)。

递归构建菜单树

package testSimple;

import java.util.ArrayList;
import java.util.List;

public class BuildTree {
    public static void main(String[] args) {
        List<Tree> list = new ArrayList<Tree>();
        list.add(new Tree(1, "一级菜单", 0));
        list.add(new Tree(2, "二级菜单1", 1));
        list.add(new Tree(3, "二级菜单2", 1));
        list.add(new Tree(4, "二级菜单3", 1));
        list.add(new Tree(5, "三级菜单11", 2));
        list.add(new Tree(6, "三级菜单12", 2));
        list.add(new Tree(7, "三级菜单21", 3));
        list.add(new Tree(8, "三级菜单22", 3));
        list.add(new Tree(9, "三级菜单31", 4));
        list.add(new Tree(10, "三级菜单32", 4));

        List<Tree> result = buildTree(list, 0);
        System.out.println(result);
    }

    public static List<Tree> buildTree(List<Tree> list, int fid) {
        List<Tree> resultList = new ArrayList<Tree>();
        if (list == null || list.size() == 0 || fid < 0) {
            return null;
        }
        for (Tree tree : list) {
            if (tree.getFid() == fid) {
                resultList.add(tree);
                tree.setChildren(buildTree(list, tree.getId()));
            }
        }
        return resultList;
    }

}

class Tree {
    private int id;
    private String name;
    private int fid;
    private List<Tree> children;

    public Tree(int id, String name, int fid) {
        super();
        this.id = id;
        this.name = name;
        this.fid = fid;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getFid() {
        return fid;
    }

    public void setFid(int fid) {
        this.fid = fid;
    }

    public List<Tree> getChildren() {
        return children;
    }

    public void setChildren(List<Tree> children) {
        this.children = children;
    }

}
           

继续阅读