Springboot 快速了解

Springboot 快速了解

springboot(一)

1、什么是springboot及其优点?

​ Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。

spring boot来简化spring应用开发,约定大于配置,去繁从简,just run就能创建一个独立的,产品级别的应用。

Spring Boot 优点非常多,如:

  • 独立运行
  • 简化配置
  • 自动配置
  • 无代码生成和xml配置
  • 应用监控

2、spring、springmvc、springboot的区别?

**spring: **

​ 一个IOC和AOP框架,项目中对象的管理权交给了容器。有七大模块。

springmvc:

​ 是spring中的一个web模块。采用的mvc模式,通过DispatcherServer前端控制器、ModelAndView 模型和视图、ViewResolver视图解析器实现了web开发。

springboot:
Spring 和 SpringMVC 的问题在于需要配置大量的参数。Spring Boot 通过一个自动配置和启动的项来目解决这个问题。为了更快的构建产品就绪应用程序,Spring Boot 提供了一些非功能性特征。

3、springboot创建web工程

springboot不建议使用jsp作为开发模板,默认使用thymeleaf模板引擎作为动态网页技术。

工程目录:

image-20200714150046191

resources目录:

​ static: 存放静态内容

​ templates:模板引擎的动态网页内容

​ application.properties: 全局配置文件

springboot中页面的加载顺序:

​ 首页加载顺序:static > public > templates

​ 错误页面加载:在static或 public或 templates中创建error目录,定义4xx.html、5xx.html即可

springboot中的启动器:

https://docs.spring.io/spring-boot/docs/2.3.1.RELEASE/reference/html/using-spring-boot.html#using-boot

NameDescription
spring-boot-starterCore starter, including auto-configuration support, logging and YAML 核心启动器,包括自动配置支持、日志记录和YAML
spring-boot-starter-activemqStarter for JMS messaging using Apache ActiveMQ
spring-boot-starter-amqpStarter for using Spring AMQP and Rabbit MQ
spring-boot-starter-aopStarter for aspect-oriented programming with Spring AOP and AspectJ
spring-boot-starter-artemisStarter for JMS messaging using Apache Artemis
spring-boot-starter-batchStarter for using Spring Batch
spring-boot-starter-cacheStarter for using Spring Framework’s caching support
spring-boot-starter-data-cassandraStarter for using Cassandra distributed database and Spring Data Cassandra
spring-boot-starter-data-cassandra-reactiveStarter for using Cassandra distributed database and Spring Data Cassandra Reactive
spring-boot-starter-data-couchbaseStarter for using Couchbase document-oriented database and Spring Data Couchbase
spring-boot-starter-data-couchbase-reactiveStarter for using Couchbase document-oriented database and Spring Data Couchbase Reactive
spring-boot-starter-data-elasticsearchStarter for using Elasticsearch search and analytics engine and Spring Data Elasticsearch
spring-boot-starter-data-jdbcStarter for using Spring Data JDBC
spring-boot-starter-data-jpaStarter for using Spring Data JPA with Hibernate
spring-boot-starter-data-ldapStarter for using Spring Data LDAP
spring-boot-starter-data-mongodbStarter for using MongoDB document-oriented database and Spring Data MongoDB
spring-boot-starter-data-mongodb-reactiveStarter for using MongoDB document-oriented database and Spring Data MongoDB Reactive
spring-boot-starter-data-neo4jStarter for using Neo4j graph database and Spring Data Neo4j
spring-boot-starter-data-r2dbcStarter for using Spring Data R2DBC
spring-boot-starter-data-redisStarter for using Redis key-value data store with Spring Data Redis and the Lettuce client
spring-boot-starter-data-redis-reactiveStarter for using Redis key-value data store with Spring Data Redis reactive and the Lettuce client
spring-boot-starter-data-restStarter for exposing Spring Data repositories over REST using Spring Data REST
spring-boot-starter-data-solrStarter for using the Apache Solr search platform with Spring Data Solr
spring-boot-starter-freemarkerStarter for building MVC web applications using FreeMarker views
spring-boot-starter-groovy-templatesStarter for building MVC web applications using Groovy Templates views
spring-boot-starter-hateoasStarter for building hypermedia-based RESTful web application with Spring MVC and Spring HATEOAS
spring-boot-starter-integrationStarter for using Spring Integration
spring-boot-starter-jdbcStarter for using JDBC with the HikariCP connection pool
spring-boot-starter-jerseyStarter for building RESTful web applications using JAX-RS and Jersey. An alternative to spring-boot-starter-web
spring-boot-starter-jooqStarter for using jOOQ to access SQL databases. An alternative to spring-boot-starter-data-jpa or spring-boot-starter-jdbc
spring-boot-starter-jsonStarter for reading and writing json
spring-boot-starter-jta-atomikosStarter for JTA transactions using Atomikos
spring-boot-starter-jta-bitronixStarter for JTA transactions using Bitronix. Deprecated since 2.3.0
spring-boot-starter-mailStarter for using Java Mail and Spring Framework’s email sending support
spring-boot-starter-mustacheStarter for building web applications using Mustache views
spring-boot-starter-oauth2-clientStarter for using Spring Security’s OAuth2/OpenID Connect client features
spring-boot-starter-oauth2-resource-serverStarter for using Spring Security’s OAuth2 resource server features
spring-boot-starter-quartzStarter for using the Quartz scheduler
spring-boot-starter-rsocketStarter for building RSocket clients and servers
spring-boot-starter-securityStarter for using Spring Security
spring-boot-starter-testStarter for testing Spring Boot applications with libraries including JUnit, Hamcrest and Mockito
spring-boot-starter-thymeleafStarter for building MVC web applications using Thymeleaf views
spring-boot-starter-validationStarter for using Java Bean Validation with Hibernate Validator
spring-boot-starter-webStarter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container
spring-boot-starter-web-servicesStarter for using Spring Web Services
spring-boot-starter-webfluxStarter for building WebFlux applications using Spring Framework’s Reactive Web support
spring-boot-starter-websocketStarter for building WebSocket applications using Spring Framework’s WebSocket support
spring-boot-starter-actuatorStarter for using Spring Boot’s Actuator which provides production ready features to help you monitor and manage your application
spring-boot-starter-tomcatStarter for using Tomcat as the embedded servlet container. Default servlet container starter used by spring-boot-starter-web
		<!--springboot 核心启动器(自动配置、日志、YAML)-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

         <!--springmvc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--监视和管理应用程序-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!--thymeleaf模板引擎-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
		
        <!--springboot热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

