Spring Boot学习笔记
程序员文章站
2022-07-10 18:10:40
...
背景
- 快速适应项目现有后台框架
- 亲身体验项目痛点并注入改进设计思想
- 重拾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 // 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 构造函数、成员方法必须写在枚举属性后
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包发布
- 注解封装
上一篇: Tomcat 图片虚拟路径映射
下一篇: tomcat地址映射