欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring Boot学习笔记

程序员文章站 2022-07-10 18:10:40
...

背景

  • 快速适应项目现有后台框架
  • 亲身体验项目痛点并注入改进设计思想
  • 重拾Java相关知识点

一、Spring Boot项目搭建

工程目录结构
Spring Boot学习笔记

1.入口文件

package com.zb.zbook;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.zb.zbook.test.Dog;

@MapperScan(basePackages = "com.zb.zbook.mapper")
@SpringBootApplication
public class ZbookApplication {

    public static void main(String[] args) {

        SpringApplication.run(ZbookApplication.class, args); // Important!Spring启动项
        System.out.println("Java, long time no see !");
        
    }

}

2.接口路由Controller

知识点
类注解

  • @RestController注解 - 标记路由项
  • @RequestMapping注解 - 添加前置路由配置,类似prefix

方法注解

  • @RequestMapping(value="/a/b/c") 接口地址定义(实际接口还有前置的RequestMapping)
  • @PostMapping http不同类型的Post
  • @GetMapping http不同类型的Post

http参数接收、http响应

  • HttpServletRequest 基于和MVC、Struct框架一样的servlet请求类,获取http请求信息
  • HttpServletResponse http响应信息
@RequestMapping(value = "/add")
    @PostMapping
    public Result addUser(HttpServletRequest request, HttpServletResponse response) throws SQLException, IOException {

        System.out.println("URL == " + request.getRequestURL());
        System.out.println("URI == " + request.getRequestURI());
		
		// 实现一个参数校验简易拦截器
        if ("" != ParameterValidate.validate(request)) {
            return new Result(ResultCode.PARAM_IS_BLANK, ParameterValidate.validate(request));
        }

        try {
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            String _age = request.getParameter("age");
            Util.print(username, password, _age);
            int age = parseInt(_age);

            User user = new User(username, age, password);
            user.toString();
			// 简单实现一个前后端接口规范
            return new Result(ResultCode.SUCCESS, userService.addUser(username, age, password));

        } catch (NumberFormatException e) {
            System.out.println("EXP ==== ");
            List<String> list = new ArrayList<String>(10);
            list.add("URL == " + request.getRequestURL());
            list.add("URI == " + request.getRequestURI());

			// 简单实现一个前后端接口规范
            return new Result(ResultCode.SUCCESS, list);
        }


    }

3.Service

设计接口

个人认为这里是很重要的一步,架构师设计好接口。然后各业务可以在Interface上拓展实现具体的业务,需要调整的时候可以在Interface层做全局调整

package com.zb.zbook.service;

import com.zb.zbook.domain.User;

public interface UserService {
    int addUser(String username, int age, String password);
}

4.ServiceImpl

接口实现层

package com.zb.zbook.serviceImpl;

import com.zb.zbook.mapper.UserMapper;
import com.zb.zbook.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zb.zbook.domain.User;
import java.util.List;
import com.zb.zbook.mapper.UserMapper;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override // 重要,接口实现必须需要Override注解
    public int addUser(String username, int age, String password ){
        return  userMapper.addUser(username, age, password);
    }

}

4.userMapper

MyBatis接口设计

package com.zb.zbook.mapper;

import org.springframework.stereotype.Repository;
import com.zb.zbook.domain.User;

import java.util.List;

@Repository
public interface UserMapper {
    
    int addUser(String username, int age, String password);

}

5.Mybatis XML sql编写

SQL操作、Java实体类持久化数据的关联

