• 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

    举例:

  • 相关阅读:
    我的第一次面试 —— 腾讯 AI安全 一面总结
    从零开始openGL——五、光线追踪
    从零开始openGL——四、纹理贴图与n次B样条曲线
    从零开始openGL——三、模型加载及鼠标交互实现
    从零开始openGL—— 二、 基本图形绘制
    NN入门,手把手教你用Numpy手撕NN(三)
    2020计算机保研经验分享
    TCP实战二(半连接队列、全连接队列)
    TCP实战一(三握四挥、流量控制)
    tcpdump抓包工具的基本使用
  • 原文地址:https://www.cnblogs.com/zhaojianhui/p/13551654.html
Copyright © 2020-2023  润新知