SpringBoot学习文档

SpringBoot

SpringBoot简介

原有Spring优缺点分析
Spring的优点分析

Spring是Java企业版(Java Enterprise Edition,JEE,也称J2EE)的轻量级代替品。无需开发重量级的Enterprise JavaBean(EJB),Spring为企业级Java开发提供了一种相对简单的方法,通过依赖注入和面向切面编程,用简单的Java对象(Plain Old Java Object,POJO)实现了EJB的功能。

Spring的缺点分析

虽然Spring的组件代码是轻量级的,但它的配置却是重量级的。过多的XML文件配置。

所有这些配置都代表了开发时的损耗。因为在思考Spring特性配置和解决业务问题之间需要进行思维切换,所以编写配置挤占了编写应用程序逻辑的时间。和所有框架一样,Spring实用,但与此同时它要求的回报也不少。
除此之外,项目的依赖管理也是一件耗时耗力的事情。在环境搭建时,需要分析要导入哪些库的坐标,而且还需要分析导入与之有依赖关系的其他库的坐标,一旦选错了依赖的版本,随之而来的不兼容问题就会严重阻碍项目的开发进度。

SpringBoot的概述
SpringBoot解决上述Spring的缺点

SpringBoot对上述Spring的缺点进行的改善和优化,基于约定优于配置的思想,可以让开发人员不必在配置与逻辑业务之间进行思维的切换,全身心的投入到逻辑业务的代码编写中,从而大大提高了开发的效率,一定程度上缩短了项目周期。

特点
  • 为基于Spring的开发提供更快的入门体验
  • 开箱即用,没有代码生成,也无需XML配置。同时也可以修改默认值来满足特定的需求
  • 提供了一些大型项目中常见的非功能性特性,如嵌入式服务器、安全、指标,健康检测、外部配置等
  • SpringBoot不是对Spring功能上的增强,而是提供了一种快速使用Spring的方式
核心功能
  1. 起步依赖
    起步依赖本质上是一个Maven项目对象模型(Project Object Model,POM),定义了对其他库的传递依
    赖,这些东西加在一起即支持某项功能。
    简单的说,起步依赖就是将具备某种功能的坐标打包到一起,并提供一些默认的功能。
  2. 自动配置
    Spring Boot的自动配置是一个运行时(更准确地说,是应用程序启动时)的过程,考虑了众多因素,才决定Spring配置应该用哪个,不该用哪个。该过程是Spring自动完成的。

SpringBoot快速入门

快速入门
创建Maven工程

使用idea工具创建一个maven工程,该工程为普通的java工程即可。

添加SpringBoot的起步依赖

SpringBoot要求,项目要继承SpringBoot的起步依赖spring-boot-starter-parent

  <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>2.1.0.RELEASE</version>
   </parent>
添加web启动器

SpringBoot要集成SpringMVC进行Controller的开发,所以项目要导入web的启动依赖:

       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
管理jdk版本

默认情况下,maven工程的jdk版本是1.5,而我们开发使用的是1.8,因此这里我们需要修改jdk版本,只需要简单的添加以下属性即可:

<properties>
        <java.version>11</java.version>
 </properties>
编写SpringBoot引导类

Spring Boot项目通过main函数即可启动,我们需要创建一个启动类,例如:

package com.sp;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MySpringBootApplication {
    public static void main(String[] args) {
        SpringApplication.run(MySpringBootApplication.class,args);
    }
    
}
注:
   (1)@SpringBootApplication:标注SpringBoot的启动类
   (2)SpringApplication.run(MySpringBootApplication.class) 代表运行SpringBoot的启动类,参数为SpringBoot启动类的字节码对象
编写Controller

在引导类MySpringBootApplication同级包或者子级包中创建xxxController,例如:

package com.sp.controller;

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

@Controller
public class HelloController {

    @RequestMapping("/hello")
    @ResponseBody
    public String hello(){

        return "Hello SpringBoot";
    }
}
启动测试

运行MySpringBootApplication主函数,启动Springboot,控制台查看信息。若端口冲突,则在配置文件中修改端口号,在重新启动。如:配置文件(application.properties)

server.port=端口号
如:server.port=8085

打开网页访问位置,如:localhost:8085/hello

SpringBoot工程热部署

我们在开发中反复修改类、页面等资源,每次修改后都是需要重新启动才生效,这样每次启动都很麻烦,浪费了大量的时间,我们可以在修改代码后不重启就能生效,在 pom.xml 中添加如下配置就可以实现这样的功能,我们称之为热部署。

<!--热部署配置-->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-devtools</artifactId>
</dependency>