第三方依赖添加到springboot中 :

https://mvnrepository.com/

image-20200714155114673

        <!--mybatis-springboot 启动器-->
        <dependency>
             <groupId>org.mybatis.spring.boot</groupId>
              <artifactId>mybatis-spring-boot-starter</artifactId>
              <version>2.1.2</version>
         </dependency>

        <!--druid 连接池-->
         <dependency>
              <groupId>com.alibaba</groupId>
              <artifactId>druid-spring-boot-starter</artifactId>
              <version>1.1.22</version>
          </dependency>

4、springboot中的jsp工程

  1. 创建工程,同时在main目录中创建以下目录:
# 工程目录
springboot-03
  |--src
    |--main
      |--java
        |--com.newer.springboot
          |--config
          |--controller
          |--mapper
          |--model
          |--service
        |--Springboot03Application
      |--resources
        |--static
        |--templates
        |--application.properties
      |--webapp
        |--WEB-INF
		  |--views
			|--index.jsp
    |--test
  |--target
  |--pom.xml

  1. 同时把webapp设置为工程中的Web Resource Directories

image-20200715142310409

  1. 改pom.xml

    <!--springboot默认不支持jsp,官网建议使用模板引擎-->
    <!--jsp依赖-->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <scope>provided</scope>
    </dependency>
    
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
    </dependency>
    
    <!-- tomcat支持 -->
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
        <scope>provided</scope>
    </dependency>
    
    <!-- 添加spring tomcat 否则jsp页面显示为下载-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
  2. 修改全局配置application.proteties

    # 设置端口号
    server.port=80
    
    # 设置工程路径  http://localhost:8088/springboot
    # server.servlet.context-path=/springboot
    
    # 设置spring mvc
    spring.mvc.view.prefix=/WEB-INF/views/
    spring.mvc.view.suffix=.jsp
    
  3. 编写Controller层:

    @Controller
    public class UserController {
    
        @RequestMapping({"/index","/"})
        public String index(){
            return "index";
        }
    }
    
  4. 使用idea中的maven插件启动项目

    命令:mvn spring-boot:run

image-20200714162417952

springboot(二)

需要了解

  1. springboot几种启动方式
  2. springboot中jsp工程的启动方式
  3. springboot+mybatis集成[重点]
  4. springboot静态资源管理

常见问题:

  1. 打不到jsp页面?

    1. IDEA2018.3配置的maven版本3.3+以上,3.6.0以下

    2. 网络问题无法加载依赖

    3. 启动jsp工程:mvn spring-boot:run

  2. 返回的是页面的名称,不是真实的页面内容?

    只能使用@Controller注解,不要使用@RestController或@ResponseBody

    @Controller
    public class UserController {
    
        //设置欢迎页 http://localhost/springboot/index.jsp
        @RequestMapping({"/index","/"})
        public String index(){
            return  "index";
        }
    }
    

1、springboot三种启动方式

1) 直接运行main方法

image-20200715145516742

2) 使用mvn插件或命令:mvn spring-boot:run

3) 打包后运行: java -jar 方式

image-20200715150003439

打包命令:mvn package

运行命令:java -jar springboot-01-0.0.1-SNAPSHOT.jar

2、springboot中jsp工程的启动方式

  1. 使用mvn插件(使用的是内置tomcat): mvn spring-boot:run

  2. 配置外置的tomcat启动(了解)

    a. 修改主启动类

    @SpringBootApplication
    public class Springboot04Application extends SpringBootServletInitializer {
    
        @Override
        protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
            return builder.sources(Springboot04Application.class);
        } 
    
        public static void main(String[] args) {
            SpringApplication.run(Springboot04Application.class, args);
        }
    
    }
    

    b. 配置外部tomcat运行war包:

image-20200715143911948

image-20200715144027452

image-20200715144138023

解决tomcat控制台乱码问题:

在tomcat服务中修改vm options: -Dfile.encoding=UTF-8

image-20200715145231793

3、springboot集成mybatis[重点]

