Springboot笔记

SpringBoot学习笔记

1、通过Maven创建

pom文件中加入:

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.0.RELEASE</version>
        <relativePath/>
    </parent>
    <properties>
        <java.version>1.8</java.version>
    </properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

 2、IDEA的脚手架创建(推荐)

SpringBoot的配置文件

1、application.properties格式 

2、application.yml格式(层次清楚,推荐使用,但是缩进较为严格)

配置文件存放位置:

1、当前项目根目录中

2、当前项目根目录下的一个/config子目录中

3、项目resources根路径中

4、项目resources根路径下的/config子文件夹中

配置文件中的占位符:

1、语法:${}

2、占位符作用以及生成随机数:

BootStrap配置文件:

SpringBoot的HelloWorld:

@RestController //等于@Controller+@Responsebody
public class HelloController {
    @RequestMapping("/hello")
    public String show() {
        return "helloworld";

    }

}

SpringBoot在Controller层中的常用注解:

  1、@RestController:相当于@Controller+@ResponseBody注解的结合,使用后Controller无法返回页面,返回的就是return中的内容

  2、@GetMapping:就是@RequestMapping(method=RequestMethod.GET)的缩写,@PostMapping、@PutMapping、@DeleteMapping效果类似

 

SpringBoot整合WEB层技术:

  1、整合Servlet

方式一:

    1.1通过注解扫描

      1.1.1创建一个servlet

      

package comzhaojianhui.cn.springbootdemo.servlet;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(name = "first",urlPatterns = "/first")
public class MyServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response){
        System.out.println("do GET");
    }
}

      1.1.2修改启动类:启动类上加上@ServletComponentScan注解

整合filter:

  1、创建一个filter

package comzhaojianhui.cn.springbootdemo.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(filterName = "firstfilter",urlPatterns = "/firstfilter")
public class FirstFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("进入first filter");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("离开first filter");
    }
}

  2、启动类加上@ServletComponentScan注解

整合Listener

1、创建一个listener

package comzhaojianhui.cn.springbootdemo.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class FirstListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {

    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {

    }
}

  2、启动类加上@ServletComponentScan注解

SpringBoot访问静态资源:static目录存放静态资源(例如css/html/js/jquery),templates目录存放Thymeleaf模板页面

如果Controller要实现static目录中html页面的视图跳转,不需要加上static目录,示例如下:

package comzhaojianhui.cn.springbootdemo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class IndexController {
    @RequestMapping("/page")
    public String hello() {
        return "index.html";//直接返回要跳转到的页面即可,页面包含.html
    }
}

配置文件中加上:

server:
  port: 8888
spring:
  thymeleaf:
    prefix: classpath:/static/
    suffix: .html

  

热部署:

1、加入jar包

  <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

2、打开顶部工具栏 File -> Settings -> Default Settings -> Build -> Compiler 然后勾选 Build project automatically 

 3、同时按住 Ctrl + Shift + Alt + / 然后进入Registry ,勾选自动编译并调整延时参数

 4、

静态资源存放的其他位置(classpath指的就是resources):

自定义静态资源位置:

SpringBoot的文件上传:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file"/>
    <input type="submit" value="上传"/>

</form>

</body>
</html>

  

package comzhaojianhui.cn.springbootdemo.controller;

import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;

@RestController
public class FileLoad {
    /**
     * 文件上传
     */
    @PostMapping("/upload")
    public String fileup(MultipartFile file) throws IOException {
        System.out.println(file.getOriginalFilename());

        file.transferTo(new File("F:/" + file.getOriginalFilename()));
        return "ok";


    }
}
server:
  port: 8888
spring:
  thymeleaf:
    prefix: classpath:/static/
    suffix: .html
    #配置单个文件大小限制
  servlet:
    multipart:
      max-file-size: 50MB
      #一次请求中上传文件总容量大小
      max-request-size: 50MB
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatisstudy?serverTimezone=UTC&characterEncoding=utf8&useSSL=false
    username: root
    password: 1314520
    type: com.alibaba.druid.pool.DruidDataSource

  

SpringBoot整合freemarker:

1、添加pom

 <!--整合freemarker-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>

SpringBoot整合Mybatis:

1、添加pom:

 <!--Mybatis启动器-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>
        <!--数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.11</version>
        </dependency>
        <!--druid连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.12</version>
        </dependency>

2、配置数据源

 

server:
  port: 8080
spring:
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
    cache: false
    mode: HTML
  servlet:
    multipart:
      max-request-size: 50MB
      max-file-size: 20MB
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatisstudy?serverTimezone=UTC&characterEncoding=utf8&useSSL=false
    username: root
    password: 1314520
    type: com.alibaba.druid.pool.DruidDataSource
mybatis:
  mapper-locations: classpath:/mapper/*.xml

  

  

3、pom中配置generator插件:

 <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!--配置generator插件-->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.5</version>
                <dependencies>
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>8.0.11</version>
                    </dependency>
                </dependencies>
                <!--指定配置文件路径-->
                <configuration>
                    <configurationFile>${project.basedir}/src/main/resources/mbg.xml</configurationFile>
                    <verbose>true</verbose>
                    <overwrite>true</overwrite>
                </configuration>
            </plugin>
        </plugins>
    </build>

  

 配置完成后双击下图中的选项即可生成:

配置资源拷贝插件:

 <!--配置资源拷贝插件-->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.yml</include>
                    <include>**/*.properties</include>
                </includes>
            </resource>
        </resources>

