Rest 实践

结合之前所学的内容,这篇教程将基于 SpringMVC 构建一个真正的 Rest 服务。

首先构建 Service 层,即逻辑层,创建接口 PersonService:

  1. public interface PersonService {
  2. List<Person> get();
  3. Person get(int id);
  4. void add(int id, String name);
  5. void delete(int id);
  6. }

同时创建对应的 PersonServiceImpl 层,对应的实现可以留空。

然后在前面的 PersonController 基础上,加入更多的 API 支持:

  1. @ResponseStatus(value = HttpStatus.NOT_FOUND)
  2. class ResourceNotFoundException extends RuntimeException {
  3. }
  4. @RestController
  5. @RequestMapping("/person")
  6. public class PersonController {
  7. @Autowired
  8. private PersonService personService;
  9. @RequestMapping(method = RequestMethod.GET)
  10. public List<Person> getAllPerson() {
  11. return personService.get();
  12. }
  13. @RequestMapping(value = "/{id:[\\d]+}", method = RequestMethod.GET)
  14. public Person getPerson(
  15. @PathVariable(value = "id") int id
  16. )
  17. {
  18. Person result = personService.get(id);
  19. if (result == null)
  20. {
  21. throw new ResourceNotFoundException();
  22. }
  23. return result;
  24. }
  25. @RequestMapping(value = "", method = RequestMethod.POST)
  26. public void addPerson(@RequestParam int id, @RequestParam String name)
  27. {
  28. personService.add(id, name);
  29. }
  30. @RequestMapping(value = "/{id:[\\d]+}", method = RequestMethod.DELETE)
  31. public void deletePerson(
  32. @PathVariable(value = "id") int id
  33. )
  34. {
  35. personService.delete(id);
  36. }
  37. }

这样一个简单的 Rest 框架就搭建好了。

对于 PersonService 的实现部分,我们再抽取一个新的 PersonDao 接口:

  1. public interface PersonDao {
  2. List<Person> get();
  3. Person get(int id);
  4. void add(int id, String name);
  5. void delete(int id);
  6. }

PersonService 的实现可以面向 PersonDao 编程:

  1. @Service
  2. public class PersonServiceImpl implements PersonService {
  3. @Autowired
  4. private PersonDao personDao;
  5. @Override
  6. public List<Person> get() {
  7. return personDao.get();
  8. }
  9. @Override
  10. public Person get(int id) {
  11. return personDao.get(id);
  12. }
  13. @Override
  14. public void add(int id, String name) {
  15. personDao.add(id, name);
  16. }
  17. @Override
  18. public void delete(int id) {
  19. personDao.delete(id);
  20. }
  21. }

这样的做的好处是,把 Service 层和 Dao 层做到了权责分离,Service 层可以引入更多的业务逻辑,而 Dao 层则只关心数据的存取。同时由于是面向接口编程,Dao 层的具体实现也可以很灵活。

下面我们基于 SQLite 和 Spring 本身的 Dao 支持实现一个简单的 Dao 层。

首先在 pom.xml 中加入有关依赖:

  1. <dependency>
  2. <groupId>org.springframework</groupId>
  3. <artifactId>spring-jdbc</artifactId>
  4. <version>4.3.9.RELEASE</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.xerial</groupId>
  8. <artifactId>sqlite-jdbc</artifactId>
  9. <version>3.8.11.2</version>
  10. </dependency>

然后实现我们的 Dao 层:

  1. @Repository
  2. public class PersonDaoImpl implements PersonDao {
  3. private JdbcTemplate jdbcTemplate;
  4. @Autowired
  5. public PersonDaoImpl(DataSource dataSource) {
  6. this.jdbcTemplate = new JdbcTemplate(dataSource);
  7. }
  8. @Override
  9. public List<Person> get() {
  10. String sql = "select * from person";
  11. return this.jdbcTemplate.query(sql, ROW_MAPPER);
  12. }
  13. @Override
  14. public Person get(int id) {
  15. String sql = "select * from person where id = ?";
  16. try {
  17. return this.jdbcTemplate.queryForObject(sql, new Object[]{id}, ROW_MAPPER);
  18. }
  19. catch (EmptyResultDataAccessException e)
  20. {
  21. return null;
  22. }
  23. }
  24. @Override
  25. public void add(int id, String name) {
  26. String sql = "insert into person values (?, ?)";
  27. this.jdbcTemplate.update(sql, id, name);
  28. }
  29. @Override
  30. public void delete(int id) {
  31. String sql = "delete from person where id = ?";
  32. this.jdbcTemplate.update(sql, id);
  33. }
  34. private static final RowMapper<Person> ROW_MAPPER = (rs, rowNum) -> new Person(
  35. rs.getInt("id"),
  36. rs.getString("name"));
  37. }

在 AppConfig 中加入数据库的配置:

  1. @Configuration
  2. @EnableWebMvc
  3. @ComponentScan("com.skyline")
  4. public class AppConfig {
  5. @Bean
  6. DataSource getDataSource()
  7. {
  8. SQLiteDataSource dataSource = new SQLiteDataSource();
  9. dataSource.setUrl("jdbc:sqlite:D:/mydata.db");
  10. return dataSource;
  11. }
  12. }

当然这里要求数据库是提前建好的,使用了下面的 schema:

  1. CREATE TABLE person(id INTEGER, name VARCHAR);

将编译生成的 class 文件和依赖 jar 包(spring-jdbc,spring-tx,sqlite-jdbc)拷贝到 Tomcat 目录下,运行 Tomcat。使用 Curl 或者浏览器就可以测试我们的 Rest 服务了。