image-20200715154049310

  1. 创建数据表

    create table t_user
    (
      id         int(10) auto_increment comment '编号'
        primary key,
      username   varchar(50) default '' not null comment '用户名',
      password   varchar(50) default '' not null comment '密码',
      createTime datetime    not null on update CURRENT_TIMESTAMP comment '创建时间'
    )
      comment 't_user' charset = utf8mb4;
    
    
  2. 改pom.xml

    		<!--mysql驱动-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
    
            <!--mybatis 集成 spring boot-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.0.1</version>
            </dependency>
    
            <!--druid连接接-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>1.1.22</version>
            </dependency>
    
  3. 改配置文件application.properties

    # 设置数据库
    spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC
    spring.datasource.username=root
    spring.datasource.password=123456
    
    # 设置mybatis(用于xml编码时)
    mybatis.type-aliases-package=com.newer.springboot.model
    mybatis.mapper-locations=classpath:/mapper/*.xml
    
  4. 写实体类

    @Data
    public class User {
        private  Integer id;
        private  String username;
        private String password;
        private Date createTime;
    }
    
  5. 写mapper接口

    @Mapper
    public interface UserMapper {
        @Select("select * from t_user where id = #{id}")
        User findById(@Param("id") Integer id);
    }
    
    
  6. 写service接口

    public interface UserService {
        User findById(Integer id);
    }
    
    
  7. 写servicer接口的实现类

    @Service
    public class UserServiceImpl implements UserService {
    
        @Autowired
        UserMapper userMapper;
    
        @Override
        public User findById(Integer id) {
            return userMapper.findById(id);
        }
    }
    
    
  8. 写controller层

    @Controller
    public class UserController {
        @Autowired
        UserService userService;
    
    
        //设置欢迎页 http://localhost/springboot/index.jsp
        @RequestMapping({"/index","/"})
        public String index(){
            return  "index";
        }
    
        @RequestMapping("/getUser")
        @ResponseBody
        public User getUserById(){
            User user = userService.findById(1);
            return user;
        }
    }
    
  9. 测试

    image-20200715154324167

4、springboot集成mybatis-plus

官网: https://mp.baomidou.com/

mybtais-plus 为简化开发而生,只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑。

  1. 创建数据表

  2. 改pom

    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
    
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.1.2</version>
            </dependency>
    
            <!--对mybatis进行了增强-->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.3.0</version>
            </dependency>
    
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>1.1.22</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
                <optional>true</optional>
            </dependency>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
    
  3. 改全局配置文件application.properties

    # 设置端口号
    server.port=80
    
    # 设置数据库
    spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=UTC
    spring.datasource.username=root
    spring.datasource.password=123456
    
    # 设置mybatis
    mybatis.type-aliases-package=com.newer.springboot.model
    mybatis.mapper-locations=classpath:/mapper/*.xml
    
  4. 写实体类

    @Data
    @TableName("t_user")
    public class User {
        @TableId
        private  Integer id;
        private  String username;
        private String password;
    
        @TableField("createTime")
        private Date createTime;
    }
    
  5. mapper接口

    @Mapper
    public interface UserMapper extends BaseMapper<User> {
    
    }
    
  6. 写servicer接

    public interface UserService extends IService<User> {
        
    }
    
  7. 写servicer接口实现类

    @Service("userService")
    public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {
        
    }
    
    
  8. 写controller层

    @RestController
    public class UserController {
        @Autowired
        UserService userService;
    
        @RequestMapping("/getUser")
        public User getUserById(){
            User user = userService.getById(1);
            return user;
        }
    
        @RequestMapping("/getUserList")
        public List<User> getUsers(){
            List<User> users = userService.list();
            return users;
        }
    
    }
    
  9. 测试

5、springboot静态资源

官网: https://www.webjars.org/

方式一:常规方式

  1. 创建相应静态包

    image-20200715233406679.png

  2. 引用静态资源

    <script src="${pageContext.request.contextPath}/js/jquery.js"></script>
    

方式二:webjars方式

  1. 修改pom.xml

    <!--Webjars版本定位工具(前端)-->
    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>webjars-locator-core</artifactId>
    </dependency>
    
    <!--jquery-->
    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>jquery</artifactId>
        <version>3.5.1</version>
    </dependency>
    
    <!--bootstrap-->
    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>bootstrap</artifactId>
        <version>3.4.1</version>
    </dependency>
    
  2. 引用webjars资源

    <script src="webjars/jquery/jquery.js"></script>
    
    <link rel="stylesheet" href="webjars/bootstrap/css/bootstrap.css"/>
    
  3. 测试

Springboot(三)

需要了解:

  1. springboot中的注解

  2. springboot环境切换

  3. 分页

常见问题:

  1. 怎么处理表单重复提交

session: 会话对象。唯一的id

  1. 了解权限管理框架有哪些及区别?

appche shiro: java权限框架

spring-security: 以spring为基础

  1. 高并发解决订单编号的几种方式

  2. 标识列,主键,自动增长

  3. 随机数类

  4. rownum、序列sequenct。

  5. reids缓存 单线程,运行在内存中的nosql数据库

  6. 使用各大厂商的方案:雪花算法

springboot中的YAML文件

YAML是JSON的超集,springboot默认使用YAML文件作为应用程序的配置文件,配置文件名:application.yml

springboot多环境切换

​ 开发的项目存在多个环境,比如开发环境(dev)、生产环境(prod)、测试环境(test)。

  1. 创建三个yml文件

    application.yml – 主环境文件(相当于application-default.yml)

    # 主环境切换
    spring:
      profiles:
        active: dev
    

    application-dev.yml – 开发环境文件

    # 设置端口(注意在属性值之间加空格)
    server:
      port: 80
    
    # 工程名称
    spring:
      application:
        name: springboot
    
    

    application-prod.yml – 生产环境文件

    # 设置端口(注意在属性值之间加空格)
    server:
      port: 8088
    
    # 工程名称
    spring:
      application:
        name: springboot
    
    

springboot中的注解(重点)

系统中的注解

​ 1. @SpringBootApplication: 运行项目

@SpringBootConfiguration 	-- 读取springboot中的配置文件
@EnableAutoConfiguration 	-- 读取自动配置中的配置文件
@ComponentScan				-- 包扫描(默认把主包下的文件扫描进行)
  1. @Bean: 相当于实例化bena对象
  2. @Scope:bean的作用域
  3. @Configuration: 配置类相当于xml文件
  4. @ConfiguationProperties(“person”) :默认从全局文件中获取值
  5. @Value():给属性赋值
  6. @PropertySource() :用于加载指定属性值
  7. @ImportSource():用于加载xml文件
  8. @Import():用于引入带有@Configuration的java类
Spring Web中的注解

@ControllerAdvice
@CookieValue
@CrossOrigin
@DeleteMapping
@ExceptionHandler
@GetMapping
@InitBinder
@Mapping
@MatrixVariable
@ModelAttribute
@package-info
@PatchMapping
@PathVariable
@PostMapping
@PutMapping
@RequestAttribute
@RequestBody
@RequestHeader
@RequestMapping
@RequestParam
@RequestPart
@ResponseBody
@ResponseStatus
@RestController
@RestControllerAdvice
@SessionAttribute
@SessionAttributes

Mybatis中的注解

@Delete
@Insert
@Many
@Mapper
@One
@Param
@Result
@ResultMap
@Results
@ResultType
@Select
@Update

Mybatis中的分页

  1. 自己写分页工具类: PagerUitl.java

  2. 使用分页插件: PageHelper

​ 官网:https://github.com/pagehelper/pagehelper-spring-boot

  1. 使用Mybatis-plus中的分页

Springboot(四)

  1. 全局异常处理

  2. 数据统一封装

  3. swagger2接口文档

  4. 测试工具postman使用

数据统一封装

  1. 为什么要封装数据

    为了提高开发组的效率,统一为APP端、Web端、Java端制定开发规范。

    {
        "code": "返回的状态码",
        "iserror":"是否有错误",
        "msg": "返回的信息描述",
        "data": "返回的数据"
    }
    
  2. 怎么封装

    1. 统一返回状态码:类似于200、404等。 可以2000、2404
    区间表示的错误
    0000表示响应成功
    1000 ~ 1999表示参数错误
    2000 ~ 2999表示用户错误
    3000 ~ 3999表示接口异常
    4000表示服务端错误
    1. 统一错误消息:与返回状态码写在同一个类中
    /**
     * @desc: 状态码
     *
     */
    public enum EnumCode {
        /**
         * 200请求成功
         */
        OK(200, "请求成功"),
        /**
         * 303登录失败
         */
        LOGIN_FAIL(303, "登录失败"),
        /**
         * 400请求参数出错
         */
        BAD_REQUEST(400, "请求参数出错"),
        /**
         * 401没有登录
         */
        UNAUTHORIZED(401, "没有登录"),
        /**
         * 403没有权限
         */
        FORBIDDEN(403, "没有权限"),
        /**
         * 410已被删除
         */
        GONE(410, "已被删除"),
        /**
         * 423已被锁定
         */
        LOCKED(423, "已被锁定"),
        /**
         * 500服务器出错
         */
        INTERNAL_SERVER_ERROR(500, "服务器出错"),
        /**
         * 异常
         */
        EXCPTION_ERROR(4001, "异常");
    
        private final Integer value;
        private final String text;
    
        private EnumCode(Integer value, String text) {
            this.value = value;
            this.text = text;
        }
    
        /**
         * 获取value
         */
        public Integer getValue() {
            return this.value;
        }
    
        /**
         * 获取Text
         */
        public String getText() {
            return this.text;
        }
    }
    
    1. 创建一个结果集返回类

      /**
       * 统一响应的数据返回类
       */
      public class ResponseResult implements Serializable {
          private Integer code;
          private Boolean hasError;
          private String message;
          private Object data;
      
    2. controller层

      @RestController
      public class UserController {
      
          /**
           * restful 风格(不能使用动名,只能是名词)
           * 对于实体对象,通过url就能返应状态
           * 请求方式+实体名
           * <p>
           * getMapping: 获取数据    /users  /user/1
           * postMapping: 添加数据   /user
           * putMapping: 修改数据    /user/1
           * deleteMapping: 删除数据 /user/1
           *
           * @return
           */
          @GetMapping("/users")
          public ResponseResult getUsers() {
              List<User> userList = new ArrayList<>();
              userList.add(new User(1, "a", "123"));
              userList.add(new User(2, "b", "123"));
              userList.add(new User(3, "c", "123"));
              userList.add(new User(4, "d", "123"));
              userList.add(new User(5, "e", "123"));
      
              return new ResponseResult().setCode(200)
                  .setHasError(false)
                  .setMessage(null)
                  .setData(userList);
          }
      
          // 演示错误返回结果
          @GetMapping("/user/{id}")
          public ResponseResult getUserById(@PathVariable("id") int id) {
      
              return new ResponseResult()
                      .setCode(2001)
                      .setHasError(true)
                      .setMessage("用户密码错误")
                      .setData(null);
          }
      }
      

全局异常处理

  1. 什么是异常

    程序中出现的错误,称为异常

    分类:Error(硬件)和Exception(运行时异常)

  2. 全局异常类:BasicErrorController

    SpringBoot内置了一个BasicErrorController对异常进行统一的处理,当在页面发生异常的时候会自动把请求转到/error。

    也可以自定义页面内容,只需在classpath路径下新建error页面即可。

  3. 全局异常解析器:HandlerExceptionResolver

  4. 自定义异常

    1. 创建一个MyException类,继承Exception类

    2. 重写构造方法

  5. 统一异常处理器(GlobalErrorHandler)
    @ControllerAdvice 限定范围 例如扫描某个控制层的包

    @RestControllerAdvice 全部异常处理返回json

    @ExceptionHandler 指定异常 例如指定处理运行异常,用于方法上。

  6. 全局异常的开发步骤

    1. 自定义异常解析器继承HandlerExceptionResolver

      /**
       * 自定义一个异常解析器
       * 作用:统一处理框架中的异常信息
       */
      public class MyExceptionResolver implements HandlerExceptionResolver {
          @Override
          public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) {
              ModelAndView mv = new ModelAndView();
              mv.setViewName("error");
              if(e instanceof MyException){
                  mv.addObject("ex",e.getMessage());
              }else if(e instanceof IOException){
                  mv.addObject("ex","IO流异常");
              }else{
                  mv.addObject("ex", "未知异常");
              }
              return mv;
          }
      }
      
    2. 创建统一的异常处理类(把controlelr中的一个异常处理方法提升到全局方法)

      @ControllerAdvice
      public class MyExceptionHandler {
      
          @ExceptionHandler
          public String handlerException(Exception e, Model model){
              if(e instanceof MyException){
                  model.addAttribute("ex", e.getMessage());
              }else if(e instanceof Exception){
                  model.addAttribute("ex", "哈哈哈,我就是黑客!");
              }
              return "/error/error";
          }
      }
      
    3. 在controller层抛出异常

      	@RequestMapping("/hello")
          public String hello() throws Exception  {
              throw new MyException("你的网站错误!");
             // return "Hello World!";
          }
      

      总结:开发时只需要在mappr层、server层、controller层中抛出异常,不需要处理。