<?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.zb.zbook.mapper.UserMapper">

    <resultMap id="userList" type="com.zb.zbook.domain.User">
        <id column="id" property="id" jdbcType="INTEGER"/>
        <result column="username" property="username" jdbcType="VARCHAR"/>
        <result column="age" property="age" jdbcType="INTEGER"/>
        <result column="password" property="password" jdbcType="VARCHAR"/>
    </resultMap>

    <select id="getUserById" parameterType="int" resultMap="userList">
        SELECT * FROM user WHERE id = #{id}
    </select>


    <insert id="addUser" parameterType="com.zb.zbook.domain.User" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO user(username, password, age) VALUES (#{username}, #{password}, #{age});
    </insert>

</mapper>

途中遇到的报错

5.1 xml文件头不能有空行

  • 关键信息鉴定不允许有匹配 "[xX][mM][lL]" 的处理指令目标。

否则报错如下

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userController': Unsatisfied dependency expressed through field 'userService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userServiceImpl': Unsatisfied dependency expressed through field 'userMapper'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userMapper' defined in file [/Users/jyjin/workspace/yanqian/zbook/target/classes/com/zb/zbook/mapper/UserMapper.class]: Unsatisfied dependency expressed through bean property 'sqlSessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.ibatis.session.SqlSessionFactory]: Factory method 'sqlSessionFactory' threw exception; nested exception is org.springframework.core.NestedIOException: Failed to parse mapping resource: 'file [/Users/jyjin/workspace/yanqian/zbook/target/classes/mapperXml/UserMapper.xml]'; nested exception is org.apache.ibatis.builder.BuilderException: Error creating document instance.  Cause: org.xml.sax.SAXParseException; lineNumber: 2; columnNumber: 6; 不允许有匹配 "[xX][mM][lL]" 的处理指令目标。
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1420) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at com.zb.zbook.ZbookApplication.main(ZbookApplication.java:14) ~[classes/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
	

5.2 xml文件必须有文件头

文件头必须声明如下

<?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" >

否则报错如下

关键鉴别信息:lineNumber: 3; columnNumber: 52; 文档根元素 "mapper" 必须匹配 DOCTYPE 根 "null"。

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userController': Unsatisfied dependency expressed through field 'userService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userServiceImpl': Unsatisfied dependency expressed through field 'userMapper'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userMapper' defined in file [/Users/jyjin/workspace/yanqian/zbook/target/classes/com/zb/zbook/mapper/UserMapper.class]: Unsatisfied dependency expressed through bean property 'sqlSessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.ibatis.session.SqlSessionFactory]: Factory method 'sqlSessionFactory' threw exception; nested exception is org.springframework.core.NestedIOException: Failed to parse mapping resource: 'file [/Users/jyjin/workspace/yanqian/zbook/target/classes/mapperXml/UserMapper.xml]'; nested exception is org.apache.ibatis.builder.BuilderException: Error creating document instance.  Cause: org.xml.sax.SAXParseException; lineNumber: 3; columnNumber: 52; 文档根元素 "mapper" 必须匹配 DOCTYPE 根 "null"。
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1420) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at com.zb.zbook.ZbookApplication.main(ZbookApplication.java:14) ~[classes/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.3.2.RELEASE.jar:2.3.2.RELEASE]

5.3 parameterType需要全路径,或者别称

错误:

<insert id="addUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO user(username, password, age) VALUES (#{username}, #{password}, #{age});
    </insert>

正确:

  • parameterType="com.zb.zbook.domain.User"
<insert id="addUser" parameterType="com.zb.zbook.domain.User" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO user(username, password, age) VALUES (#{username}, #{password}, #{age});
    </insert>

直接设置User报错如下
关键鉴定信息:Cause: java.lang.ClassNotFoundException: Cannot find class: User

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userController': Unsatisfied dependency expressed through field 'userService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userServiceImpl': Unsatisfied dependency expressed through field 'userMapper'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userMapper' defined in file [/Users/jyjin/workspace/yanqian/zbook/target/classes/com/zb/zbook/mapper/UserMapper.class]: Unsatisfied dependency expressed through bean property 'sqlSessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [org/mybatis/spring/boot/autoconfigure/MybatisAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.ibatis.session.SqlSessionFactory]: Factory method 'sqlSessionFactory' threw exception; nested exception is org.springframework.core.NestedIOException: Failed to parse mapping resource: 'file [/Users/jyjin/workspace/yanqian/zbook/target/classes/mapperXml/UserMapper.xml]'; nested exception is org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. The XML location is 'file [/Users/jyjin/workspace/yanqian/zbook/target/classes/mapperXml/UserMapper.xml]'. Cause: org.apache.ibatis.builder.BuilderException: Error resolving class. Cause: org.apache.ibatis.type.TypeException: Could not resolve type alias 'User'.  Cause: java.lang.ClassNotFoundException: Cannot find class: User
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:643) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1420) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.3.2.RELEASE.jar:2.3.2.RELEASE]
	at com.zb.zbook.ZbookApplication.main(ZbookApplication.java:14) ~[classes/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.3.2.RELEASE.jar:2.3.2.RELEASE]

6.相关配置

application.yml

# tomcat配置
server:
  tomcat:
    uri-encoding: UTF-8
    max-connections: 500
    min-spare-threads: 25
    max-threads: 300
    accept-count: 200
  port: 9000 # 服务端口