SpringBoot 基础配置

@SpringBootApplication

@SpringBootApplication 注解是加在项目的启动类上的。@SpringBootApplication 实际上是一个组合注解,定义如下:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
//代码略
}
  • 第一个@SpringBootConfiguration 的定义如下:

    @Configuration
    public @interface SpringBootConfiguration {
    }
    

    原来就是一个@Configuration ,所以@Spring BootConfiguration 的功能就是表明这是一个配置
    类,开发者可以在这个类中配置Bean。从这个角度来讲,这个类所扮演的角色有点类似于Spring
    中applicationContext.xml 文件的角色。

  • 第二个注解@EnableAutoConfiguration 表示开启自动化配置。Spring Boot 中的自动化配置是非侵入式的,在任意时刻,开发者都可以使用自定义配置代替自动化配置中的某一个配置。

  • 第三个注解@ComponentScan 完成包扫描,也是Spring 中的功能。由于@ComponentScan 注解默认扫描的类都位于当前类所在包的下面, 因此建议在实际项目开发中把项目启动类放在根包中。

  1. 项目启动类中的@ComponentScan 注解,除了扫描@Service , @Repository 、@Component 、@Controller 和@RestController 等之外,也会扫描@Configuration 注解的类。
Web 容器配置
Tomcat 配置
  1. 常规配置

    在Sprin g Boot 项目中,可以内置Tomcat 、Jetty 、Undertow 、Netty 等容器。当开发者添加了spring-boot-starter-web 依赖之后, 默认会使用Tomcat 作为Web 容器。如果需要对Tomcat 做进一步的配置,可以在application.properties 中进行配置,代码如下:

    #配直了Web 容器的端口号
    server.port=8080
    #配直了当项目出错时跳转去的页面
    server.error.path=/error
    #配直了session 失效时间, 30m表示30分钟,如果不写单位, 默认单位是秒。
    server.servlet.session.timeout=30m
    #表示项目名称,不配直时,默认为/。如果配直了,就要在访问路径中加上配直的路径。
    server.servlet.context-path=/chapter02
    #表示配直Tomcat 请求编码。
    server.tomcat.uri-encoding=utf-8
    #表示Tomcat 最大线程数。
    server.tomcat.max-threads=500
    #存放Tomcat 运行日志和临时文件的目录,若不配直,则默认使用系统的临时目录。
    server.tomcat.basedir=/home/sang/tmp
    
Properties 配置