Swagger2的应用

  1. 改pom.xml

    <!--Swagger 引入依赖-->
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <version>2.6.0</version>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>2.6.0</version>
    </dependency>
    
    1. 改应用程全局配置application.propertis

      # swagger配置
      swagger.enable = true
      
    2. swagger全局配置

    @Configuration
    @EnableSwagger2
    public class Swagger2Config {
    
        @Value("${swagger.enabled}")
        private boolean enableSwagger;
    
        @Bean
        public Docket createRestApi(){
            return new Docket(DocumentationType.SWAGGER_2)
                    .apiInfo(apiInfo())
                    //是否开启
                    .enable(enableSwagger)
                    .select()
                    //扫描的路径包,设置basePackage会将包下的所有被@Api标记类的所有方法作为api
                    .apis(RequestHandlerSelectors.basePackage("com.newer.springboot.controller"))
                    //指定路径处理PathSelectors.any()代表所有的路径
                    .paths(PathSelectors.any())
                    .build();
        }
    
        private ApiInfo apiInfo() {
            return new ApiInfoBuilder()
                    //设置文档标题
                    .title("Spring-boot项目")
                    //文档描述
                    .description("V1.0接口规范")
                    //服务条款URL
                    .termsOfServiceUrl("http://127.0.0.1:80/")
                    //版本号
                    .version("1.0.0")
                    .build();
        }
    
    }
    
    1. controller层使用

      @RestController
      @Api(value="用户接口",description="用户接口测试")
      public class UserController {
      
          @RequestMapping("/hello")
          @ApiOperation(value="测试",httpMethod="GET",notes="测试")
          public String hello() throws Exception  {
              throw new MyException("你的网站错误!");
             // return "Hello World!";
          }
      
          /**
           * restful 风格(不能使用动名,只能是名词)
           * 对于实体对象,通过url就能返应状态
           * 请求方式+实体名
           * <p>
           * getMapping: 获取数据    /users  /user/1
           * postMapping: 添加数据   /user
           * putMapping: 修改数据    /user/1
           * deleteMapping: 删除数据 /user/1
           *
           * @return
           */
          @GetMapping("/users")
          @ApiOperation(value="查询所有用户",httpMethod="GET",notes="查看所有用户详情")
          public ResponseResult getUsers() {
              List<User> userList = new ArrayList<>();
              userList.add(new User(1, "a", "123"));
              userList.add(new User(2, "b", "123"));
              userList.add(new User(3, "c", "123"));
              userList.add(new User(4, "d", "123"));
              userList.add(new User(5, "e", "123"));
      
              return new ResponseResult().setCode(200).setHasError(false).setMessage(null).setData(userList);
          }
      
          // 演示错误返回结果
          @GetMapping("/user/{id}")
          @ApiOperation(value="根据id获取用户",httpMethod="GET",notes="查看用户错误演示")
          public ResponseResult getUserById(@PathVariable("id") int id) {
      
              return new ResponseResult()
                      .setCode(2001)
                      .setHasError(true)
                      .setMessage("用户密码错误")
                      .setData(null);
          }
      }
      
      
  2. 测试

    http://localhost/swagger-ui.html