修改启动类添加@MapperScan注解完成mapper接口和映射文件的扫描,示例如下:

当mapper.xml映射配置文件放在resources目录下的mapper文件夹时,需要使用

mybatis:
  mapper-locations: classpath:/mapper/*.xml

resultType起别名:

  


异常处理

1、自定义错误页面:如果我们需要将所有的异常统一跳到自定义的错误页面,需要在resources的templates目录下创建error.html,只能叫error,不能换名字!

2、通过@ExceptionHandler处理异常

3、通过@ControllerAdvice和@ExceptionHandler定义异常类处理

4、通过@SimpleMappingExceptionResolver处理,示例如下(错误页面存放与templates目录下):只能传递异常页面,无法传递异常信息

package comzhaojianhui.cn.springbootdemo.Exception;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import java.util.Properties;

@Configuration
public class GlobalEx2 {
    @Bean
    public SimpleMappingExceptionResolver get() {
        SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
        Properties prop = new Properties();
        /**
         * 参数一:异常类型且是全名
         * 参数二:视图名
         */
        prop.put("java.lang.NullPointerException", "error2");
        prop.put("java.lang.ArithmeticException", "error3");
        resolver.setExceptionMappings(prop);
        return resolver;
    }
}

5、自定义HadlerExceptionResolver处理对象处理:可以传递异常页面和信息

package comzhaojianhui.cn.springbootdemo.Exception;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Configuration
public class Global3 implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        ModelAndView mv = new ModelAndView();
        //判断异常类型进行视图跳转
        if (e instanceof NullPointerException) {
            mv.setViewName("error4");
        }
        if (e instanceof ArithmeticException) {
            mv.setViewName("error5");
        }
        mv.addObject("error", e.toString());
        return mv;
    }
}

SpringBoot整合junit单元测试示例:

SpringBoot服务端数据校验:

1、对实体对象的校验

  NotNull:多用于对Integer校验

  NotBlank:对字符串做非空校验

  NotEmpty:对集合类型做非空校验

 2、在controller中开启校验规则

package comzhaojianhui.cn.springbootdemo.controller;

import comzhaojianhui.cn.springbootdemo.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/adduser")
    public String add(@Validated User user, BindingResult result) {
        if (result.hasErrors()) {
          /*  List<ObjectError> list = result.getAllErrors();
            for (Object err : list) {
                FieldError fieldError = (FieldError) err;
                String fieldName = fieldError.getField();
                String msg = fieldError.getDefaultMessage();
                System.out.println(fieldName + "	" + msg);

            }*/
            return "addUser";
        }
        System.out.println(user);

        return "ok";

    }
}

  

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form th:action="@{/user/adduser}" method="post">
    <input type="text" name="name"/><span th:errors="${user.name}"/><br/>
    <input type="text" name="id"/><span th:errors="${user.id}"/>

</form>

</body>
</html>

自定义错误提示信息:

  1、注解中定义错误信息

public class User {
    @NotBlank(message = "名字不能为空")
    private String name;
    @NotNull(message = "id不能为空")
    private Integer id;

}

  2、配置文件中定义提示信息,配置文件名必须是ValidationMessages.properties

  

userid.notnull=用户ID不能为空1122
username.notnull=用户姓名不能为空11

  

package comzhaojianhui.cn.springbootdemo.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @NotBlank(message = "{username.notnull}")
    private String name;
    @NotNull(message = "{userid.notnull}")
    private Integer id;

}

  

解决页面跳转异常:

package comzhaojianhui.cn.springbootdemo.controller;

import comzhaojianhui.cn.springbootdemo.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * 跳转页面的方法
 * 解决异常的方式:在跳转页面方法中注入对应pojo对象
 */
@Controller
public class PageController {
    @RequestMapping("/{page}")
    public String showPage(@PathVariable String page, User user) {
        return page;
    }
}

修改参数key的名称:

  

 

其他校验规则:

SpringBoot中对controller中其他参数的校验示例:

全局异常中添加:


SpringBoot的度量指控与健康检查

1、引入pom:

 <!--Actuator启动器 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

  

2、配置文件添加:

使用可视化监控工具:SpringBoot Admin:

1、创建一个基于springboot的服务端项目

2、服务端添加依赖:

<dependency>
            <groupId>de.codecentric</groupId>
            <artifactId>spring-boot-admin-starter-server</artifactId>
            <version>2.3.0</version>
        </dependency>

3、修改配置文件:

 4、修改启动类

搭建客户端:

1、添加Pom

<!-- https://mvnrepository.com/artifact/de.codecentric/spring-boot-admin-starter-client -->
<dependency>
    <groupId>de.codecentric</groupId>
    <artifactId>spring-boot-admin-starter-client</artifactId>
    <version>2.3.0</version>
