Add swagger, more endpoints

This commit is contained in:
BadBUTA 2023-12-21 01:04:32 +08:00
parent 3610fcf44b
commit a0ff867b66
12 changed files with 299 additions and 71 deletions

View File

@ -2,34 +2,39 @@ package com.badbuta.learnspringbootrestfulsqlite;
import org.springframework.web.bind.annotation.RestController;
import com.badbuta.learnspringbootrestfulsqlite.entities.User;
import com.google.gson.Gson;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
/**
* The RESTful API Controller Class
* The URL for this API Controller is '/api'
* The URL for this API Controller is '/api/v1'
*
* NOTE: By adding @CrossOrigin, Swagger preview can work perfectly.
*
*/
@RestController
@RequestMapping(value = "/api")
@CrossOrigin
@RequestMapping(value = "/api/v1")
public class ApiController {
// TODO Load the config from application.properties rather than var
public static String MY_BATIS_CONFIG = "mybatis/config.xml";
@Value("${mybatis.config-location}")
private String myBatisConfigLocation;
/**
* API Endpoint = /api (or /api/)
@ -49,17 +54,13 @@ public class ApiController {
// return "GET /test, param: a=" + valA;
// }
/**
* Get the user(s) by id (using query-string param)
*
* @param id The ID for
* @return User object in JSON
*/
@GetMapping("users")
@GetMapping("fix")
public String getUsers() {
Gson gson = new Gson();
try (Reader in = Resources.getResourceAsReader(MY_BATIS_CONFIG)) {
String myBatisConfigPath = myBatisConfigLocation.split(":")[1];
try (Reader in = Resources.getResourceAsReader(myBatisConfigPath)) {
// Create SQL Session Factory from mybatis config
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
@ -67,39 +68,17 @@ public class ApiController {
SqlSession session = factory.openSession();
// Select users
List<Map<String, Object>> result = session.selectList("mainapp.mybatis.selectUsers");
List<User> result = session
.selectList("com.badbuta.learnspringbootrestfulsqlite.mapper.UserMapper.getUsers");
return gson.toJson(result);
} catch (IOException e) {
// If exception, return the exception object in JSON
// TODO: it is not a good practice and should return formatted error object
System.err.println(e);
return gson.toJson(e);
}
}
@GetMapping("users/{id}")
public String getUsersById(@RequestParam(name = "id", required = false) String id) {
Gson gson = new Gson();
try (Reader in = Resources.getResourceAsReader(MY_BATIS_CONFIG)) {
// Create SQL Session Factory from mybatis config
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
// Create session
SqlSession session = factory.openSession();
// Select users
List<Map<String, Object>> result = session.selectList("mainapp.mybatis.selectUsers");
return gson.toJson(result);
} catch (IOException e) {
// If exception, return the exception object in JSON
// TODO: it is not a good practice and should return formatted error object
return gson.toJson(e);
}
}
}

View File

@ -1,9 +1,11 @@
package com.badbuta.learnspringbootrestfulsqlite;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.badbuta.learnspringbootrestfulsqlite.mapper")
public class MainApplication {
public static void main(String[] args) {

View File

@ -0,0 +1,58 @@
package com.badbuta.learnspringbootrestfulsqlite;
import org.springframework.web.bind.annotation.RestController;
import com.badbuta.learnspringbootrestfulsqlite.entities.User;
import com.badbuta.learnspringbootrestfulsqlite.services.UserService;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
/**
* The RESTful API Controller Class
* The URL for this API Controller is '/api/v1'
*
* NOTE: By adding @CrossOrigin, Swagger preview can work perfectly.
*
*/
@RestController
@CrossOrigin
@RequestMapping(value = "/api/v1")
public class UserController {
@Autowired
private UserService userService;
/**
* Get the user(s) by id (using query-string param)
*
* @param id The ID for
* @return User object in JSON
*/
@GetMapping(value = "users", produces = "application/json")
public List<User> getUsers() {
List<User> users = userService.getUsers();
return users;
}
@GetMapping(value = "users/{id}", produces = "application/json")
public User getUsersById(@PathVariable("id") String userId) {
User user = userService.getUserById(Integer.parseInt(userId));
return user;
}
@PostMapping("users")
public User insertUser(@RequestBody User user) {
// TODO: Return always 1, need to fix
int id = userService.insertUser(user);
user.setId(id);
return user;
}
}

View File

@ -1,7 +1,7 @@
package com.badbuta.learnspringbootrestfulsqlite;
package com.badbuta.learnspringbootrestfulsqlite.entities;
/**
* Domain class - user
* Domain class - User
*/
public class User {

View File

@ -0,0 +1,15 @@
package com.badbuta.learnspringbootrestfulsqlite.mapper;
import java.util.List;
import org.springframework.stereotype.Repository;
import com.badbuta.learnspringbootrestfulsqlite.entities.User;
@Repository
public interface UserMapper {
int insertUser(User user);
User getUserById(int id);
List<User> getUsers();
}

View File

@ -0,0 +1,110 @@
openapi: "3.0.2"
info:
title: Learn Spring Boot RESTful API (SQLite)
version: "1.0"
description: This is an initial draft of API Spec., not generated.
servers:
- url: http://localhost:8888/api/v1
paths:
/users:
get:
summary: Get all users
responses:
"200":
description: OK
content:
application/json:
schema:
type: array
items:
type: object
$ref: "#/components/schemas/User"
post:
summary: Insert a user
requestBody:
description: User object for insertion
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
example: David
password:
type: string
example: 9ff1a0c82d7268b89aeeb112c7f9250b
description: hashed password
# $ref: "#/components/schemas/User"
example:
name: john
password: 9ff1a0c82d7268b89aeeb112c7f9250b
responses:
"201":
description: "The user account has been created"
content:
application/json:
schema:
type: object
$ref: "#/components/schemas/User"
"default":
description: "Unexpected error"
content:
application/json:
schema:
type: array
items:
type: object
$ref: "#/components/schemas/Error"
/users/{id}:
get:
summary: Get a users
parameters:
- in: path
name: id
schema:
type: number
example: 1
required: true
description: User Id for query
responses:
"200":
description: OK
content:
application/json:
schema:
type: array
items:
type: object
$ref: "#/components/schemas/User"
components:
schemas:
User:
properties:
id:
type: integer
example: 123
description: zero-based User ID
name:
type: string
example: David
password:
type: string
example: 9ff1a0c82d7268b89aeeb112c7f9250b
description: hashed password
required:
- id
Error:
properties:
code:
type: string
message:
type: string

View File

@ -0,0 +1,30 @@
package com.badbuta.learnspringbootrestfulsqlite.services;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.badbuta.learnspringbootrestfulsqlite.entities.User;
import com.badbuta.learnspringbootrestfulsqlite.mapper.UserMapper;
@Service
public class UserService {
@Autowired
UserMapper userMapper;
public int insertUser(User user) {
int insteredUserId = userMapper.insertUser(user);
return insteredUserId;
}
public User getUserById(int id) {
return userMapper.getUserById(id);
}
public List<User> getUsers() {
// Map<String, User> users = userMapper.getUsers();
// return users.values().toArray(new User[0]);
return userMapper.getUsers();
}
}

View File

@ -1,5 +1,13 @@
spring.datasource.url=jdbc:sqlite:data
# spring.datasource.driver-class-name=org.sqlite.JDBC
# Setting used by @Repository
spring.datasource.url=jdbc:sqlite:data/mainapp.sqlite3
spring.datasource.driver-class-name=org.sqlite.JDBC
# spring.datasource.username=
# spring.datasource.password=
mybatis.config-location=classpath:mybatis/config.xml
# MyBatis related:
# mybatis.check-config-location=true
# mybatis.mapper-locations=classpath:mapper/*.xml
# mybatis.type-aliases-package=com.badbuta.learnspringbootrestfulsqlite.entities
mybatis.config-location=classpath:mybatis/mybatis-config.xml
server.port=8888

View File

@ -1,9 +0,0 @@
<?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="mainapp.mybatis">
<select id="selectUsers" resultType="map">
select * from users
</select>
</mapper>

View File

@ -0,0 +1,29 @@
<?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.badbuta.learnspringbootrestfulsqlite.mapper.UserMapper">
<select id="getUsers" resultType="User">
select * from users
</select>
<!-- NOTE: Sqlite JDBC driver not supporting RETURN_GENERATED_KEYS -->
<insert id="insertUser" parameterType="User" keyProperty="id">
<selectKey order="AFTER" keyProperty="id" resultType="int">
SELECT last_insert_rowid()
</selectKey>
insert into users (name,password) values (#{name},#{password})
</insert>
<select id="getUserById" parameterType="int" resultType="User">
select *
from users
where id = #{id};
</select>
<!-- <resultMap id="UserM" type="com.badbuta.learnspringbootrestfulsqlite.entities.User">
<result property="id" column="id" />
<result property="name" column="name" />
<result property="password" column="password" />
</resultMap> -->
</mapper>

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="learnspringbootrestfulsqlite">
<environment id="learnspringbootrestfulsqlite">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="org.sqlite.JDBC"/>
<property name="url" value="jdbc:sqlite:data/mainapp.sqlite3"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/mainapp.xml"/>
</mappers>
</configuration>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- In order to use the application setting here, we need to set the <properties> -->
<properties resource="application.properties"/>
<typeAliases>
<!-- Equivent to application.properties: mybatis.type-aliases-package -->
<package name="com.badbuta.learnspringbootrestfulsqlite.entities"></package>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${spring.datasource.driver-class-name}"/>
<property name="url" value="${spring.datasource.url}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapping/UserMapper.xml"/>
</mappers>
</configuration>