Swagger2+swagger-bootstrap-ui的使用(去了解)

Springboot(五)

  1. Aop日志

  2. 快速实现事务

  3. 拦截器Intercepote

  4. 数据校验

了解部分:

  1. 定时任务

  2. 发送email

  3. 解决前后端分离项目的后台跨域问题

  4. 了解RestTemplate进行服务调用

springboot实现快速事务

  1. 什么是事务?

    ​ 把多条sql语句当作一个逻辑执行单元,要么同时成功,要么同时失败!

  2. 事务四个特性

    ​ 原子性(atomic):要么都成功,要么都失败
    ​ 一致性(consistent):事务提交前后数据保持一致
    ​ 隔离性(isolate):事务互相不影响
    ​ 持久性(durable):一旦提交,永久保存,不能回滚

  3. 事务并发产生的问题:
    ​脏读:一个事务读取另一个事务未提交的一条数据
    幻读:一个事务读取另一个事务添加的多条数据
    不可重复读:一个事务读取另一个事务修改的一条数据

  4. 事务4种隔离性(级别越低数字越小):

    1. 读未提交(READ_UNCOMMITED):一个事务可以读取另一个未提交事务的数据,隔离级别最差。
    2. 读已提交(READ_COMMITED):一个事务要等另一个事务提交后才能读取数据,可避免脏读,不可重复读。
    3. 可重复读(REPEATABLE_READ):就是在开始读取数据(事务开启)时,不再允许修改操作,可避免脏读、不可重复读。
    4. 串行化(SERIALIZABLE):完全符合ACID原则,可避免脏读、不可重复读、幻读,但效率最差。
  5. 事务7种传播机制

    传播行为意义
    REQUIRED如果当前有事务则加入事务,如果没有事务,则创建一个新的(默认值)
    NOT_SUPPORTED支持当前事务,如果没有当前事务,就以非事务方法执行,相当于没有事务
    REQUIRES_NEW不管是否存在事务,都创建一个新的事务,原来的方法挂起,新的方法执行完毕后,继续执行老的事务
    MANDATORY必须在一个已有的事务中执行,否则报错
    NEVER必须在一个没有的事务中执行,否则报错
    SUPPORTS其他bean调用这个方法时,如果声明了事务,则就用这个事务,如果没有声明事务,那就不用事务
    NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与REQUIRED类似的操作

    在springboot开发时一般使用数据库的默认隔离级别和默认传播行为,源码如下:

    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited
    @Documented
    public @interface Transactional {
        @AliasFor("transactionManager")
        String value() default "";
    
        @AliasFor("value")
        String transactionManager() default "";
    	// 默认传播行为
        Propagation propagation() default Propagation.REQUIRED;
    	// 默认隔离级别
        Isolation isolation() default Isolation.DEFAULT;
    
        int timeout() default -1;
    
        boolean readOnly() default false;
    
        Class<? extends Throwable>[] rollbackFor() default {};
    
        String[] rollbackForClassName() default {};
    
        Class<? extends Throwable>[] noRollbackFor() default {};
    
        String[] noRollbackForClassName() default {};
    }
    
    
  6. 事务的注解

    @Transactional : 一般用于service业务层

    @Service("userService")
    @Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED,readOnly = false )
    public class UserServiceImpl implements UserService {
    
        @Resource
        UserMapper userMapper;
    
        @Override
        public User findById(int id) {
            User user = userMapper.selectById(id);
            return user;
        }
    
        @Override
        public List<User> findAll() {
            return userMapper.selectAll();
        }
    
        @Override
        public Boolean updateById(String username, int id) throws SQLException  {
            Boolean flag = userMapper.updateById(username, id);
            // 事务默认只对运行时的异常有效
            // SQLSQLException不是runtimeException的子类
            throw new SQLException("修改失败");
            // throw new RuntimeException("修改失败");
        }
    }
    
  7. springboot中的事务坑

    默认只对运行时异常有效。对sqlException无效。

    @Transactional(rollbackFor = Exception.class)
    

