diff --git a/CHANGE_LOG.md b/CHANGE_LOG.md
new file mode 100644
index 0000000..5a503c9
--- /dev/null
+++ b/CHANGE_LOG.md
@@ -0,0 +1,18 @@
+# 更新日志
+
+### 2023-2-10
+1. 初始化项目,采用Srpingboot+H2来实现简单的CRUD,API满足restful规范
+2. 添加UserService单元测试
+3. 封装统一返回参数JsonResult
+
+由于是简单的demo,所以在代码可维护的前提下,没有直接采用maven分模块的形式来分层,而是采用包的形式
+
+启动入口是UserApplication的main方法
+
+### 2023-2-11
+1. 添加CHANGE_LOG.md
+2. 添加TokenService,说明终端用户的访问控制
+3. 添加logback-spring.xml
+4. 添加FriendsController描述如何维护关注和取消关注API等
+5. 在FriendsController添加如何获取附近的朋友API
+6. 添加QUICK_START.md,介绍项目启动及API描述
\ No newline at end of file
diff --git a/QUICK_START.md b/QUICK_START.md
new file mode 100644
index 0000000..d950878
--- /dev/null
+++ b/QUICK_START.md
@@ -0,0 +1,72 @@
+# 快速开始
+
+### 项目启动
+1. 找到UserApplication.java
+2. 运行main
+
+## API介绍
+### UserController
+1. 查询用户API
+
+| URI | GET /api/user/get/{id} |
+| ---- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| 入参名称 | id // user ID |
+| 返回结果 | {
"code":0,
"msg":"",
"data":{"id":"xxx",//user ID
"name":"test",//user name
"dob":"",//date of birth
"address":"",//user address
"description":"",//user description
"createdAt":""//user created date}
} |
+
+2. 新增用户API
+
+| URI | POST /api/user/create |
+| ---- |------------------------------------------------------------------------------------------------------------------|
+| 入参名称 | name // user name
dob // date of birth
address // user address
description // user description |
+| 返回结果 | {
"code":0,
"msg":"",
"data":""
} |
+
+3. 修改用户API
+
+| URI | PUT /api/user/update |
+|------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|
+| 入参名称 | id // user ID
name // user name
dob // date of birth
address // user address
description // user description |
+| 返回结果 | {
"code":0,
"msg":"",
"data":""
} |
+
+4. 删除用户API
+
+| URI | DELETE /api/user/delete |
+|------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|
+| 入参名称 | id // user ID |
+| 返回结果 | {
"code":0,
"msg":"",
"data":""
} |
+
+### FriendsController
+1. 关注API
+
+| URI | POST /api/friends/follow |
+|--------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|
+| 入参名称 | id // user ID
followedUserId // followed user ID |
+| 返回结果 | {
"code":0,
"msg":"",
"data":""
} |
+
+2. 取消关注API
+
+| URI | POST /api/friends/follow/cancel |
+|---------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|
+| 入参名称 | id // user ID
followedUserId // followed user ID |
+| 返回结果 | {
"code":0,
"msg":"",
"data":""
} |
+
+3. 查询关注我的人API
+
+| URI | GET /api/friends/fans |
+|-------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|
+| 入参名称 | id // user ID |
+| 返回结果 | {
"code":0,
"msg":"",
"data":""
} |
+
+4. 查询我关注的人API
+
+| URI | GET /api/friends/followers |
+|-------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|
+| 入参名称 | id // user ID |
+| 返回结果 | {
"code":0,
"msg":"",
"data":""
} |
+
+5. 查询我附近的朋友API
+
+| URI | POST /api/friends/follow/cancel |
+|-------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|
+| 入参名称 | name // user name |
+| 返回结果 | {
"code":0,
"msg":"",
"data":""
} |
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..64143ef
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,85 @@
+
+
+ 4.0.0
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.7.8
+
+
+
+
+ com.wiredcraft
+ test-backend-java
+ 1.0-SNAPSHOT
+
+ test-backend-java
+
+ Demo project
+
+
+ 8
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ com.h2database
+ h2
+ runtime
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+ org.springframework.boot
+ spring-boot-devtools
+ true
+
+
+
+
+ org.projectlombok
+ lombok
+ true
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+ org.projectlombok
+ lombok
+
+
+
+
+
+
+
+
diff --git a/src/main/java/com/wiredcraft/test/user/UserApplication.java b/src/main/java/com/wiredcraft/test/user/UserApplication.java
new file mode 100644
index 0000000..8470074
--- /dev/null
+++ b/src/main/java/com/wiredcraft/test/user/UserApplication.java
@@ -0,0 +1,16 @@
+package com.wiredcraft.test.user;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+/**
+ * Boot Starter
+ */
+@SpringBootApplication
+public class UserApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(UserApplication.class, args);
+ }
+
+}
diff --git a/src/main/java/com/wiredcraft/test/user/auth/TokenService.java b/src/main/java/com/wiredcraft/test/user/auth/TokenService.java
new file mode 100644
index 0000000..7eff88f
--- /dev/null
+++ b/src/main/java/com/wiredcraft/test/user/auth/TokenService.java
@@ -0,0 +1,12 @@
+package com.wiredcraft.test.user.auth;
+
+/**
+ * 用于终端用户访问,一般设计成token+3方扫码形式
+ * 用户通过3方扫码登录后拿到token,再通过角色访问控制来限制资源的访问
+ *
+ * 企业级控制一般需要前端和后端配合来实现控制,设计如下
+ * 资源级别:菜单,页面,按钮
+ * 角色和资源绑定,用户和角色绑定
+ */
+public class TokenService {
+}
diff --git a/src/main/java/com/wiredcraft/test/user/controller/FriendsController.java b/src/main/java/com/wiredcraft/test/user/controller/FriendsController.java
new file mode 100644
index 0000000..4914c8a
--- /dev/null
+++ b/src/main/java/com/wiredcraft/test/user/controller/FriendsController.java
@@ -0,0 +1,111 @@
+package com.wiredcraft.test.user.controller;
+
+import com.wiredcraft.test.user.model.vo.UserVO;
+import com.wiredcraft.test.user.service.FriendsService;
+import com.wiredcraft.test.user.tool.JsonResult;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * Friends API
+ */
+@RestController
+@RequestMapping("/api/friends")
+public class FriendsController {
+
+ @Autowired
+ private FriendsService friendsService;
+
+ /**
+ * 关注
+ *
+ * @param userId 当前用户
+ * @param followedUserId 被关注人
+ * @return
+ */
+ @PostMapping("/follow")
+ public JsonResult follow(@RequestParam int userId, @RequestParam int followedUserId) {
+ friendsService.follow(followedUserId, userId);
+ return JsonResult.success();
+ }
+
+ /**
+ * 取消关注
+ *
+ * @param userId 当前用户
+ * @param followUsereId 被关注的人
+ * @return
+ */
+ @PostMapping("/follow/cancel")
+ public JsonResult cancelFollow(@RequestParam int userId, @RequestParam int followUsereId) {
+ friendsService.cannelFollow(followUsereId, userId);
+ return JsonResult.success();
+ }
+
+ /**
+ * 关注我的人
+ *
+ * @param userId
+ * @return
+ */
+ @GetMapping("/fans")
+ public JsonResult> fans(@RequestParam int userId) {
+ List fans = friendsService.fans(userId);
+ return JsonResult.success(fans);
+ }
+
+ /**
+ * 我关注的人
+ *
+ * @param userId
+ * @return
+ */
+ @GetMapping("/followers")
+ public JsonResult> followers(@RequestParam int userId) {
+ List followers = friendsService.fans(userId);
+ return JsonResult.success(followers);
+ }
+
+ /**
+ * 关注我的数量
+ *
+ * @param userId
+ * @return
+ */
+ @GetMapping("/fans/count")
+ public JsonResult countFans(@RequestParam int userId) {
+ return JsonResult.success();
+ }
+
+ /**
+ * 我关注的数量
+ *
+ * @param userId
+ * @return
+ */
+ @GetMapping("/followers/count")
+ public JsonResult countFollowers(@RequestParam int userId) {
+ return JsonResult.success();
+ }
+
+ /**
+ * 获取附近的朋友
+ *
+ * @param name 用户名
+ * @return
+ */
+ @GetMapping("/nearby")
+ public JsonResult> nearbyFriends(@RequestParam String name) {
+
+ // 1 根据name查询坐标,查用户表
+
+ // 2 查询我的朋友的id,查关系表
+
+ // 3 半径内符合条件的朋友,查用户表,条件是坐标范围和朋友ID集合
+
+ return JsonResult.success();
+ }
+
+}
diff --git a/src/main/java/com/wiredcraft/test/user/controller/UserController.java b/src/main/java/com/wiredcraft/test/user/controller/UserController.java
new file mode 100644
index 0000000..b1e0410
--- /dev/null
+++ b/src/main/java/com/wiredcraft/test/user/controller/UserController.java
@@ -0,0 +1,87 @@
+package com.wiredcraft.test.user.controller;
+
+import com.wiredcraft.test.user.model.req.UserReq;
+import com.wiredcraft.test.user.model.vo.UserVO;
+import com.wiredcraft.test.user.service.UserService;
+import com.wiredcraft.test.user.tool.JsonResult;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * User API
+ * 该类一般用于暴露给前端或者23方,2方目前主流调用方式为RPC
+ * 命名方式具体看规范,有一些用Controller,有一些用Api
+ * 暴露的uri也是具体看规范,目前有两种方式
+ * 1 根据 GET POST PUT DELETE 来区分请求,例如uri:/api/user
+ * 2 在一些企业级实战中,为了方便维护代码,不需要严格遵守RESTful API,可通过在uri上直接体现一些关键词,增加可读性,
+ * 例如uri:/api/user/get/{id}
+ */
+@RestController
+@RequestMapping("/api/user")
+public class UserController {
+
+ @Autowired
+ private UserService userService;
+
+ /**
+ * List users
+ *
+ * @return users
+ */
+ @GetMapping("/page")
+ public JsonResult> list() {
+ List list = userService.list();
+ return JsonResult.success(list);
+ }
+
+ /**
+ * Get user by user ID
+ *
+ * @param id user ID
+ * @return user info
+ */
+ @GetMapping("/get/{id}")
+ public JsonResult get(@PathVariable int id) {
+ UserVO userVO = userService.get(id);
+ return JsonResult.success(userVO);
+ }
+
+ /**
+ * Create user
+ *
+ * @param userReq user form
+ * @return user ID
+ */
+ @PostMapping("/create")
+ public JsonResult create(@RequestBody UserReq userReq) {
+ userService.create(userReq);
+ return JsonResult.success();
+ }
+
+ /**
+ * Update user
+ *
+ * @param userReq user form
+ * @return user ID
+ */
+ @PutMapping("/update")
+ public JsonResult update(@RequestBody UserReq userReq) {
+ userService.update(userReq);
+ return JsonResult.success();
+ }
+
+ /**
+ * Delete by user ID
+ *
+ * @param id User ID
+ * @return
+ */
+ @DeleteMapping("/delete/{id}")
+ public JsonResult delete(@PathVariable int id) {
+ userService.delete(id);
+ return JsonResult.success();
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/wiredcraft/test/user/dao/UserRepository.java b/src/main/java/com/wiredcraft/test/user/dao/UserRepository.java
new file mode 100644
index 0000000..2309cb5
--- /dev/null
+++ b/src/main/java/com/wiredcraft/test/user/dao/UserRepository.java
@@ -0,0 +1,7 @@
+package com.wiredcraft.test.user.dao;
+
+import com.wiredcraft.test.user.model.po.UserPO;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface UserRepository extends JpaRepository {
+}
diff --git a/src/main/java/com/wiredcraft/test/user/model/po/UserPO.java b/src/main/java/com/wiredcraft/test/user/model/po/UserPO.java
new file mode 100644
index 0000000..b6e8197
--- /dev/null
+++ b/src/main/java/com/wiredcraft/test/user/model/po/UserPO.java
@@ -0,0 +1,50 @@
+package com.wiredcraft.test.user.model.po;
+
+import lombok.Data;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import java.util.Date;
+
+/**
+ * User PO 持久化
+ */
+@Data
+@Entity
+public class UserPO {
+
+ /**
+ * User ID
+ */
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Integer id;
+
+ /**
+ * User name
+ */
+ private String name;
+
+ /**
+ * Date of birth
+ */
+ private Date dob;
+
+ /**
+ * User address
+ */
+ private String address;
+
+ /**
+ * User description
+ */
+ private String description;
+
+ /**
+ * User create date
+ */
+ private Date createdAt;
+
+}
diff --git a/src/main/java/com/wiredcraft/test/user/model/req/FriendsReq.java b/src/main/java/com/wiredcraft/test/user/model/req/FriendsReq.java
new file mode 100644
index 0000000..fc048fd
--- /dev/null
+++ b/src/main/java/com/wiredcraft/test/user/model/req/FriendsReq.java
@@ -0,0 +1,21 @@
+package com.wiredcraft.test.user.model.req;
+
+import lombok.Data;
+
+/**
+ * 关注和取关
+ */
+@Data
+public class FriendsReq {
+
+ /**
+ * 被关注的User ID
+ */
+ private int followedUserId;
+
+ /**
+ * 关注的User ID
+ */
+ private int followerId;
+
+}
diff --git a/src/main/java/com/wiredcraft/test/user/model/req/UserReq.java b/src/main/java/com/wiredcraft/test/user/model/req/UserReq.java
new file mode 100644
index 0000000..3f4d1bc
--- /dev/null
+++ b/src/main/java/com/wiredcraft/test/user/model/req/UserReq.java
@@ -0,0 +1,42 @@
+package com.wiredcraft.test.user.model.req;
+
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * User API 入参
+ */
+@Data
+public class UserReq {
+
+ /**
+ * User ID
+ */
+ private Integer id;
+
+ /**
+ * User name
+ */
+ private String name;
+
+ /**
+ * Date of birth
+ */
+ private Date dob;
+
+ /**
+ * User address
+ */
+ private String address;
+
+ /**
+ * User description
+ */
+ private String description;
+
+ /**
+ * User create date
+ */
+ private Date createdAt;
+}
diff --git a/src/main/java/com/wiredcraft/test/user/model/vo/UserVO.java b/src/main/java/com/wiredcraft/test/user/model/vo/UserVO.java
new file mode 100644
index 0000000..8ceeaa3
--- /dev/null
+++ b/src/main/java/com/wiredcraft/test/user/model/vo/UserVO.java
@@ -0,0 +1,43 @@
+package com.wiredcraft.test.user.model.vo;
+
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * User VO 出参
+ */
+@Data
+public class UserVO {
+
+ /**
+ * User ID
+ */
+ private Integer id;
+
+ /**
+ * User name
+ */
+ private String name;
+
+ /**
+ * Date of birth
+ */
+ private Date dob;
+
+ /**
+ * User address
+ */
+ private String address;
+
+ /**
+ * User description
+ */
+ private String description;
+
+ /**
+ * User create date
+ */
+ private Date createdAt;
+
+}
diff --git a/src/main/java/com/wiredcraft/test/user/service/FriendsService.java b/src/main/java/com/wiredcraft/test/user/service/FriendsService.java
new file mode 100644
index 0000000..41cf447
--- /dev/null
+++ b/src/main/java/com/wiredcraft/test/user/service/FriendsService.java
@@ -0,0 +1,44 @@
+package com.wiredcraft.test.user.service;
+
+import com.wiredcraft.test.user.model.vo.UserVO;
+import org.apache.catalina.User;
+
+import java.util.List;
+
+/**
+ * 关注和取关
+ */
+public interface FriendsService {
+
+ /**
+ * 关注
+ * @param followedUserId 被关注人
+ * @param followerId 当前用户
+ * @return
+ */
+ boolean follow(int followedUserId, int followerId);
+
+ /**
+ * 取关
+ * @param followedUserId 被关注人
+ * @param followerId 当前用户
+ * @return
+ */
+ boolean cannelFollow(int followedUserId, int followerId);
+
+ /**
+ * 查询哪些人关注了我
+ *
+ * @param userId 当前用户ID
+ * @return
+ */
+ List fans(int userId);
+
+ /**
+ * 我关注了哪些人
+ * @param userId 当前用户
+ * @return
+ */
+ List followers(int userId);
+
+}
diff --git a/src/main/java/com/wiredcraft/test/user/service/UserService.java b/src/main/java/com/wiredcraft/test/user/service/UserService.java
new file mode 100644
index 0000000..c96cd07
--- /dev/null
+++ b/src/main/java/com/wiredcraft/test/user/service/UserService.java
@@ -0,0 +1,60 @@
+package com.wiredcraft.test.user.service;
+
+import com.wiredcraft.test.user.model.req.UserReq;
+import com.wiredcraft.test.user.model.vo.UserVO;
+
+import java.util.List;
+
+/**
+ * User Service
+ */
+public interface UserService {
+
+ /**
+ * List users
+ *
+ * @return set of UserVO
+ */
+ List list();
+
+ /**
+ * Get user by ID
+ *
+ * @param id user ID
+ * @return UserVO
+ */
+ UserVO get(int id);
+
+ /**
+ * Create user
+ *
+ * @param userReq user form
+ * @return
+ */
+ int create(UserReq userReq);
+
+ /**
+ * Update user
+ *
+ * @param userReq user form
+ * @return
+ */
+ int update(UserReq userReq);
+
+ /**
+ * Delete user by ID
+ *
+ * @param id user ID
+ * @return
+ */
+ boolean delete(int id);
+
+ /**
+ * Logic delete by user ID
+ *
+ * @param id user ID
+ * @return
+ */
+ boolean logicDelete(int id);
+
+}
diff --git a/src/main/java/com/wiredcraft/test/user/service/impl/FriendsServiceImpl.java b/src/main/java/com/wiredcraft/test/user/service/impl/FriendsServiceImpl.java
new file mode 100644
index 0000000..9133d2d
--- /dev/null
+++ b/src/main/java/com/wiredcraft/test/user/service/impl/FriendsServiceImpl.java
@@ -0,0 +1,40 @@
+package com.wiredcraft.test.user.service.impl;
+
+import com.wiredcraft.test.user.model.vo.UserVO;
+import com.wiredcraft.test.user.service.FriendsService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class FriendsServiceImpl implements FriendsService {
+
+ @Override
+ public boolean follow(int followedUserId, int followerId) {
+ //TODO: 在关联表中添加一条关联记录
+ return true;
+ }
+
+ @Override
+ public boolean cannelFollow(int followedUserId, int followerId) {
+ // TODO: 在关联表中删除一条关联记录
+ return true;
+ }
+
+ @Override
+ public List fans(int userId) {
+ // TODO:
+ // 1 分页查关联表ID
+ // 2 去用户表查询用户信息
+ return null;
+ }
+
+ @Override
+ public List followers(int userId) {
+ // TODO:
+ // 1 分页查关联表ID
+ // 2 去用户表查询用户信息
+ return null;
+ }
+
+}
diff --git a/src/main/java/com/wiredcraft/test/user/service/impl/UserServiceImpl.java b/src/main/java/com/wiredcraft/test/user/service/impl/UserServiceImpl.java
new file mode 100644
index 0000000..64ade5c
--- /dev/null
+++ b/src/main/java/com/wiredcraft/test/user/service/impl/UserServiceImpl.java
@@ -0,0 +1,74 @@
+package com.wiredcraft.test.user.service.impl;
+
+import com.wiredcraft.test.user.dao.UserRepository;
+import com.wiredcraft.test.user.model.po.UserPO;
+import com.wiredcraft.test.user.model.req.UserReq;
+import com.wiredcraft.test.user.model.vo.UserVO;
+import com.wiredcraft.test.user.service.UserService;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+@Log4j2
+public class UserServiceImpl implements UserService {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Override
+ public List list() {
+ List userPOList = userRepository.findAll();
+ List result = new ArrayList<>();
+ for (UserPO po : userPOList) {
+ UserVO vo = new UserVO();
+ BeanUtils.copyProperties(po, vo);
+ result.add(vo);
+ }
+ return result;
+ }
+
+ @Override
+ public UserVO get(int id) {
+ UserPO po = userRepository.getById(id);
+ if (po == null) {
+ return null;
+ }
+ UserVO vo = new UserVO();
+ BeanUtils.copyProperties(po, vo);
+ return vo;
+ }
+
+ @Override
+ public int create(UserReq userReq) {
+ UserPO userPO = new UserPO();
+ BeanUtils.copyProperties(userReq, userPO);
+ userRepository.save(userPO);
+ return userPO.getId();
+ }
+
+ @Override
+ public int update(UserReq userReq) {
+ UserPO userPO = new UserPO();
+ BeanUtils.copyProperties(userReq, userPO);
+ userRepository.save(userPO);
+ return userPO.getId();
+ }
+
+ @Override
+ public boolean delete(int id) {
+ userRepository.deleteById(id);
+ return true;
+ }
+
+ @Override
+ public boolean logicDelete(int id) {
+ // TODO: 添加逻辑删除字段,比如deleted:0未删除 1已删除
+ return true;
+ }
+
+}
diff --git a/src/main/java/com/wiredcraft/test/user/tool/JsonResult.java b/src/main/java/com/wiredcraft/test/user/tool/JsonResult.java
new file mode 100644
index 0000000..e238a3d
--- /dev/null
+++ b/src/main/java/com/wiredcraft/test/user/tool/JsonResult.java
@@ -0,0 +1,63 @@
+package com.wiredcraft.test.user.tool;
+
+/**
+ * 返回结果统一封装
+ * 也可以方便统一异常处理
+ */
+public final class JsonResult {
+
+ private int code = 0;
+ private String msg;
+ private T data;
+
+ private JsonResult(){
+ this.data = null;
+ }
+
+ private JsonResult(int code, String msg){
+ this.code = code;
+ this.msg = msg;
+ }
+
+ public static JsonResult success(){
+ return new JsonResult<>();
+ }
+
+ public static JsonResult success(T data){
+ JsonResult result = success();
+ result.setdata(data);
+ return result;
+ }
+
+ public static JsonResult failure(int code, String msg){
+ return new JsonResult<>(code, msg);
+ }
+
+ public int getCode(){
+ return code;
+ }
+
+ public JsonResult setCode(int code){
+ this.code = code;
+ return this;
+ }
+
+ public String getMsg(){
+ return msg;
+ }
+
+ public JsonResult setMsg(String msg){
+ this.msg = msg;
+ return this;
+ }
+
+ public T getData(){
+ return data;
+ }
+
+ public JsonResult setdata(T data){
+ this.data = data;
+ return this;
+ }
+
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 0000000..5dee04c
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1,9 @@
+# database
+spring.datasource.url=jdbc:h2:mem:test
+spring.datasource.h2.username=sa
+spring.datasource.h2.password=
+spring.datasource.h2.driver-class-name=org.h2.Driver
+spring.h2.console.path=/h2
+spring.h2.console.enabled=true
+spring.h2.console.settings.web-allow-others=true
+spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
\ No newline at end of file
diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml
new file mode 100644
index 0000000..6f4c48a
--- /dev/null
+++ b/src/main/resources/logback-spring.xml
@@ -0,0 +1,151 @@
+
+
+
+
+
+
+
+ Logback For Boss
+
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger-%msg%n
+ UTF-8
+
+
+
+
+
+
+ ERROR
+ ACCEPT
+ DENY
+
+
+ ${logDir}\%d{yyyyMMdd}\error.log
+ ${maxHistory}
+
+
+ %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger -
+ %msg%n
+
+ UTF-8
+
+ false
+ false
+
+
+
+
+
+ WARN
+ ACCEPT
+ DENY
+
+
+ ${logDir}\%d{yyyyMMdd}\warn.log
+ ${maxHistory}
+
+
+ %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger-%msg%n
+ UTF-8
+
+ false
+ false
+
+
+
+
+
+ INFO
+ ACCEPT
+ DENY
+
+
+ ${logDir}\%d{yyyyMMdd}\info.log
+ ${maxHistory}
+
+
+ %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger-%msg%n
+ UTF-8
+
+ false
+ false
+
+
+
+
+
+ DEBUG
+ ACCEPT
+ DENY
+
+
+ ${logDir}\%d{yyyyMMdd}\debug.log
+ ${maxHistory}
+
+
+ %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger-%msg%n
+ UTF-8
+
+ false
+ false
+
+
+
+
+
+
+ ${logDir}/%d{yyyyMMdd}/boss.%d{yyyy-MM-dd}.log
+
+ 30
+
+
+
+ %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
+
+
+
+ 10MB
+
+
+
+
+
+ true
+
+ 0
+
+ 512
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/java/com/wiredcraft/test/user/UserApplicationTests.java b/src/test/java/com/wiredcraft/test/user/UserApplicationTests.java
new file mode 100644
index 0000000..60d6f4c
--- /dev/null
+++ b/src/test/java/com/wiredcraft/test/user/UserApplicationTests.java
@@ -0,0 +1,13 @@
+package com.wiredcraft.test.user;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class UserApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/src/test/java/com/wiredcraft/test/user/service/UserServiceTest.java b/src/test/java/com/wiredcraft/test/user/service/UserServiceTest.java
new file mode 100644
index 0000000..4708ec2
--- /dev/null
+++ b/src/test/java/com/wiredcraft/test/user/service/UserServiceTest.java
@@ -0,0 +1,69 @@
+package com.wiredcraft.test.user.service;
+
+import com.wiredcraft.test.user.model.po.UserPO;
+import com.wiredcraft.test.user.model.req.UserReq;
+import com.wiredcraft.test.user.model.vo.UserVO;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import java.util.Date;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@SpringBootTest
+
+class UserServiceTest {
+
+ @Autowired
+ private UserService userService;
+
+ @Test
+ void get() {
+ UserReq userReq = buildUser();
+ int id = userService.create(userReq);
+ UserVO userVO = userService.get(id);
+ Assertions.assertNotNull(userVO);
+ Assertions.assertEquals(userVO.getName(), "raistlin");
+ }
+
+ @Test
+ void create() {
+ UserReq userReq = buildUser();
+ int id = userService.create(userReq);
+ Assertions.assertNotNull(id);
+ }
+
+ @Test
+ void update() {
+ UserReq userReq = buildUser();
+ int id = userService.update(userReq);
+ UserVO userVO = userService.get(id);
+ Assertions.assertNotNull(userVO);
+ Assertions.assertEquals(userVO.getName(), "raistlin");
+ }
+
+ @Test
+ void delete() {
+ UserReq userReq = buildUser();
+ int id = userService.create(userReq);
+ UserVO userVO = userService.get(id);
+ userService.delete(id);
+ }
+
+
+ /**
+ * Mock User
+ *
+ * @return
+ */
+ private static UserReq buildUser(){
+ UserReq user = new UserReq();
+ user.setName("raistlin");
+ user.setAddress("address");
+ user.setCreatedAt(new Date());
+ return user;
+ }
+
+}
\ No newline at end of file