Spring 提供了@Value 注解以及EnvironmentAware 接口来将Spring Environment中的数据注入到属性上, Spring Boot 对此进一步提出了类型安全配置属性( Type-safe ConfigurationProperties ) ,这样即使在数据量非常庞大的情况下,也可以更加方便地将配置文件中的数据注入Bean 中。

  1. 在application.properties进行配置,如:

    book.name=水浒传
    book.price=30.0
    book.author=施耐庵
    
  2. 编写类,如:

    @Component
    @ConfigurationProperties(prefix = "book")
    public class Book {
    
        private String name;
        private double price;
        private String author;
      //省略getter/setter
    

    注:

    • @ConfigurationProperties 中的prefix 属性描述了要加载的配置文件的前缀。
  3. 测试

YAML 配置

YAML 是JSON 的超集,简洁而强大,是一种专门用来书写配置文件的语言,可以替代application .properties 。在创建一个Spring Boot 项目时,引入的spring-boot-starter-web 依赖间接地引入了snakeyaml 依赖, snakeyaml 会实现对YAML 配置的解析。YAML 的使用非常简单,利用缩进来表示层级关系,并且大小写敏感。

YAML 不仅可以配置常规属性,也可以配置复杂属性, 例如下面一组配置:

book:
  name:红楼梦
  price:12.5
  author:曹雪芹
  feature:
    生动
    好看
    便宜

@Component
@ConfigurationProperties(prefix = "book")
public class Book {

    private String name;
    private double price;
    private String author;
    private List<String> feature;
    //省略getter/setter

Spring Boot 整合Web 开发

静态资源访问
默认策略

Spring Boot 默认会过滤所有的静态资源, 而静态资源的位置一共有5 个,分别是"classpath:/META-INF /resources/"、“classpath: /resources/”、“classpath: /static/”、“classpath :/public/“以及”/”,也就是说,开发者可以将静态资源放到这5 个位置中的任意一个。注意, 按照定义的顺序, 5 个静态资源位置的优先级依次降低。但是一般情况下, Spring Boot 项目不需要webapp 目录,所以第5 个"/"可以暂不考虑。

自定义策略

如果默认的静态资源过滤策略不能满足开发需求,也可以自定义静态资源过滤策略,
静态资源过滤策略有以下两种方式:

  1. 在自己置文件中定义

    spring.mvc.static-path-pattern=/static/**
    spring.resources.static-locations=classpath:/static
    
    注:
    (1)过滤规则为/static/**, 静态资源位置为classpath:/static/。
    (2)重新启动项目, 在浏览器中输入"localhost:8080/static/pl.png ",即可看到classpath:/static/目录下的资源。
    
  2. Java 编码定义

    也可以通过Java 编码方式来定义,此时只需要实现WebMvcConfigurer 接口即可, 然后实现该接口的addResourceHandlers 方法,代码如下:

    @Configuration
    public class MyWebMvcConfig implements WebMvcConfigurer {
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/static/**")
                    .addResourceLocations("classpath:/static");
        }
    }
    
文件上传
  1. 首先创建一个Spring Boot 项目并添加spring-boot-starter-web 依赖。然后在resources 目录下的static 目录中创建一个upload.html 文件,内容如下:

    <form action="/upload" method="post" enctype="multipart/form-data">
        选择文件:<input type="file" name="fileName" value="请选择文件">
        <input type="submit" value="提交">
    </form>
    
  2. 创建上传控制器,如:

        @PostMapping("/upload")
        @ResponseBody
        public String upload(MultipartFile fileName){
            File file = new File("D://upload");
            Random random = new Random();
            if (!file.exists()){
                file.mkdirs();
            }
    
            String oldName = fileName.getOriginalFilename();
            int ran = random.nextInt(900000)+100000;
            String newName = ran+oldName.substring(oldName.lastIndexOf("."),oldName.length());
            try {
                fileName.transferTo(new File(file,newName));
                return "上传成功";
            } catch (IOException e) {
                e.printStackTrace();
            }
            return "上传失败";
        }
    
  3. 测试

  4. 配置文件上传大小

    #配置文件上传大小
    #是否开启文件上传支持,默认为true
    spring.servlet.multipart.enabled=true
    #文件写入磁盘的闽值,默认为0
    spring.servlet.multipart.file-size-threshold=0
    #上传文件的临时保存位直
    spring.servlet.multipart.location=E:\\temp
    #上传的羊个文件的最大大小,默认为1MB
    spring.servlet.multipart.max-file-size=5MB
    #多文件上传时文件的总大小,默认为10MB
    spring.servlet.multipart.max-request-size=10MB
    #文件是否延迟解析,默认为false
    spring.servlet.multipart.resolve-lazily=false
    
@ControllerAdvice

顾名思义,@ControllerAdvice 就是@Controller 的增强版。@ControllerAdvice 主要用来处理全局数据, 一般搭配@ExceptionHandler、@ModelAttribute 以及@InitBinder 使用。

全局异常处理

@ControllerAdvice 最常见的使用场景就是全局异常处理。如果用户上传的文件超过了限制大小,就会抛出异常,此时可以通过@ControllerAdvice 结合@ExceptionHandler 定义全局异常捕获机制,代码如下:

@ControllerAdvice
public class CustomExceptionHandler {
    @ExceptionHandler(MaxUploadSizeExceededException.class)
    public void uploadException (MaxUploadSizeExceededException e, HttpServletResponse response) throws IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write("上传文件大小超出限制!");
        out.flush();
        out.close();
    }

}

只需在系统中定义CustomExceptionHandler 类,然后添加@Con位oilerAdvice 注解即可。当系统启动时,该类就会被扫描到Spring 容器中,然后定义uploadException 方法,在该方法上添加了@ExceptionHandler 注解,其中定义的MaxUploadS izeExceededException.class 表明该方法用来处理MaxUploadSizeExceededExcepti on 类型的异常。如果想让该方法处理所有类型的异常,只需将MaxUploadSizeExceededException 改为Exception 即可。

拦截器

Spring MVC 中提供了AOP 风格的拦截器,拥有更加精细的拦截处理能力。Spring Boot 中拦
截器的注册更加方便,如:

public class MyInterceptorl implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Myinterceptorl>>preHandle");
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("Myinterceptorl>>postHandle");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("Myinterceptorl>>afterCompletion");
    }
}

拦截器中的方法将按preHandle→ Controller → postHandle→ afterCompletion 的顺序执行。注意,只有preHandle 方法返回true 时后面的方法才会执行。当拦截器链内存在多个拦截器时, postHandler在拦截器链内的所有拦截器返回成功时才会调用,而afterCompletion 只有preHandle 返回true 才调用,但若拦截器链内的第一个拦截器的preHandle 方法返回false ,则后面的方法都不会执行。

配置拦截器。定义配置类进行拦截器的配置,代码如下:

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptorl()).addPathPatterns("/**")
                .excludePathPatterns("/hello");
    }
}

注:
(1)自定义类实现WebMvcConfigurer接口,实现接口中的addlnterceptors。
(2)addPathPattems 表示拦截路径, excludePathPattems 表示排除的路径。
配置 AOP

Spring 框架对AOP 提供了很好的支持。在AOP 中,有一些常见的概念需要读者了解。

  1. Joinpoint (连接点):类里面可以被增强的方法即为连接点。例如,想修改哪个方法的功能,那么该方法就是一个连接点。
  2. Pointcut(切入点):对Joinpoint 进行拦截的定义即为切入点,例如,拦截所有以insert 开始的方法,这个定义即为切入点。
  3. Advice (通知):拦截到Joinpoint 之后所要做的事情就是通知。例如, 上文说到的打印日志监控。通知分为前直通知、后直通知、异常通知、最终通知和环绕通知。
  4. Aspect (切面): Pointcut 和Advice 的结合。
  5. Target (目标对象):要增强的类称为Target。

步骤

  1. 导入jar包

    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>
    
  2. 编写Service类,如:

    public interface UserService {
    
        User findById(int id);
    
        void addUser(User user);
    
    }
    
    @Service
    public class UserServiceImpl implements UserService{
        @Override
        public User findById(int id) {
            User user = new User(id,"张三","123456","云南省");
            System.out.println(user);
            return user;
        }
    
        @Override
        public void addUser(User user) {
            System.out.println("添加成功");
            System.out.println(user);
    
        }
    }
    
  3. 编写切面

    @Component
    @Aspect
    public class UserAspect {
    
        @Pointcut("execution(* com.sp.service.*.*(..))")
        public void pct(){}
    
        @Before("pct()")
        public void before(JoinPoint jt){
            String name = jt.getSignature().getName();
            System.out.println(name+"方法开始");
        }
    
        @After("pct()")
        public void after(JoinPoint jt){
            String name = jt.getSignature().getName();
            System.out.println(name+"方法开始");
        }
    
        @AfterReturning(value = "pct()",returning = "result")
        public void afterReturning(JoinPoint jt,Object result){
            String name = jt.getSignature().getName();
            System.out.println(name+"方法返回值为: "+result);
        }
    
        @AfterThrowing(value = "pct()",throwing = "e")
        public void afterThrowing(JoinPoint jt,Exception e){
            String name = jt.getSignature().getName();
            System.out.println(name+"方法抛出了异常,异常是: "+e.getMessage());
        }
    
        @Around("pct()")
        public Object around(ProceedingJoinPoint pj) throws Throwable {
            return pj.proceed();
        }
    }
    

    注:

    1. @Aspect 注解表明这是一个切面类。
    2. @Pointcut 注解,这是一个切入点定义,execution 中的第一个*表示方法返回任意值,第二个*表示service 包下的任意类,第三个*表示类中的任意方法,括号中的两个点表示方法参数任意,即这里描述的切入点为service 包下所有类中的所有方法。
    3. @Before 注解,表示这是一个前直通知,该方法在目标方法执行之前执行。通过JoinPoint参数可以获取目标方法的方法名、修饰符等信息。
    4. @After注解,表示这是一个后直通知,该方法在目标方法执行之后执行。
    5. @AfterReturning注解,表示这是一个返回通知,在该方法中可以获取目标方法的返回值。@AfterReturning 注解的returning 参数是指返回值的变量名,对应方法的参数。
    6. @AfterThrowing 注解, 表示这是一个异常通知, 即当目标方法发生异常时,该方法会被调用,异常类型为Exception 表示所有的异常都会进入该方法中执行, 若异常类型为ArithmeticException , 则表示只有目标方法抛出的ArithmeticException 异常才会进入该方法中处理。
    7. @Around 注解,表示这是一个环绕通知。环绕通知是所有通知
      里功能最为强大的通知,可以实现前直通知、后直通知、异常通知以及返回通知的功能。

4.测试

SpringBoot 整合持久层技术

导入jar包
 <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jdbc -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>
整合JdbcTemplate
  1. 配置数据库连接

    #配置数据库
    #数据库连接池
    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
    #数据库连接地址
    spring.datasource.url=jdbc:mysql://localhost:3306/db8?characterEncoding=utf8&useSSL=false
    #用户名
    spring.datasource.username=root
    #密码
    spring.datasource.password=123456
    
  2. 创建实体类,例如:

    @Data
    public class Book implements Serializable {
    
        private int id;
        private String name;
        private String author;
        private double price;
        private String sort;
        private String publish;
        private String publication;
    }
    
  3. 创建数据库访问层,例如:

    public interface BookDao {
    
        List<Book> findAll();
    
        void insert(Book book);
    
    }
    
    @Repository
    public class BookDaoImpl implements BookDao {
       public final static String SQL_FIND_ALL = "SELECT * FROM tb_book";
       public final static String SQL_INSERT = "INSERT INTO tb_book(name,author,price,sort,publish,publication)" +
                "VALUES(?,?,?,?,?,?)";
    
        @Autowired
        private JdbcTemplate jdbcTemplate;
    
        @Override
        public List<Book> findAll() {
    
            return jdbcTemplate.query(SQL_FIND_ALL,new BeanPropertyRowMapper<>(Book.class));
        }
    
        @Override
        public void insert(Book book) {
    
            jdbcTemplate.update(SQL_INSERT,book.getName(),book.getAuthor(),book.getPrice(),book.getSort(),book.getPublish(),book.getPublication());
    
        }
    }
    
    
  4. 测试,如:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class Demo01 {
    
        @Autowired
        private BookDao dao;
    
        @Test
        public void test01(){
            List<Book> books = dao.findAll();
            for (Book b: books) {
                System.out.println(b);
            }
        }
    }
    
整合MyBatis
  1. 添加jar包

    <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</version>
            </dependency>
            
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-log4j</artifactId>
                <version>1.3.8.RELEASE</version>
            </dependency>
    
  2. 配置数据库

    #配置数据库
    #数据库连接池
    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
    #数据库连接地址
    spring.datasource.url=jdbc:mysql://localhost:3306/db8?characterEncoding=utf8&useSSL=false
    #用户名
    spring.datasource.username=root
    #密码
    spring.datasource.password=123456
    
    #配置Mybatis
    #别名
    mybatis.type-aliases-package=com.sp.bean
    # mapper.xml文件位置,如果没有映射文件,请注释掉
    mybatis.mapper-locations=classpath:mapper/*.xml
    #配置日志
    mybatis.configuration.log-impl=org.apache.ibatis.logging.log4j.Log4jImpl
    
  3. 日志文件

    log4j.rootLogger=ERROR, stdout
    log4j.logger.com.sp.dao=TRACE
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
    
  4. 编写实体类(上面已创建)

  5. 编写接口,如:

    @Repository
    public interface BookMapper {
    
        List<Book> findAll();
    }
    
    注:
    (1)@Mapper 注解,表明该接口是一个MyBatis中的Mapper,这种方式需要在每一个Mapper 上都添加注解。
    (2)在配直类上添加@MapperScan("mapper包名")注解,表示扫描mapper包下的所有接口作为Mapper,这样就不需要在每个接口上配直@Mapper注解了。
    
  6. 编写映射文件,例如:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.sp.dao.BookMapper">
        <resultMap id="bookMap" type="com.sp.bean.Book">
            <id property="id" column="id"/>
            <result property="name" column="name"/>
            <result property="author" column="author"/>
            <result property="price" column="price"/>
            <result property="sort" column="sort"/>
            <result property="publish" column="publish"/>
            <result property="publication" column="publication"/>
        </resultMap>
    
        <select id="findAll" resultMap="bookMap">
            select * from tb_book
        </select>
    
    </mapper>
    
  7. 配置包扫描

    @SpringBootApplication
    @MapperScan("com.sp.dao")
    public class MySpringBootApplication {
        public static void main(String[] args) {
            SpringApplication.run(MySpringBootApplication.class,args);
        }
    
    }
    
  8. 测试

通用mapper

通用mapper 可以极大的方便开发人员进行ORM,提供极其方便的单表增删改查。
什么是通用mapper,一句话简单说,它就是个辅助mybatis极简单表开发的组件。它不是为了替代mybatis,而是让mybatis的开发更方便。

  1. 导入jar包

     <!-- https://mvnrepository.com/artifact/tk.mybatis/mapper-spring-boot-starter -->
            <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper-spring-boot-starter</artifactId>
                <version>2.1.5</version>
            </dependency>
    
  2. 使用,例如:

    @Data
    @Table(name = "person")
    public class Person implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "t_id")
        private int id;
        @Column(name = "t_name")
        private String name;
        @Column(name = "age")
        private int age;
        @Column(name = "sex")
        private String sex;
        @Column(name = "address")
        private String address;
        @Column(name = "telephone")
        private String phone;
    }
    
    

    注:

    • 默认表名=类名,字段名=属性名
    • 表名可以使用@Table(name = “tableName”) 进行指定
    • @Column(name = “fieldName”) 指定
    • 使用@Transient 注解表示跟字段不进行映射
  3. 接口处使用,例如:

    @Repository
    public interface PersonMapper extends Mapper<Person> {
    
        @Override
        List<Person> selectAll();
    }
    
  4. 后续配置同上

  5. 测试

SpringBoot 整合视图层技术

整合Thymeleaf

Thymeleaf 是新一代Java 模板引擎,类似于Velocity、FreeMarker 等传统Java 模板引擎。与传统Java 模板引擎不同的是, Thymeleaf 支持HTML 原型,既可以让前端工程师在浏览器中直接打开查看样式, 也可以让后端工程师结合真实数据查看显示效果。同时, Spring Boot 提供了Thymeleaf自动化配置解决方案,因此在Spring Boot 中使用Thymeleaf 非常方便。

步骤

  1. 安装jar包

    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-thymeleaf -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
    
  2. 配置Thymeleaf

    #是否开启缓存,开发时可设置为false,默认为true
    spring.thymeleaf.cache=true
    #检查模板是否存在,默认为true
    spring.thymeleaf.check-template=true
    #检查模板位置是否存在,默认为true
    spring.thymeleaf.check-template-location=true
    #模板文件编码
    spring.thymeleaf.encoding=utf-8
    #模板文件位置
    spring.thymeleaf.prefix=classpath:/templates/
    #Content-Type配置
    spring.thymeleaf.servlet.content-type=text/html
    #模板文件后缀
    spring.thymeleaf.suffix=.html
    
  3. 配置控制器,例如:

    @Controller
    @RequestMapping("/book")
    public class BookController {
    
        @Autowired
        private BookService bookService;
    
        @RequestMapping("/findAll")
        public ModelAndView findAll(){
            List<Book> books = bookService.findAll();
            ModelAndView mv = new ModelAndView();
            mv.addObject("books",books);
            mv.setViewName("bookList");
            return mv;
        }
    }
    
  4. 创建视图,例如:

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>图书列表</title>
        <style>
            table{
                text-align: center;
            }
        </style>
    </head>
    <body>
    <table border="1">
        <tr>
            <th>编号</th>
            <th>书名</th>
            <th>作者</th>
            <th>价格</th>
            <th>类型</th>
            <th>出版社</th>
            <th>出版时间</th>
        </tr>
        <tr th:each="book:${books}">
            <td th:text="${book.id}"></td>
            <td th:text="${book.name}"></td>
            <td th:text="${book.author}"></td>
            <td th:text="${book.price}"></td>
            <td th:text="${book.sort}"></td>
            <td th:text="${book.publish}"></td>
            <td th:text="${book.publication}"></td>
        </tr>
    </table>
    </body>
    

    注:

    (1)把html 的名称空间,改成: xmlns:th=“http://www.thymeleaf.org” 会有语法提示

    (2)th- 指令: th- 是利用了Html5中的自定义属性来实现的。如果不支持H5,可以用data-th- 来代替。

    (3)th:each :类似于c:foreach 遍历集合,但是语法更加简洁。

    (4)th:text :声明标签中的文本

    (5)${} :这个类似与el表达式,但其实是ognl的语法,比el表达式更加强大

  5. 测试

    访问:http://localhost:8085/book/findAll 是否成功。

  6. thymeleaf其他知识

    表达式

    1. 变量表达式:变量表达式即OGNL表达式或Spring EL表达式(在Spring中用来获取model attribute的数据)。如下所示:

      ${session.user.name} 例如: <td th:text="${book.id}"></td>
      
    2. 选择(星号)表达式:选择表达式很像变量表达式,不过它们用一个预先选择的对象来代替上下文变量容器(map)来执行,如下:

      *{customer.name} 
      被指定的object由th:object属性定义:
      <tr th:each="user : ${users}" th:object="${user}">
      <td th:text="${user.id}">1</td>
      <td th:text="*{name}">张三</td>
      <td th:text="*{userName}">zhangsan</td>
      ...
      
    3. URL表达式:URL表达式指的是把一个有用的上下文或回话信息添加到URL,这个过程经常被叫做URL重写。

      (1)无参数返回:@{/order/list}
      (2)设置参数:@{/order/details(id=${orderId}, name=*{name})}
      (3)相对路径:@{../documents/report}
      (4)url表达式:<a th:href="@{/delete(id=${user.id}, userName=*{userName})}">删除</a>
      

      常用th标签

      (1)th:text:文本替换   <p th:text="${collect.description}">description</p >
      (2)th:id:替换id       <input th:id="'xxx' + ${collect.id}"/ >
      (3)th:utext:支持html的文本替换   <p th:utext="${htmlcontent}">conten</p>
      (4)th:object 替换对象< div th:object="${session.user}">
      (5)th:value 属性赋值  <input th:value="${user.name}" />
      (6)th:with  变量赋值运算  <div th:with="isEven=${prodStat.count}%2==0">< /div>
      (7)th:style 设置样式 th:style="'display:' + @{(${sitrue} ? 'none' : 'inline-block')} + ''"
      (8)th:onclick 点击事件th:onclick="'getCollect()'"
      (9)th:each 属性赋值tr th:each="user,userStat:${users}">
      (10)th:if 判断条件 <a th:if="${userId == collect.userId}" >
      (11)th:href 链接地
      (12)th:switch 多路选择,配合th:case使用  < div th:switch="${user.role}">
      (13)th:case  th:switch的一个分支 <p th:case="'admin'">User is an administrator< /p>
      (14)th:action 表单提交的地址 
           <form action="subscribe.html" th:action="@{/subscribe}">
      

      基本用法

      • 赋值、字符串拼接

        字符串拼接还有另外一种简洁的写法

        <a th:href="|/update/${user.id}|">修改</a>
        <a th:href="'/approve/' + ${user.id}">审核</a>
        
      • 条件判断 If/Unless

        Thymeleaf中使用th:if和th:unless属性进行条件判断,下面的例子中, <a> 标签只有在th:if 中条件成立时才显
        示:
        
        <h5>if指令</h5>
        <a th:if="${users.size() > 0}">查询结果存在</a><br>
        <a th:if="${users.size() <= 0}">查询结果不存在</a><br>
        <a th:unless="${session.user != null}" href="#">登录<a><br>
        
      • for 循环

         <tr th:each="book:${books}">
                <td th:text="${book.id}"></td>
                <td th:text="${book.name}"></td>
                <td th:text="${book.author}"></td>
                <td th:text="${book.price}"></td>
                <td th:text="${book.sort}"></td>
                <td th:text="${book.publish}"></td>
                <td th:text="${book.publication}"></td>
           </tr>
        
整合 FreeMarker

FreeMarker 是一个非常古老的模板引擎,可以用在Web 环境或者非Web 环境中。与Thymeleaf不同, FreeMarker 需要经过解析才能够在浏览器中展示出来。FreeMarker 不仅可以用来配置HTML页面模板,也可以作为电子邮件模板、配置文件模板以及源码模板等。

  1. 下载jar包

    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-freemarker -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-freemarker</artifactId>
            </dependency>
    
  2. 配置FreeMarker

    #HttpServletRequest 的属性是否可以覆盖controller中model的同名项
    spring.freemarker.allow-request-override=false
    #HttpSession的属性是否可以覆盖controller中的model的同名项
    spring.freemarker.allow-session-override=false
    #是否开启缓存
    spring.freemarker.cache=false
    #模板文件编码
    spring.freemarker.charset=utf-8
    #是否检查模板位置
    spring.freemarker.check-template-location=true
    #Content-Type的值
    spring.freemarker.content-type=text/html
    #是否将HttpServletRequest 中的属性添加到Model中
    spring.freemarker.expose-request-attributes=false
    #是否将HttpSession 中的属性添加到Model中
    spring.freemarker.expose-session-attributes=false
    #模板文件后缀
    spring.freemarker.suffix=.ftl
    #模板文件位置
    spring.freemarker.template-loader-path=classpath:/templates/
    
  3. 创建控制器,同上

  4. 创建视图

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>图书列表</title>
        <style>
            table{
                text-align: center;
            }
        </style>
    </head>
    <body>
    <table border="1">
        <tr>
            <th>编号</th>
            <th>书名</th>
            <th>作者</th>
            <th>价格</th>
            <th>类型</th>
            <th>出版社</th>
            <th>出版时间</th>
        </tr>
       <#if books ??&& (books?size>0)>
           <#list books as book>
               <tr>
                   <td>${book.id}</td>
                   <td>${book.name}</td>
                   <td>${book.author}</td>
                   <td>${book.price}</td>
                   <td>${book.sort}</td>
                   <td>${book.publish}</td>
                   <td>${book.publication}</td>
               </tr>
           </#list>
    
       </#if>
    </table>
    </body>
    
  5. 测试,同上

Mybatis Plus插件使用

  1. 导入jar包

    <!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.3.2</version>
    </dependency>
    
  2. 配置配置文件

    #配置数据库
    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
    #配置数据库驱动
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    #请求地址
    spring.datasource.url=jdbc:mysql://localhost:3306/db8?characterEncoding=utf8&useSSL=false
    #用户名
    spring.datasource.username=root
    #密码
    spring.datasource.password=123456
    
    #配置mybatis plus
    #定义别名包 将实体对象的包路径进行封装.
    #mybatis-plus.type-aliases-package=com.sp.pojo
    #mybatis-plus.mapper-locations=classpath:mapper/*.xml
    
    mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.log4j.Log4jImpl
    
    
  3. 编写实体类

  4. 编写mapper映射接口,如:

    @Repository
    public interface BookMapper extends BaseMapper<Book> {
    }
    
  5. 测试,如:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class BookTest {
    
        @Autowired
        private BookMapper bookMapper;
    
        @Test
        public void test01(){
            List<Book> books = bookMapper.selectList(null);
    
        }
    }
    
常用注解

MyBatisPlus提供了一些注解供我们在实体类和表信息出现不对应的时候使用。通过使用注解完成逻辑上匹配。
@TableName :实体类的类名和数据库表名不一致
@TableId :实体类的主键名称和表中主键名称不一致
@TableField :实体类中的成员名称和表中字段名称不一致

如果mysql自增主键注解策略设置如下:@TableId(type = IdType.AUTO)

分页
内置分页
  1. 添加内容

    @Configuration
    public class MybatisPlusConfig {
    
        @Bean
        public PaginationInterceptor paginationInterceptor(){
    
            return new PaginationInterceptor().setCountSqlParser(new JsqlParserCountOptimize(true));
        }
    }
    
  2. 使用MybatisPlus内置分页测试,如:

        @Test
        public void test06(){
            Page<Book> page = new Page<>(1,3);
    
            IPage<Book> bookPage = bookMapper.selectPage(page,new QueryWrapper<>());
            List<Book> books = bookPage.getRecords();
            System.out.println("总条数: " + bookPage.getTotal());
            System.out.println("当前页数: " + bookPage.getCurrent());
            System.out.println("当前每页显示数: " + bookPage.getSize());
            System.out.println("总页数: "+bookPage.getPages());
        }
    
自定义xml分页
  1. 在配置中文件中添加以下信息:

    配置mybatis plus
    #定义别名包 将实体对象的包路径进行封装.
    mybatis-plus.type-aliases-package=com.sp.pojo
    mybatis-plus.mapper-locations=classpath:mapper/*.xml
    
  2. 编写映射接口,例如:

    @Repository
    public interface BookMapper extends BaseMapper<Book> {
    
        public IPage<Book> findByPage(@Param("p")IPage<Book> page);
    }
    
  3. 编写映射器,例如:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.sp.mapper.BookMapper">
    
        <select id="findByPage" resultType="book">
            select * from tb_book
        </select>
    </mapper>
    
  4. 编写测试,例如:

        @Test
        public void test07(){
            Page<Book> page = new Page<>(1,3);
            IPage<Book> bookPage = bookMapper.findByPage(page);
            List<Book> books = bookPage.getRecords();
        }
    
pageHelper分页
  1. 添加jar包

    <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>5.2.0</version>
    </dependency>
    
  2. 添加以下内容,例如:

    @Configuration
    public class MybatisPlusConfig {
    
        @Bean
        public PaginationInterceptor paginationInterceptor(){
    
            return new PaginationInterceptor().setCountSqlParser(new JsqlParserCountOptimize(true));
        }
    
        @Bean
        public PageInterceptor pageInterceptor(){
            return new PageInterceptor();
        }
    }
    
  3. 编写映射接口,同上

  4. 测试,例如:

     @Test
        public void test08(){
            PageHelper.startPage(2,3);
            List<Book> b1 = bookMapper.selectList(null);
            PageInfo<Book> pageInfo = new PageInfo<>(b1);
            List<Book> books = pageInfo.getList();
            System.out.println("每⻚显示条数:"+pageInfo.getPageSize());
            System.out.println("当前⻚的条数:"+pageInfo.getSize());
            System.out.println("总条数:"+pageInfo.getTotal());
            System.out.println("总⻚数:"+pageInfo.getPages());
            System.out.println("上⼀⻚:"+pageInfo.getPrePage());
            System.out.println("下⼀⻚:"+pageInfo.getNextPage());
            System.out.println("当前⻚:"+pageInfo.getPageNum());
        }
    
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值