SpringBoot核心功能

1、配置文件

1.1、properties文件

1.2、yml文件

1.2.1、简介

YAML 是 "YAML Ain't Markup Language"(YAML 不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:"Yet Another Markup Language"(仍是一种标记语言)。

非常适合用来做以数据为中心的配置文件

1.2.2、基本语法

  • key: value;kv之间有空格
  • 大小写敏感
  • 使用缩进表示层级关系
  • 缩进不允许使用tab,只允许空格
  • 缩进的空格数不重要,只要相同层级的元素左对齐即可
  • '#'表示注释
  • 字符串无需加引号,如果要加,''与""表示字符串内容 会被 转义/不转义

1.2.3、数据类型

  • 字面量:单个的、不可再分的值。date、boolean、string、number、null
k: v
  • 对象:键值对的集合。map、hash、set、object
行内写法:  k: {k1: v1,k2: v2,k3: v3}
#或
k: 
  k1: v1
  k2: v2
  k3: v3
  • 数组:一组按次序排列的值。array、list、queue
行内写法:  k: [v1,v2,v3]
#或者
k:
 - v1
 - v2
 - v3

1.2.4、配置提示

自定义类绑定的配置提示

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.springframework.boot</groupId>
                            <artifactId>spring-boot-configuration-processor</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

2、Web开发

2.1、SpringBoot中SpringMVC自动配置

  • 内容协商视图解析器(ContentNegotiatingViewResolver)和BeanName视图解析器(BeanNameViewResolver)
  • 静态资源(包括webjars)
  • 自动注册 Converter,GenericConverter,Formatter
  • 支持 HttpMessageConverters (后来我们配合内容协商理解原理)
  • 自动注册 MessageCodesResolver (国际化用)
  • 静态index.html 页支持
  • 自定义 Favicon
  • 自动使用 ConfigurableWebBindingInitializer ,(DataBinder负责将请求数据绑定到JavaBean上)

2.2、功能分析

1、静态资源目录

只要静态资源放在类路径下:called/static(or /public or /resources or /META-INF/resources

访问:当前项目根路径/+静态资源名

原理:静态资源映射:/**

请求进来,先去找Controller看能不能处理,不能处理则交给静态资源处理,如果静态资源也不能处理则404,。

修改默认的静态资源目录

spring:
  resources:
    static-locations: classpath:/haha/

2、静态资源访问前缀

spring:
  mvc:
    static-path-pattern: /res/**

访问静态资源:当前项目名+ static-path-pattern + 静态资源名 = 静态资源目录下寻找

3、支持webjars

https://www.webjars.org/

自动映射:/webjars/**

        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.6.0</version>
        </dependency>

访问:http://localhost:8080/webjars/jquery/3.6.0/jquery.js

4、欢迎页支持

  • 静态资源目录下index.html

    • 可以是配置后的资源路径,但是不能配置静态资源访问前缀,会导致index.html不能访问

      spring:
      #  mvc:
      #    static-path-pattern: /res/**   这个会导致welcome page 功能失效
      
        resources:
          static-locations: classpath:/haha/
    • 也可以是默认的static静态资源目录下(没有配置)
    • controller能处理的 /index 请求

    5、自定义Favicon

    将favicon.ico放在静态资源目录下即可。

    #spring:
    #  mvc:
    #    static-path-pattern: /res/**   会导致这个 Favicon 功能失效

    6、普通参数与基本注解

    • 注解:

    @PathVariable、@ReqestHeader、@RequestAttribute、@RequestParam、@MatrixVariable、@CookieVariable、@RequestBody

    //@PathVariable、@ReqestHeader、@RequestParam、@CookieVariable 注解的使用
    
    @RestController
    public class ParameterTestController {
    
        @GetMapping("/car/{id}/owner/{username}")
        public Map<String,Object> getCar(@PathVariable("id") Integer id,
                                         @PathVariable("username") String username,
                                         @PathVariable Map<String,String> pv,
                                         @RequestHeader("User-Agent") String userAgent,
                                         @RequestHeader Map<String,String> header,
                                         @RequestParam List<String> interests,
                                         @RequestParam Map<String,Object> Param,
    //                                     @CookieValue("_ga") String _ga,
                                         @CookieValue("_ga") Cookie cookie){
    
            Map<String,Object> map = new HashMap<>();
    //        map.put("id",id);
    //        map.put("username",username);
    //        map.put("pv",pv);
    //        map.put("User-Agent",userAgent);
    //        map.put("header",header);
            map.put("interests",interests);
            map.put("Param",Param);
    //        map.put("_ga",_ga);
            System.out.println(cookie.getName()+"===>"+cookie.getValue());
            return map;
        }
    }

    @RequestAttribute注解的使用

    @Controller
    public class RequestController {
        @GetMapping("/goto")
        public String goToPage(HttpServletRequest request){
    
            request.setAttribute("msg","成功了....");
            request.setAttribute("code",200);
            return "forward:/success";
        }
    
        //模拟读取数据回显到页面
        @ResponseBody
        @GetMapping("/success")
        public Map success(@RequestAttribute("msg") String msg,
                           @RequestAttribute("code") Integer code,
                           HttpServletRequest request){
            Object msg1 = request.getAttribute("msg");
    
            Map<String,Object> map = new HashMap<>();
            map.put("HttpServletRequest_msg",msg1);
            map.put("annotation_msg",msg);
            map.put("code",code);
            return map;
        }
    }

    @RequestBody注解的使用

    @RestController
    public class ParameterTestController {
        @PostMapping("/save")
        public Map getFormValues(@RequestBody String content){  //获取表单的所有提交的值
            Map<String,Object> map = new HashMap<>();
            map.put("content",content);
            return map;
        }
    }

    @MatrixVariable注解的使用

    @RestController
    public class ParameterTestController {
        //1、语法:  /cars/sell;low=34;brand=zhangsan,lisi,wangwu
        //2、SpringBoot默认是禁用掉了矩阵变量
        //      手动开启:原理。对于路径的处理:UrlPathHelper
        //              RemoveSemicolonContent 移除分号后面的内容
        //3、矩阵变量必须要有 url 路径变量  才能被解析
        @GetMapping("/cars/{path}")
        public Map matrixVariable(@MatrixVariable("low") String low,
                                  @MatrixVariable("brand") List<String> brand,
                                  @PathVariable("path") String path){
    
            Map<String,Object> map = new HashMap<>();
            map.put("low",low);
            map.put("brand",brand);
            map.put("path",path);
            return map;
        }
    
        //  /boss/1;age=30/2;age=18
        @GetMapping("/boss/{bossId}/{empId}")
        public Map boss(@MatrixVariable(value = "age",pathVar = "bossId") Integer bossAge,
                        @MatrixVariable(value = "age",pathVar = "empId") Integer empAge){
            Map<String,Object> map = new HashMap<>();
            map.put("bossAge",bossAge);
            map.put("empAge",empAge);
            return map;
        }
    }

    对应的index.html首页

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    测试基本注解:
    <ul>
        <a href="car/3/owner/zhangsan?age=17&interests=basketball&interests=game">car/{id}/owner/{username}</a>
        <li>@PathVariable(路径变量)</li>
        <li>@RequestHeader(请求头)</li>
        <li>@RequestParam(获取请求参数)</li>
        <li>@CookieValue(获取cookie的值)</li>
        <li>@RequestBody(获取请求体)</li>
        <li>@RequestAttribute(获取request域属性)</li>
        <li>@MatrixVariable(矩阵变量)</li>
    </ul>
    
    <form action="/save" method="post">
        测试@RequestBody(获取请求体)<br/>
        用户名:<input type="text" name="username"/><br/>
        邮箱:<input name="email"/><br/>
        <input type="submit" value="提交"/>
    </form>
    /cars/sell;low=34;brand=zhangsan;brand=lisi     矩阵变量<br/>
    页面开发时,cookie被禁用掉了,怎么使用session中的内容;<br/>
    session.set(a,b)---> jssessionid ---> cookie ---> 每次发请求携带<br/>
    url重写:/abc;jssessionid=xxx  把cookie的值使用矩阵变量的形式传递<br/>
    <a href="/cars/sell;low=34;brand=zhangsan,lisi,wangwu">@MatrixVariable(矩阵变量)</a><br/>
    <a href="/cars/sell;low=34;brand=zhangsan;brand=lisi;brand=wangwu">@MatrixVariable(矩阵变量)</a><br/>
    <a href="/boss/1;age=30/2;age=18">@MatrixVariable(矩阵变量)</a><br/>
    </body>
    </html>

    7、视图解析与模板引擎

    视图解析:SpringBoot默认不支持jsp,需要引入第三方模板引擎技术实现页面渲染

    视图处理方式:转发、重定向、自定义视图

    thymeleaf模板引擎

    使用方法:

    1、引入thymeleaf的starter场景

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>

    2、在默认的目录templates下,创建html页面并引入名称空间

    <html xmlns:th="http://www.thymeleaf.org">

    例:success.html

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1 th:text="${msg}">哈哈</h1>
    <h2><a href="www.baidu.com" th:href="${link}"/>我的博客</h2>
    <h2><a href="www.baidu.com" th:href="@{link}"/>我的博客2</h2>
    </body>
    </html>

    相应的处理器:ViewController

    @Controller
    public class ViewController {
    
        @GetMapping("/page")
        public String toPage(Model model){
    
            model.addAttribute("msg","成功了....");
            model.addAttribute("link","https://www.tainfei.top/");
    
            return "success";
        }
    }

    8、拦截器

    1、HandlerInterceptor接口
    2、配置拦截器
    /**
     * 登录检测
     * 拦截器:
     * 1、配置拦截器要拦截哪些
     * 2、拦截器添入容器中
     *
     * @author: Herz
     * @date: 2021/5/28 9:23
     */
    @Slf4j
    public class LoginInterceptor implements HandlerInterceptor {
    
        /**
         * 目标方法执行之前
         *
         * @param request
         * @param response
         * @param handler
         * @return
         * @throws Exception
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            String requestURI = request.getRequestURI();
            log.info("preHandle 拦截的请求路径:" + requestURI);
    
            //登录检查逻辑
            HttpSession session = request.getSession();
    
            Object attribute = session.getAttribute("loginUser");
            if (attribute != null) {
                //放行
                return true;
            } else {
                //拦截住,未登录
    //            session.setAttribute("msg", "请先登录");
                request.setAttribute("msg","请先登录");
                //跳转登录页
    //            response.sendRedirect("/");    //重定向取不到session 域中得值
                request.getRequestDispatcher("/").forward(request,response);
                return false;
            }
        }
    
    
        /**
         * 目标方法执行之后
         *
         * @param request
         * @param response
         * @param handler
         * @param modelAndView
         * @throws Exception
         */
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            log.info("postHandle的ModelAndView{}",modelAndView);
        }
    
    
        /**
         * 页面渲染以后
         *
         * @param request
         * @param response
         * @param handler
         * @param ex
         * @throws Exception
         */
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            log.info("afterCompletion异常:",ex);
        }
    }

    将拦截器注册到容器中

    /**
     * 1、编写一个拦截器实现 HandlerInterceptor 接口
     * 2、拦截器注册到容器中(实现 WebMvcConfigurer 接口的 addInterceptors 方法)
     * 3、指定拦截器规则【如果是拦截所有请求,静态资源的访问也会被拦截】
     *
     *
     * @author: Herz
     * @date: 2021/5/28 10:17
     */
    @Configuration
    public class AdminWebConfig implements WebMvcConfigurer {
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LoginInterceptor())
                    .addPathPatterns("/**")                 //拦截的请求路径,静态资源访问也被拦截
                    .excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**");      //不拦截的请求路径
        }
    }
    3、验证拦截器

    9、文件上传

    @Slf4j
    @Controller
    public class FormTestController {
    
        /**
         * 自动封装上传过来的文件
         * @param email
         * @param username
         * @param headerImg
         * @param photos
         * @return
         * @throws IOException
         */
        @PostMapping("/upload")
        public String uploads(@RequestParam("email") String email,
                              @RequestParam("username") String username,
                              @RequestParam("headerImg") MultipartFile headerImg,
                              @RequestParam("photos") MultipartFile[] photos) throws IOException {
    
            log.info("上传的信息:email={},username={},headerImg={},Photos={}",email,username,headerImg.getSize(),photos.length);
    
            if (!headerImg.isEmpty()){
                //上传到文件服务器,OSS服务器
                String originalFilename = headerImg.getOriginalFilename();
                headerImg.transferTo(new File("F:\\FormTest\\"+originalFilename));
            }
    
            for (MultipartFile photo : photos) {
                if (!photo.isEmpty()){
                    String originalFilename = photo.getOriginalFilename();
                    photo.transferTo(new File("F:\\FormTest\\"+originalFilename));
                }
            }
    
            return "main";
        }
    
    
    
        @GetMapping("/form_layouts")
        public String form_layouts(){
    
            return "form/form_layouts";
        }
    }

    对应的文件上传表单

                            <form role="form" th:action="@{/upload}" method="post" enctype="multipart/form-data">
                                <div class="form-group">
                                    <label for="exampleInputEmail1">邮箱</label>
                                    <input type="email" class="form-control" name="email" id="exampleInputEmail1" placeholder="Enter email">
                                </div>
                                <div class="form-group">
                                    <label for="exampleInputUsername1">姓名</label>
                                    <input type="text" class="form-control" name="username" id="exampleInputUsername1" placeholder="username">
                                </div>
                                <div class="form-group">
                                    <label for="exampleInputFile">头像</label>
                                    <input type="file" id="exampleInputFile" name="headerImg">
                                </div>
                                <div class="form-group">
                                    <label for="InputFiles">生活照</label>
                                    <input type="file" id="InputFiles" name="photos" multiple>
                                </div>
                                <div class="checkbox">
                                    <label>
                                        <input type="checkbox"> Check me out
                                    </label>
                                </div>
                                <button type="submit" class="btn btn-primary">提交</button>
                            </form>

    配置文件上传的大小与总的请求大小

    spring.servlet.multipart.max-file-size=10MB
    spring.servlet.multipart.max-request-size=100MB

    10、Web原生组件的注入(Servlet、Filter、Listener)

    1、使用Servlet API

    Servlet

    @WebServlet(urlPatterns = "/my")  //效果:直接响应,没有经过拦截器
    public class MyServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.getWriter().write("666666");
        }
    }
    
    
    
    
    @ServletComponentScan(basePackages = "com.tianfei.admin") //指明原生Servlet组件放在哪里
    @SpringBootApplication
    public class Boot04WebAdminApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(Boot04WebAdminApplication.class, args);
        }
    }

    Filter

    @Slf4j
    @WebFilter(urlPatterns = {"/css/*","/images/*"})
    public class MyFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
          log.info("MyFilter初始化");
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            log.info("方法被过滤");
            filterChain.doFilter(servletRequest,servletResponse);
        }
    
        @Override
        public void destroy() {
            log.info("MyFilter销毁");
        }
    }

    Listener

    @Slf4j
    @WebListener
    public class MyContextListener implements ServletContextListener {
    
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            log.info("MyContextListener监听到项目初始化完成");
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
            log.info("MyContextListener监听到项目销毁");
        }
    }

    注意:需要在SpringBoot的主方法上添加 @ServletComponentScan(basePackages = "com.tianfei.admin") //指明原生Servlet组件放在哪里

    2、RegistrationBean

    自定义一个Servlet

    public class MyServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.getWriter().write("666666");
        }
    }

    自定义一个Filter

    @Slf4j
    public class MyFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
          log.info("MyFilter初始化");
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            log.info("MyFilter工作");
            filterChain.doFilter(servletRequest,servletResponse);
        }
    
        @Override
        public void destroy() {
            log.info("MyFilter销毁");
        }
    }

    自定义一个Listener

    @Slf4j
    public class MyContextListener implements ServletContextListener {
    
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            log.info("MyContextListener监听到项目初始化完成");
        }
    
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
            log.info("MyContextListener监听到项目销毁");
        }
    }

    使用RegistrationBean注册到容器中

    //(proxyBeanMethods = true):保证依赖的组件始终是单实例的
    @Configuration(proxyBeanMethods = true)
    public class MyRegisterConfig {
    
        @Bean
        public ServletRegistrationBean getServlet(){
    
            MyServlet myServlet = new MyServlet();
    
            return new  ServletRegistrationBean(myServlet,"/my","/my02");
        }
    
        @Bean
        public FilterRegistrationBean getFilter(){
    
    //        return new FilterRegistrationBean(new MyFilter(),getServlet());   //过滤路径和  getServlet()映射路径相同
    
            FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter());
            filterRegistrationBean.setUrlPatterns(Arrays.asList("/my","/css/*"));
            return filterRegistrationBean;
        }
    
        @Bean
        public ServletListenerRegistrationBean getListener(){
    
            return new ServletListenerRegistrationBean(new MyContextListener());
        }
    }

    11、定制化SpringMVC原理

    1、定制化的常见方式
    • 修改配置文件;
    • 编写自定义配置类 xxxxConfiguration; + @Bean替换、增加容器中得组件;视图解析器;
    • 编写自定义类 xxxCustomizer

      @Component
      public class MyWebServerFactoryCustomizer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
      
          @Override
          public void customize(ConfigurableServletWebServerFactory server) {
              server.setPort(9000);
          }
      }
    • web应用 编写一个自定义类实现WebMvcConfigurer接口定制web功能 ;(推荐使用)+ @Bean 给容器中扩展组件
      @Configuration
      public class AdminWebConfig implements WebMvcConfigurer {
      
          @Override
          public void addInterceptors(InterceptorRegistry registry) {
              registry.addInterceptor(new LoginInterceptor())
                      .addPathPatterns("/**")                 //拦截的请求路径,静态资源访问也被拦截
                      .excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**");      //不拦截的请求路径
          }
      }
    • @EnableWebMvc + 实现WebMvcConfigurer接口 —— @Bean 可以完全接管SpringMVC,自己重新指定规则;实现定制和扩展功能
    2、定制化原理

    场景starter导入---- xxxAutoConfiguration --导入依赖组件 --绑定properties配置文件 ----- 绑定配置文件项

    3、数据访问

    1、SQL

    1、数据源的自动配置 HikariDataSource

    导入JDBC场景依赖:

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jdbc</artifactId>
            </dependency>

    导入数据库驱动:

            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>

    这里数据库驱动有版本仲裁(默认版本:8.0.25),想要修改到自己所需要的版本:

    1、导入驱动时直接指定版本号(maven中得依赖就近原则)
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.47</version>
            </dependency>
    2、在pom.xml配置文件中配置属性(maven中得属性就近原则)
        <properties>
            <mysql.version>5.1.47</mysql.version>
        </properties>

    修改自动配置属性:

    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/userdb
        username: root
        password: tianfei
        driver-class-name: com.mysql.jdbc.Driver
    
      jdbc:
        template:
          query-timeout: 3

    测试代码:

    @Slf4j
    @SpringBootTest
    class Boot05JdbcApplicationTests {
    
        @Autowired
        JdbcTemplate jdbcTemplate;
    
        @Test
        void contextLoads() {
            Long nums = jdbcTemplate.queryForObject("select COUNT(*) from t_account", Long.class);
            log.info("总记录数为:"+nums);
        }
    }

    2、使用Druid数据源

    1、druid官方github地址

    https://github.com/alibaba/druid

    整合第三方技术的两种方式:

    • 自定义
    • 引入starter场景
    2、自定义方式

    引入相关依赖

            <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.47</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.2.6</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jdbc</artifactId>
            </dependency>
    @Configuration
    public class MyDataSourceConfig {
    
        @ConfigurationProperties(prefix = "spring.datasource")
        //默认的自动配置数据源是容器中没有才会配置@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
        @Bean
        public DataSource dataSource() throws SQLException {
            DruidDataSource dataSource = new DruidDataSource();
            //打开监控功能、防火墙
            dataSource.setFilters("stat,wall");
            dataSource.setMaxActive(10);
            return dataSource;
        }
    
    
        /**
         * 监控页面的 sql监控
         * web.xml中得配置
         *   <servlet>
         *       <servlet-name>DruidStatView</servlet-name>
         *       <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>
         *   </servlet>
         *   <servlet-mapping>
         *       <servlet-name>DruidStatView</servlet-name>
         *       <url-pattern>/druid/*</url-pattern>
         *   </servlet-mapping>
         *
         *
         * @return
         */
        @Bean
        public ServletRegistrationBean statViewServlet(){
            StatViewServlet statViewServlet = new StatViewServlet();
            ServletRegistrationBean<StatViewServlet> registrationBean = new ServletRegistrationBean<>(statViewServlet,"/druid/*");
            //配置监控页访问密码
            registrationBean.addInitParameter("loginUsername","druid");
            registrationBean.addInitParameter("loginPassword","druid");
            return registrationBean;
        }
    
    
        /**
         * 监控页面的 web应用监控
         * web.xml中得配置
         *   <filter>
         *       <filter-name>DruidWebStatFilter</filter-name>
         *       <filter-class>com.alibaba.druid.support.http.WebStatFilter</filter-class>
         *       <init-param>
         *           <param-name>exclusions</param-name>
         *           <param-value>*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*</param-value>
         *       </init-param>
         *   </filter>
         *   <filter-mapping>
         *       <filter-name>DruidWebStatFilter</filter-name>
         *       <url-pattern>/*</url-pattern>
         *   </filter-mapping>
         *
         *
         * @return
         */
        @Bean
        public FilterRegistrationBean webStatFilter(){
            WebStatFilter webStatFilter = new WebStatFilter();
            FilterRegistrationBean<WebStatFilter> registrationBean = new FilterRegistrationBean<>(webStatFilter);
            registrationBean.setUrlPatterns(Arrays.asList("/*"));
            registrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
            return registrationBean;
        }
    }
    3、引入starter官方场景
    <dependency>
       <groupId>com.alibaba</groupId>
       <artifactId>druid-spring-boot-starter</artifactId>
       <version>1.1.17</version>
    </dependency>

    相关配置

    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/userdb?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false
        username: root
        password: tianfei
        driver-class-name: com.mysql.jdbc.Driver
    
        druid:
          stat-view-servlet:
            enabled: true   #功能开启
            login-username: druid
            login-password: druid
            reset-enable: false   #重置按钮
    
          web-stat-filter:
            enabled: true
            url-pattern: /*
            exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'
    
          aop-patterns: com.tianfei.admin/*      #监控的包
          filters: stat,wall    #底层功能开启,stat(sql监控功能),wall(防火墙功能)
          filter:
            stat:
              slow-sql-millis: 1000
              log-slow-sql: true    #日志记录慢查询
            wall:
              enabled: true

    3、整合MyBatis操作

    starter

    官方的starter:spring-boot-starter-*

    第三方的starter:*-spring-boot-starter

    3.1纯配置方式
    spring:
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost:3306/userdb?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false
        username: root
        password: tianfei
    
    #mybatis配置规则
    mybatis:
      config-location: classpath:mybatis/mybatis-config.xml   #mybatis的核心配置文件位置
      mapper-locations: classpath:mybatis/mapper/*.xml      #sql映射文件文职

    整合步骤:

    • 导入官方的starter

              <dependency>
                  <groupId>org.mybatis.spring.boot</groupId>
                  <artifactId>mybatis-spring-boot-starter</artifactId>
                  <version>2.2.0</version>
              </dependency>
    • 编写mapper接口(注意标注 @Mapper 注解)

      @Mapper
      public interface AccountMapper {
      
          public Account getById(Integer id);
      }
    • 编写sql映射文件,并绑定mapper接口。

      <?xml version="1.0" encoding="UTF-8" ?>
              <!DOCTYPE configuration
                      PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
                      "http://mybatis.org/dtd/mybatis-3-config.dtd">
      <configuration>
              <settings>
                      <!-- 开启驼峰命名规则 -->
                      <setting name="mapUnderscoreToCamelCase" value="true"/>
              </settings>
      </configuration>
    • 在application.yaml配置文件中,指定mybatis核心配置文件位置和sql映射文件位置以及全局配置文件的信息(建议:配置在yaml文件中mybatis.configuration)
    3.2纯注解版
    @Mapper
    public interface CityMapper {
    
        @Select("select * from city where id=#{id}")
        public City getById(Integer id);
    
        @Insert("insert into city(`name`,`state`,`country`) values (#{name},#{state},#{country})")
        @Options(useGeneratedKeys = true,keyProperty = "id")
        public void insert(City city);
    }
    3.3混合版
    @Mapper
    public interface CityMapper {
    
        @Select("select * from city where id=#{id}")
        public City getById(Integer id);
    
        public void insert(City city);
    }
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.tianfei.boot06mybatisannotation.mapper.CityMapper">
        <insert id="insert" parameterType="com.tianfei.boot06mybatisannotation.bean.City" useGeneratedKeys="true" keyProperty="id">
            insert into city(`name`,`state`,`country`) values (#{name},#{state},#{country});
        </insert>
    </mapper>

    最佳实战:

    • 导入mybatis的官方starter
    • 在配置文件application.yaml中配置mapper-locations sql映射文件的位置
    • 编写mapper接口,并添加@Mapper注解
    • 简单的sql语句直接使用注解方式
    • 复杂的sql语句编写mapper接口后,进行绑定映射
    • @MapperScan("com.tianfei.boot06mybatisannotation.mapper") 可以简化,其他接口不用添加 @Mapper 注解

    4、SpringBoot整合mybatis-plus

    • 导入mybatis-plus官方starter

              <dependency>
                  <groupId>com.baomidou</groupId>
                  <artifactId>mybatis-plus-boot-starter</artifactId>
                  <version>3.4.3</version>
              </dependency>
    • 在application.yaml配置文件中配置数据源

      spring:
        datasource:
          url: jdbc:mysql://localhost:3306/userdb?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&useSSL=false
          username: root
          password: tianfei
          driver-class-name: com.mysql.jdbc.Driver
    • 编写一个mapper接口继承BaseMapper<T> 接口

      public interface UserMapper extends BaseMapper<User> {
      
      }
    • 编写一个Service接口继承 IService<T>接口,并编写Service的实现类继承ServiceImpl<M,T>类

      public interface UserService extends IService<User> {
      }
      
      @Service
      public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
      }
    • 编写一个controller

      @Controller
      public class TableController {
      
          @Autowired
          UserService service;
      
          @GetMapping("/dynamic_table")
          @ResponseBody
          public String dynamic_table(@RequestParam(value = "pn",defaultValue = "1") Integer pn, Model model) {
              //分页查询数据
              Page<User> userPage = new Page<>(pn,2);
              //分页查询的结果
              Page<User> page = service.page(userPage, null);
              
              model.addAttribute("page",page);
              List<User> records = page.getRecords();
              long pages = page.getPages();
      
              return "dynamic_table";
          }
      }
    • 在主程序上添加@MapperScan("com.tianfei.boot07mybatisplus.mapper") 注解,开启扫描mapper包下的mapper接口

      @MapperScan("com.tianfei.boot07mybatisplus.mapper")
      @SpringBootApplication
      public class Boot07MybatisplusApplication {
      
          public static void main(String[] args) {
              SpringApplication.run(Boot07MybatisplusApplication.class, args);
          }
      }
    • 测试访问:localhost:8080/项目名/dynamic_table

    注意!!!!使用mybatisPlus的分页插件时,需创建一个配置类MybatisPlusConfig

    @Configuration
    @MapperScan("com.tianfei.admin.mapper.*")
    public class MybatisPlusConfig {
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor() {
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
            // paginationInterceptor.setOverflow(false);
            // 设置最大单页限制数量,默认 500 条,-1 不受限制
            // paginationInterceptor.setLimit(500);
            // 开启 count 的 join 优化,只针对部分 left join
    
            //分页拦截器
            PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
            paginationInnerInterceptor.setOverflow(true);
            paginationInnerInterceptor.setMaxLimit(500L);
            interceptor.addInnerInterceptor(paginationInnerInterceptor);
            return interceptor;
        }
    }

    4、单元测试

    1、Junit5常用注解

    https://junit.org/junit5/docs/current/user-guide/#writing-tests-annotations

    2、SpringBoot整合Junit

    • 编写测试方法:@Test标注(注意需要使用junit5版本的注解)
    • Junit类具有Spring的功能,@Autowired、比如 @Transactional 标注测试方法,测试完成后自动回滚

    5、原理解析

    1、application-profile功能

    • 默认配置文件 application.yaml;任何时候都会加载
    • 指定环境配置文件 application-{env}.yaml
    • 激活指定环境
    • 配置文件激活
    • 命令行激活:java -jar xxx.jar --spring.profiles.active=prod --person.name=haha
    • 修改配置文件的任意值,命令行优先
    • 默认配置与环境配置同时生效
    • 同名配置项,profile配置优先

    2、@Profile条件装配功能

    //@Profile("prod")
    @Configuration
    public class MyConfig {
        @Profile("prod")
        @Bean
        public Color red(){
            return new Color();
        }
    
        @Profile("test")
        @Bean
        public Color green(){
            return new Color();
        }
    }

    3、profile分组

    spring.profiles.group.myprod[0]=proddb
    spring.profiles.group.myprod[1]=prodmq
    
    使用:spring.profiles.active=myprod  激活
    最后修改:2021 年 07 月 27 日 04 : 26 PM
    如果觉得我的文章对你有用,请随意赞赏