# mybatis配置
mybatis:
  type-aliases-package: com.zb.mapper // map对应的路径
  mapper-locations: classpath:mapperXml/*.xml

pagehelper:
  helper-dialect: mysql
  reasonable: true
  support-methods-arguments: true
  params: count=countSql
logging:
  level:
    com.zb.mapper: debug

---

# Spring开发配置
spring:
  profiles: dev
  # 数据库配置
  datasource:
    url: jdbc:mysql://CONNECTION_ADDRESSS/DB_NAME?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=yes
    username: USERNAME_DB
    password: PASSWORD_DB
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    filters: stat
    maxActive: 20
    initialSize: 1
    maxWait: 60000
    minIdle: 1
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: select 'x'
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    maxOpenPreparedStatements: 20

  # 框架配置
  application:
    name: myspringboot
    output:
      ansi:
        enabled: always
    profiles:
      active: dev
    # jsp引擎配置
    thymeleaf: # jsp模板引擎包,这个用jsp必须用到
      encoding: UTF-8
      prefix: classpath:/templates/

二、简要Spring开发后的设计

1.前后端接口规范设计

知识点

  • @Data注解 - 省去get、set方法、各态构造函数
  • @AllArgsConstructor - 参数全部排列组合构造函数
  • @NoArgsConstructor - 空参数构造函数

数据格式

{
	code: 1001,
	message: "操作成功",
	data: {...} or [...] boolean or String or Number
}

Result代码

package com.zb.zbook.util;

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

import java.io.Serializable;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result implements Serializable {
    private Integer code;
    private String message;
    private Object data;

    public Result(ResultCode resultCode, Object data){
        this.code = resultCode.code();
        this.message = resultCode.message();
        this.data = data;
    }
}

2. 系统错误码

错误码枚举

ResultCode代码

package com.zb.zbook.util;

public enum ResultCode {

    /*成功*/
    SUCCESS(1,"成功"),

    /*参数错误 1001-1999*/
    PARAM_IS_INVALID(1001,"参数无效"),
    PARAM_IS_BLANK(1002,"参数为空"),

    /*用户错误 2001-2999*/
    USER_NOT_LOGIN(2001,"用户未登录");

    private Integer code;
    private String message;

    ResultCode(Integer code, String message) {
        this.code = code;
        this.message = message;
    }

    public Integer code() {
        return code;
    }

    public String message() {
        return message;
    }
}

2.1 构造函数、成员方法必须写在枚举属性后

Spring Boot学习笔记

3. 简单的参数校验拦截

  • 拦截器入参:HttpServletRequest类,因为可以获取所有参数
  • 拦截器返回:错误信息或空字符

拦截器:

package com.zb.zbook.util;

import org.thymeleaf.util.ObjectUtils;
import org.thymeleaf.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

public class ParameterValidate {

    public static String validate(HttpServletRequest request) {
        Map<String, String[]> paramMap = request.getParameterMap();
        Iterator<String> it = paramMap.keySet().iterator();
        String s = "";

        for (String key : paramMap.keySet()) {
            String[] value = paramMap.get(key);
            System.out.println("key ----> " + key.toString());
            System.out.println("value ----> " + value[0].toString());
            if (null == value || "" == value[0]) {
                s = s + key + "、";
            }
        }

        if(s.length()>0){
            s = "参数" + s.substring(0, s.length() - 1) + "不能为空!";
        }
        System.out.println("s ----> " + s);
        return s;
    }
}

使用:

只为演示暂不考虑现有校验注解,纯粹学习

Controller开头处加上以下代码

if ("" != ParameterValidate.validate(request)) {
            return new Result(ResultCode.PARAM_IS_BLANK, ParameterValidate.validate(request));
        }

3.1 Java泛型类型指定不可省

解决时间最久的一个报错,错误代码

  public static String validate(HttpServletRequest request) {
        Map paramMap = request.getParameterMap();
        Iterator it = paramMap.keySet().iterator();
        String s = "";

        for (Object key : paramMap.keySet()) {
            Object value = paramMap.get(key);
            System.out.println("key ----> " + key.toString());
            System.out.println("value ----> " + value.toString());
            if (null == value || "" == value.toString()) { // 第二个判断没法写,怎么都进不去
                s = s + key + "、";
            }
        }

        if(s.length()>0){
            s = "参数" + s.substring(0, s.length() - 1) + "不能为空!";
        }
        System.out.println("s ----> " + s);
        return s;
    }

Spring Boot学习笔记

Spring Boot学习笔记

分析

  • password、age均为空,if进不去
  • 第二个条件"" == value.toString()始终不成立,尝试了很多写法都不行
  • password是空,打印出来是个地址
  • 断点打出来是个数组对象,是空字符串
    Spring Boot学习笔记

试了很多方法之后

进入getParameterMap方法查看了类型确实string数组,转类型解决问题

public Map<String, String[]> getParameterMap();

Spring Boot学习笔记

Spring Boot学习笔记
Spring Boot学习笔记

三、后续待研究

  • jar包开发发布
  • mvn包发布
  • 注解封装