Spring Boot 搭建笔记

背景

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

一、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
  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:
  datasource:
    url: jdbc:mysql://mysql57.rdsmpxa0o9ae2yo.rds.bj.baidubce.com:3306/jyjin?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=yes
    username: yqcloud_user
    password: Hand1234
    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: zbook
      output:
        ansi:
          enabled: always
      profiles:
        active: dev
      # jsp引擎配置
      thymeleaf:
        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 构造函数、成员方法必须写在枚举属性后

在这里插入图片描述

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;
    }

在这里插入图片描述

在这里插入图片描述

分析

  • password、age均为空,if进不去
  • 第二个条件"" == value.toString()始终不成立,尝试了很多写法都不行
  • password是空,打印出来是个地址
  • 断点打出来是个数组对象,是空字符串
    在这里插入图片描述

试了很多方法之后

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

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

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

三、后续待研究

  • jar包开发发布
  • mvn包发布
  • 注解封装
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值