数据校验

  1. 为什么前后台都要进行数据校验?

    前台校验可以解决用户输入问题,后台校验正确性和准确性,一般可以跳过前台的验证机制。为了避免网站受到攻击。

  2. springboot中校验数据开发步骤

    1. 改pom.xml
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>
    
    1. 在model层的实体类上加注解

    数据校验注解

    @AssertFalse
    @AssertTrue
    @DecimalMax
    @DecimalMin
    @Digits
    @Email
    @Future
    @FutureOrPresent
    @Max
    @Min
    @Negative
    @NegativeOrZero
    @NotBlank
    @NotEmpty
    @NotNull
    @Null
    @Past
    @PastOrPresent
    @Pattern
    @Positive
    @PositiveOrZero
    @Size

    日期格式化注解

    @JsonFormat:后台传到前台的json格式的日期
    @DateTimeFormat:前台传到后台的日期格式

    1. 在controller层加校验注解

    注解:@Validated

    @PostMapping("/user")
        @ApiOperation(value = "添加用户", httpMethod = "POST", notes = "添加用户详情")
        public ResponseResult addUser(@Validated User user) {
            log.info("user===>"+user);
            return new ResponseResult().setCode(200).setHasError(false).setMessage(null).setData(null);
        }
    

统一日志管理