</dependency>

2、修改配置文件:


SpringBoot日志管理(默认是logback):

屏蔽指定包的日志输出:

SpringBoot的打包方式:双击install即可

运行:java -jar 文件名

SpringBoot多环境配置:

 


SpringBoot在Linux下的运行:

 


SpringBoot开发定时任务

示例:

1、启动类中加注解@EnableScheduling

package comzhaojianhui.cn.springbootdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling//开启定时任务
public class SpringbootdemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootdemoApplication.class, args);
    }

}

 2、编写的方法中添加@Scheduled(cron = "0/3 * * * * ?")注解,括号里写cron表达式,表示几秒钟执行一次(此例中3秒一次),cron表达式参考网站:https://cron.qqe2.com/

package comzhaojianhui.cn.springbootdemo.config;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;


@Component
public class OrderTask {

    @Scheduled(cron = "0/3 * * * * ?")
    public void autoCloseOrder() {
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        String nowtime = dateFormat.format(date);
        System.out.println("执行定时任务,当前时间为:" + nowtime);

    }

}

 执行后效果图如下:

 

定时任务关闭超期未支付订单会存在的弊端:

  • 1、会有时差,导致程序不严谨:例如10:39下单,11:00检查不足一小时;12点检查,超过1小时多余39分钟
  • 2、不支持集群,单机使用无问题,使用集群后就会有多个定时任务。  解决方案:只用一台计算机节点,单独用来运行所有的定时任务
  • 3、会对数据库全表搜索,影响数据库性能:select * from xxx   
  • 小结:定时任务仅仅适用于小型轻量级项目、传统项目。对于大型项目:可用消息队列如:MQ->RabbitMQ、kafka、ZeroMQ... 延时任务(队列) 例如:10:12下单的,未付款状态,11:12检查,如果状态还是未支付,则直接关闭

任务调度之Quartz:

常用api:

 开发步骤:

1、导入quartz的jar包:

 <!--开发定时任务-->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
            <version>2.3.0</version>
        </dependency>

2、入门案例:

package comzhaojianhui.cn.springbootdemo.config;

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzMain {
    public static void main(String[] args) throws Exception {
        //1、调度器Scheduler,从工厂中获取调度实例
        Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
        //2、任务实例JodDetail QuartzJob.class为加载任务类,与QuartzJob类完成绑定
        JobDetail jobDetail = JobBuilder.newJob(QuartzJob.class).withIdentity("job1", "group1").build();//参数1:任务的名称(唯一实例) 参数2:任务组的名称
        //3、触发器Trigger startNow为马上启动触发器
        Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").
                startNow().withSchedule(SimpleScheduleBuilder
                .simpleSchedule().repeatSecondlyForever(5)).build(); //每5秒重复执行一次
        //让调度器关联任务和触发器,保证按照触发器定义的条件执行任务
        scheduler.scheduleJob(jobDetail, trigger);
        //启动调度
        scheduler.start();
    }
}

  

package comzhaojianhui.cn.springbootdemo.config;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.text.SimpleDateFormat;
import java.util.Date;

public class QuartzJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        //自定义任务:比如输出当前时间
        Date date = new Date();
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString = sf.format(date);
        //工作内容
        System.out.println("执行定时任务,当前时间为:" + dateString);

    }
}

  效果图:

Job和JobDetail介绍:

Job:工作任务调度的接口,任务类需要实现该接口。该接口中定义execute方法,在里面编写任务执行的业务逻辑。

Job实例在Quartz中的生命周期:每次调度器执行Job时,它在调用execute方法前会创建一个新Job实例,当调用完成后,关联的Job对象实例会被释放,释放的实例会被垃圾回收机制回收。

JobDetail:为Job实例提供了许多设置属性,调度器需要借助JobDetail对象来添加Job实例。

JobDetail的重要属性:name、group、jobClass、jobDataMap

常用属性示例:

 System.out.println("name:" + jobDetail.getKey().getName());
  System.out.println("group:" + jobDetail.getKey().getGroup());
   System.out.println("class:" + jobDetail.getKey().getClass());

  结果图:

JobExecutionContext介绍:

  • 当Scheduler调用一个job,就会将JobExecutionContext传递给Job的execute()方法。
  • Job能通过JobExecutionContext对象访问到Quartz运行时候的环境以及Job本身的明细数据。

JobDataMap介绍:

1、使用Map获取

  • 在进行任务调度时,JobDataMap存储在JobExecutionContext中,非常方便获取
  • JobDataMap可以用来装载任何可序列化的数据对象,当Job实例对象被执行时这些参数对象会传递给他。
  • JobDataMap实现了JDK的Map接口,并且添加了非常方便的方法用来存取基本数据类型。

示例代码:

 

有状态的job(任务类上加@PersistJobDataAfterExecution)和无状态的job:

有状态的job可以理解为多次Job调用期间可以持有一些状态信息,这些状态信息存储在JobDataMap中,而默认的无状态的job每次调用时都会创建一个新的JobDataMap

举例:

原文地址:https://www.cnblogs.com/zhaojianhui/p/13551654.html