Pending:
nexus local repository, upload and download jar package
jwt resolve
Design Spring Security and permissions system based JWT
https://www.codesheep.cn/2019/03/14/security-jwt-hibernate/
Table definitions, database tables migration, update
https://flywaydb.org/getstarted/firststeps/maven#creating-the-first-migration
The only field, unique_together
unique_together = (('type_name', 'capability_name'))
Inquire:
精确(UserCopy1Example.andDescriptionEqualTo) done
模糊(UserCopy1Example.andDescriptionLike) done
Conditions sorting (UserCopy1Example.orderByClause) done
Enumeration: done
Java enumeration (enum) Detailed seven common usage
https://blog.csdn.net/qq_27093465/article/details/52180865
MyBaits enumeration types - the type using a database field in the string of numbers or the like where a non-enumerated type
https://blog.csdn.net/houyefeng/article/details/45886613
MyBatis database field mapping Java enum
https://blog.csdn.net/chidi5109/article/details/100599083
Mybatis enumeration mapping database stored int conversion
https://blog.csdn.net/zangdaiyang1991/article/details/86518088
SpringBoot integration Mybatis automatically converted enumeration type
https://blog.csdn.net/qq_26440803/article/details/83451221
General enumeration SpringBoot and MybatisPlus3.X integration of (XII)
https://www.cnblogs.com/dalianpai/p/11771269.html
Route management, the request processing
@Temporal(TemporalType.TIMESTAMP)
@Column
@JsonProperty("create_time")
@JsonDeserialize(using = EventCreateTimeDeserializer.class)
@JsonSerialize(using = EventCreateTimeSerializer.class)
@TableField(typeHandler = EventCreateTimeHandler.class)
@Future(message = "时间在当前时间之后才可以通过")
private java.util.Date createTime;
post http://localhost:9000/log/
EventCreateTimeDeserializer.deserialize
Entity:
setCreateTime
setLevel
@Future(message = "时间在当前时间之后才可以通过")
private java.util.Date createTime;
getEffectiveTemporalValidationTolerance
FutureValidatorForDate.getInstant
AbstractFutureInstantBasedValidator.is_valid
EventLevelValidator
long id = this.getBaseMapper().insert(event);
getCreateTime
[2020-02-13 14:57:42.646] [DEBUG] <http-nio-9000-exec-1> org.apache.ibatis.logging.jdbc.BaseJdbcLogger:143 ==> Preparing: INSERT INTO tianshu_log_event ( create_time, content, level, owner, description ) VALUES ( ?, ?, ?, ?, ? )
EventCreateTimeHandler.setParameter
EventLevelHandler.setParameter
return this.getById(event.getId());
setCreateTime、setLevel
EventCreateTimeSerializer.serialize
controller(RestController),model(Entity、Domain),view
Ma Ying-jeou: Chapter 6 Web MVC REST application
https://coding.imooc.com/class/chapter/252.html#Anchor
Data validation:
Quick start Spring Boot parameters check
Spring Boot parameter check (the difference @Validated and @Valid, custom check, check how nested)
https://blog.csdn.net/Howinfun/article/details/90287047
packet checksum validation-api nested property (a collection of objects) wording
https://blog.csdn.net/huangdi1309/article/details/89673875
Brother Mark: Section XII verification ( courseware ) [Q ]
Serialization and de-serialization
Ma Ying-jeou: Chapter 6 Web MVC REST application
https://coding.imooc.com/class/chapter/252.html#Anchor/
https://spring.io/guides/gs/accessing-data-mysql/
CRUD
Associated foreign key (one to one, many-to-many foreign key delete behavior: CASCADE, PROTECT, SET_NULL, SET_DEFAULT, SET):
分页(userCopy1Repository.getPageList(page, pageSize),
PagingAndSortingRepository)
https://github.com/pagehelper/Mybatis-PageHelper
Bulk operations, delete (SimpleJpaRepository)
Persistence API section VIII of the Java ( courseware ) (Note: only functions to achieve here, since jpa do a lot of packaging, then consider the performance or use mybatis)
Atomic operation?
.setCommit (false)
.setCommit(true)
https://segmentfault.com/n/1330000009887617
Custom response
https://blog.csdn.net/shenszy/article/details/85676415
httpClient
rest Template
createTime--> create_time
asynchronous
http://www.spring4all.com/article/540
Not implemented, the problems encountered:
spring boot2 EnableAysnc If the controller requires proxying (e.g. due to @Transactional), please us
Bale
1 jar command line to run
java -jar target\msgcenter-0.0.1-SNAPSHOT.jar
2 war tmocat running in the container, is provided as follows:
Deployment
docker
http://www.spring4all.com/article/557
application.yml
# Logger Config
logging:
level:
root: info # 全局
ik.starriver.msgcenter: debug # 包级别
pattern:
console: '%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){magenta} %clr([%5p]) %highlight(%C:%L) %m %n'
file: '%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){magenta} %clr([%5p]) %highlight(%C:%L) %m %n'
# 默认日志文件名
file: test.log
# 默认日志路径
path: ./log
# logback.xml路径,默认为classpath:logback.xml
# config: ./logback.xml
#app
server:
port: 9000
#spring
spring:
output:
ansi:
enabled: ALWAYS
devtools:
restart:
enabled: false
# mysql DATABASE CONFIG
datasource:
# 使用druid数据源
# type: com.alibaba.druid.pool.DruidDataSource
type: org.apache.commons.dbcp2.BasicDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://10.1.252.23:3306/springtest?serverTimezone=UTC
username: root
password: 123456
filters: stat
maxActive: 20
initialSize: 1
maxWait: 60000
minIdle: 1
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: select 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxOpenPreparedStatements: 20
# dbcp2
dbcp2:
url: jdbc:mysql://10.1.252.23:3306/springtest?serverTimezone=UTC
username: root
password: '%tBqnWF1y3ku'
maxTotal: 20
maxIdle: 5
driverClassName: com.mysql.cj.jdbc.Driver
jpa:
open-in-view: false
database: MYSQL
databasePlatform: org.hibernate.dialect.MySQL5InnoDBDialect
generateDdl: true
hibernate:
ddlAuto: update
#mybatis
mybatis-plus:
mapper-locations: classpath:/mapper*/*Mapper.xml
#实体扫描,多个package用逗号或者分号分隔
typeAliasesPackage: ik.starriver.msgcenter.entity
# typeEnumsPackage: com.baomidou.springboot.entity.enums
global-config:
# 数据库相关配置
db-config:
# table-prefix: tianshu_log_
#主键类型 AUTO:"数据库ID自增", INPUT:"用户输入ID",ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
# id-type: ASSIGN_ID
#字段策略 IGNORED:"忽略判断",NOT_NULL:"非 NULL 判断"),NOT_EMPTY:"非空判断"
field-strategy: not_empty
#驼峰下划线转换
column-underline: true
#数据库大写下划线转换
#capital-mode: true
#逻辑删除配置
logic-delete-value: 0
logic-not-delete-value: 1
db-type: mysql
#刷新mapper 调试神器
refresh: true
# 原生配置
configuration:
map-underscore-to-camel-case: true
cache-enabled: false
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.M1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>ik.starriver</groupId>
<artifactId>msgcenter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>msgcenter</name>
<description>msgcenter project for starriver</description>
<properties>
<java.version>1.8</java.version>
<mybatis-plus-boot-starter.version>3.3.1</mybatis-plus-boot-starter.version>
<docker.image.prefix>starriver</docker.image.prefix>
<!-- <dockerfile.maven.version>1.3.4</dockerfile.maven.version>-->
</properties>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- mybatis-plus start -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus-boot-starter.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- mybatis-plus end -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
</project>
Bale:
D:\shen\java\webdevelop\spring\msgcenter>java -jar target\msgcenter-0.0.1-SNAPSHOT.jar
Upload jar package to the deployment environment:
Dockerfile
Command line: docker run -e "JAVA_OPTS = -Xmx52m" app-image
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD msgcenter-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 9000
ENV JAVA_OPTS="-Xmx52m"
ENV DATABASE_URL="--spring.datasource.url=jdbc:mysql://127.0.0.1:3306/springtest"
ENV DATABASE_USERNAME="--spring.datasource.username=root"
ENV DATABASE_PASSWORD="--spring.datasource.password=123456"
ENTRYPOINT exec java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar $DATABASE_URL $DATABASE_USERNAME $DATABASE_PASSWORD
# 启动命令模式为:exec java $JAVA_OPTS(jvm的参数) xxx-app.jar $SPRING_OPTIONS(spring的参数)
Docker-compose.yml
[root@shen msgcenter]# cat docker-compose.yml
version: "3"
services:
web:
build: .
image: msgcenter
ports: ['9000:9000']
#command: ["/bin/bash", "start.sh"]
# command: ["uwsgi", "--ini", "uwsgi.ini"]
#environment:
# - ALLOW_HOST=*
#- DB_HOST=10.1.252.23
#- DB_PORT=3306
#- DB_USER=root
#- DB_PASSWORD=%tBqnWF1y3ku
#- DB_NAME=tianshu_data_dict
# volumes: ['.:/code']
docker-deploy.py
[root@shen msgcenter]# cat docker-deploy.py
import re
import os
DOCKER_COMPOSE_IMAGE_NAME = "msgcenter"
def stop_container():
p = os.popen('docker ps')
output = p.read()
# print(output)
pattern = re.compile(".*{}".format(DOCKER_COMPOSE_IMAGE_NAME))
try:
container_id = re.search(pattern, output).group().split()[0]
if not container_id:
return
p = os.popen('docker stop {}'.format(container_id))
output = p.read()
print("docker stop {}".format(output))
except (AttributeError, ) as e:
print("stop_container: {}".format(str(e)))
def docker_compose():
p = os.popen('docker-compose up -d --build')
output = p.read()
print(output)
def docker_ps():
print("------------------")
docker_ps_cmd = 'docker ps|grep {}'.format(DOCKER_COMPOSE_IMAGE_NAME)
print(docker_ps_cmd)
p = os.popen(docker_ps_cmd)
output = p.read()
print(output)
if __name__ == "__main__":
stop_container()
docker_compose()
docker_ps()
Generated image, and start docker
[root@shen msgcenter]# python3 docker-deploy.py
PS:
cli dynamic way incoming global variables:
D:\shen\java\webdevelop\spring\log>java -jar target\log-0.0.1-SNAPSHOT.jar
--spring.datasource.url=
jdbc:mysql://10.1.252.23:3306/springisp?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf8
--spring.profiles.active=pro
--spring.datasource.username=root
--spring.datasource.password=123456
Official website deployment documentation
https://docs.spring.io/spring-boot/docs/current/reference/html/deployment.html#containers-deployment
FROM openjdk:8-jdk-alpine AS builder
WORKDIR target/dependency
ARG APPJAR=target/*.jar
COPY ${APPJAR} app.jar
RUN jar -xf ./app.jar
FROM openjdk:8-jre-alpine
VOLUME /tmp
ARG DEPENDENCY=target/dependency
COPY --from=builder ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=builder ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=builder ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","com.example.MyApplication"]
Database time zone issue
Such misunderstandings and JDBC MySQL, resulting in a time stamp is actually stored in the database, and the service system to take the difference between the value of the 13 or 14 hours, this time with the United States is (= 13) No (= 14) daylight saving when closely related.
solve:
mysql> set global time_zone = '+08:00';
Query OK, 0 rows affected (0.00 sec)
mysql> set time_zone = '+08:00';
Query OK, 0 rows affected (0.00 sec)
https://blog.csdn.net/qq_30553235/article/details/79612824
restdocs
https://www.cnblogs.com/qq350760546/p/8397557.html
https://docs.spring.io/spring-restdocs/docs/2.0.4.RELEASE/reference/html5/#introduction
http://www.spring4all.com/article/3333
http request class structure:
RestTemplate
@Test
public void test() {
final String url = "http://localhost:9000/log/?page=2&pageSize=2&orderBy=level&direction=desc&searchName=content&searchValue=con&nameLike=true";
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Content-Type", MediaType.APPLICATION_JSON_VALUE);
requestHeaders.add("Authorization", "Bearer test");
RestTemplate template = new RestTemplate();
HttpEntity<String> requestEntity = new HttpEntity<String>(null, requestHeaders);
ResponseEntity<String> response = template.exchange(url, HttpMethod.GET, requestEntity, String.class);
String result = response.getBody();
System.err.println(result);
}
MockMvc
@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureRestDocs(uriPort = 9000)
public class RestControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
void testGetEventPage() throws Exception {
HttpHeaders headers = new HttpHeaders();
headers.put("Content-Type", Arrays.asList(MediaType.APPLICATION_JSON_VALUE));
headers.put("Authorization", Arrays.asList("Bearer dXNlcjpzZWNyZXQ="));
this.mockMvc.perform(get("/log/?page=2&pageSize=2&orderBy=level&direction=desc&searchName=content&searchValue=con&nameLike=true").headers(headers))
.andExpect(status().isOk())
.andDo(document("eventPage",
requestHeaders(
headerWithName("Content-Type").description(
"desc Content-Type"),
headerWithName("Authorization").description(
"JWT token: Bearer dXNlcjpzZWNyZXQ=")),
requestParameters(
parameterWithName("page").description("The page to retrieve"),
parameterWithName("pageSize").description("Entries per page"),
parameterWithName("orderBy").description("Entries orderBy"),
parameterWithName("direction").description("Entries orderBy direction"),
parameterWithName("searchName").description("filter by column name"),
parameterWithName("searchValue").description("filter by column name's value"),
parameterWithName("nameLike").description("use name like or not")
)
// responseHeaders(
// headerWithName("X-RateLimit-Reset").description(
// "Time at which the rate limit period will reset"))
));
}