​ Spring Boot默认使用slf4j日志门面+LogBack日志实现,也可以切换为其它日志框架。

​ 常见的日志框架有:JUL , JCL , Jboss-logging , logback , log4j , log4j2 , slf4j等等,他们的分类如下:

日志门面(日志的抽象层)日志实现
JCL,SLF4J,Jboss-loggingLog4j , JUL(java.util.logging ) , Log4j2, Logback

JCL是Apache公司开发的一个框架,Jakarta小组开发的,Spring Framework在使用,但是2014年已经停止更新了。SLF4J , Log4j , Logback是同一个人写的,这个人想优化Log4j,但是认为重新写比较麻烦,于是写了SLF4J这个抽象层日志框架,又写了Logback这个实现类。Log4j2也是Apache公司的,好多框架都没适配。Hibernate底层使用Jboss-logging实现。

在控制台打印日志

方式一:使用lombak日志注解

@Slf4j // 统一日志注解

方式二:

private static final Logger log = LoggerFactory.getLogger(UserController.class);

如何将日志信息存储到文件

# 日志文件路径
# logging.path=d:/workspace/springboot/mylog

# 日志文件名(默认名springboot.log)
# logging.file=mylog.log

​ 如果两者都配置了:logging.file=mylog.log、logging.path=D:/data/mylog,此时并不会在d盘下生成日志文件,只会在项目的根目录下创建一个mylog.log的文件。

其原因是,没有logback-spring.xml配置文件,系统只认识logging.file,不认识logging.path。

logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

	<!--定义日志保存的路径-->
	<!--1.更改默认的logback.xml为logback-spring.xml
		SpringBoot当看到logback-spring.xml文件存在的时候,才会启动日志的环境切换
		logback.xml文件没法做到
		2. 在需要切换的环境上增加springProfile标签
	-->
	<springProfile name="dev">
		<property name="LOG_HOME" value="d:/logs/dev/" />
	</springProfile>
	<!--线上-->
	<springProfile name="prd">
		<property name="LOG_HOME" value="d:/logs/prd/" />
	</springProfile>
	<!--定义一个控制台输出器,名为console-->
	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
		<!--按pattern指定的格式输出日志,编码为UTF-8-->
		<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
			<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread]  %logger{30} - %msg%n</pattern>
			<charset>UTF-8</charset>
		</encoder>
	</appender>
	<!--定义一个日滚动(每天生成一份)的日志文件-->
	<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
		<!--按pattern指定的格式输出日志,编码为UTF-8-->
		<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
			<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread]  %logger{30} - %msg%n</pattern>
			<charset>UTF-8</charset>
		</encoder>
		<!-- 定义保存的文件名 -->
		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
			<!--%d{yyyy-MM-dd}代表每天生成一个新的日志-->
			<fileNamePattern>${LOG_HOME}/mysprintboot_%d{yyyy-MM-dd}.log</fileNamePattern>
			<!--日志最多保存90天,也就是90份-->
			<maxHistory>90</maxHistory>
		</rollingPolicy>
		<!-- 在日滚动文件中,强制只保存错误级别以上信息 -->
		<filter class="ch.qos.logback.classic.filter.LevelFilter">
			<level>INFO</level>
			<onMatch>ACCEPT</onMatch>
			<onMismatch>DENY</onMismatch>
		</filter>
	</appender>
	<!-- 定义日志全局最低输出级别是INFO,同时向控制台和日滚动文件输出 -->
	<root level="INFO">
		<appender-ref ref="console" />
		<appender-ref ref="file" />
	</root>
</configuration>

如何设置日志级别

日志级别总共有TRACE < DEBUG < INFO < WARN < ERROR < FATAL ,且级别是逐渐提供,如果日志级别设置为INFO,则意味TRACE和DEBUG级别的日志都看不到。Spring Boot默认级别就是INFO。

logging.level.root=warn

如何设置日志格式

logging.pattern.console=%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %logger- %msg%n 
logging.pattern.file=%d{yyyy/MM/dd-HH:mm} [%thread] %-5level %logger- %msg%n

日志格式如下:

占位符描述
%d{yyyy-MM-dd HH:mm:ss.SSS}日期
%5p日志级别,5位字符长度显示,如果内容占不满5位则内容右对齐并在左侧补空格
%-5p5位字符长度显示日志级别,如果内容占不满5位则内容左对齐并在右侧补空格 -代表左对齐
%logger日志所在包和类
%M日志所在方法名
%L日志所在代码行
%m日志正文
%n换行

AOP实现日志

  1. 项目中为什么要使用日志功能。

    记录用户的一系列操作,存储到数据库中。

  2. 日志功能的实现方式

    1. aop方式实现

    2. 拦截器实现

    3. 过滤器实现

  3. AOP日志:

    1. 改pom.xml

      <!-- Spring Boot Aop依赖 -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-aop</artifactId>
      </dependency>
      
    2. 创建一个Aspect通知类

      写一个日志注解(非必需)

      @Target({TYPE, METHOD})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      @Inherited
      public @interface LoginLog {
          String value();
      }
      
      

      Aspect通知类

      @Aspect // 切面 通知+切入点
      @Component
      @Slf4j
      public class LoginAspect {
      
          // 指定切入点
          @Pointcut("@annotation(com.newer.springboot.aop.LoginLog)")
          public void loginPointCat() {
          }
      
          // 保存登录之后的用户信息
          // 后置通知
          @AfterReturning("loginPointCat()")
          public void saveUserLog(JoinPoint joinPoint) {
              // 获得request对象
              ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
              HttpServletRequest request = requestAttributes.getRequest();
              HttpSession session = request.getSession();
      
              // 获取用户
              // User user =  (User) session.getAttribute("user");
      
              // 获取参数
              Object[] args = joinPoint.getArgs();
              log.info("params:"+ Arrays.toString(args));
      
              // 操作的方法:
              MethodSignature signature = (MethodSignature) joinPoint.getSignature();
              Method method = signature.getMethod();
              String value = method.getAnnotation(LoginLog.class).value();
              log.info("method:"+value);
      
              // 操作用户的IP
              String remoteAddr = request.getRemoteAddr();
              log.info("ipAddress:"+remoteAddr);
      
              // 操作时间
      
              // 存数据库
      
          }
      }
      
    3. 在目标方法中使用

      @RequestMapping("/login")
      @LoginLog("login")  // 使用日志注解
      public String login(Model model) {
          model.addAttribute("username", "admin");
          model.addAttribute("password", "123456");
          return "index";
      }
      

拦截器实现日志

​ aop方式可以在任意类上实现日志业务的打印或存储,如果我们只需要controller层对日志处理,可以使用拦截器。步骤如下:

  1. 改pom.xml

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.60</version>
    </dependency>
    
  2. 创建类实现HanlerInterceptor接口

    /**
     * 登录日志拦截器
     */
    @Slf4j
    public class WebInterceptor implements HandlerInterceptor {
    
    
        // 方法执行前拦截
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            // 请求路径
            String url = request.getRequestURI();
    
            // 获取请求参数
            String paramData = JSON.toJSONString(request.getParameterMap(),SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteMapNullValue);
    
            // 请求客户ip
            String clientIp = request.getRemoteAddr();
    
            // 请求方式:get/post/put/delete
            String methodName = request.getMethod();
    
            // 设置请求的开始时间
            request.setAttribute("STARTTIME", System.currentTimeMillis());
    
    
            StringBuffer content = new StringBuffer();
            content.append("url="+url);
            content.append(" ,paramData=").append(paramData);
            content.append( ", clientIp=").append(clientIp);
            content.append(" ,HTTP_METHOD=").append(methodName);
    
            log.info("content:"+content);
    
            return true; // 拦截开关
        }
    
        // 视图渲染前拦截
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    
        }
    
        // 方法执行后拦截
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            // 响应状态
            int status = response.getStatus();
            //当前时间
            long currentTime = System.currentTimeMillis();
            long startTime = Long.valueOf(request.getAttribute("STARTTIME").toString());
            System.out.println("time2:"+(currentTime - startTime)+"ms");
        }
    }
    
  3. 配置拦截器

    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    
        @Bean
        public HandlerInterceptor handlerInterceptor() {
            return new WebInterceptor();
        }
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(handlerInterceptor())
                    // 拦截所有方法
                    .addPathPatterns("/**")
                    // 以下url不拦截
                    .excludePathPatterns("/", "/login", "/error", "/logout", "/static/**", "/error/**");
        }
    }
    

Hu-tool工具包

​ 官网:https://www.hutool.cn/

​ Hutool是一个Java工具包类库,对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种Util工具类。

包含组件

模块介绍
hutool-aopJDK动态代理封装,提供非IOC下的切面支持
hutool-bloomFilter布隆过滤,提供一些Hash算法的布隆过滤
hutool-cache简单缓存实现
hutool-core核心,包括Bean操作、日期、各种Util等
hutool-cron定时任务模块,提供类Crontab表达式的定时任务
hutool-crypto加密解密模块,提供对称、非对称和摘要算法封装
hutool-dbJDBC封装后的数据操作,基于ActiveRecord思想
hutool-dfa基于DFA模型的多关键字查找
hutool-extra扩展模块,对第三方封装(模板引擎、邮件、Servlet、二维码、Emoji、FTP、分词等)
hutool-http基于HttpUrlConnection的Http客户端封装
hutool-log自动识别日志实现的日志门面
hutool-script脚本执行封装,例如Javascript
hutool-setting功能更强大的Setting配置文件和Properties封装
hutool-system系统参数调用封装(JVM信息等)
hutool-jsonJSON实现
hutool-captcha图片验证码实现
hutool-poi针对POI中Excel和Word的封装
hutool-socket基于Java的NIO和AIO的Socket封装

可以根据需求对每个模块单独引入,也可以通过引入hutool-all方式引入所有模块。

Maven安装

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.3.9</version>
</dependency>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值