使用Spring创建一个简单的系统

我们将创建一个简单的工资服务来管理公司的员工。我们将员工对象存储在(内存中的H2)数据库中,并访问它们(通过一种称为JPA的东西)。然后我们将用允许通过互联网访问的东西(称为Spring MVC层)来包装它。

1.定义职工

package payroll;

import java.util.Objects;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
//@Entity是JPA注释,用于使该对象准备好存储在基于JPA的数据存储中。
//id、name和role是我们员工域对象的属性。id用更多的JPA注释标记,以表明它是主键,并由JPA提供商自动填充。

class Employee {

  private @Id @GeneratedValue Long id;
  private String name;
  private String role;

  Employee() {}

  Employee(String name, String role) {

    this.name = name;
    this.role = role;
  }

  public Long getId() {
    return this.id;
  }

  public String getName() {
    return this.name;
  }

  public String getRole() {
    return this.role;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public void setName(String name) {
    this.name = name;
  }

  public void setRole(String role) {
    this.role = role;
  }

  @Override
  public boolean equals(Object o) {

    if (this == o)
      return true;
    if (!(o instanceof Employee))
      return false;
    Employee employee = (Employee) o;
    return Objects.equals(this.id, employee.id) && Objects.equals(this.name, employee.name)
        && Objects.equals(this.role, employee.role);
  }

  @Override
  public int hashCode() {
    return Objects.hash(this.id, this.name, this.role);
  }

  @Override
  public String toString() {
    return "Employee{" + "id=" + this.id + ", name='" + this.name + '\'' + ", role='" + this.role + '\'' + '}';
  }
}

2.获取数据

使用Spring Data JPA来处理繁琐的数据库交互。Spring Data JPA存储库是与支持针对后端数据存储创建、读取、更新和删除记录的方法的接口。一些存储库还支持适当的数据分页和排序。

Spring使访问数据变得容易。通过简单地声明以下EmployeeRepository界面,我们将自动能够创建新员工;更新现有的;删除员工;查找员工。

package payroll;

import org.springframework.data.jpa.repository.JpaRepository;

interface EmployeeRepository extends JpaRepository<Employee, Long> {

}

为了获得所有这些免费功能,我们所要做的就是声明一个扩展Spring Data JPA的JpaRepository的接口,将域类型指定为Employee,并将id类型指定为Long

此时就足以启动一个应用程序。

package payroll;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
//@SpringBootApplication是一个元注释,可以拉动组件扫描、自动配置和属性支持。启动一个servlet容器并提供服务。
public class PayrollApplication {

  public static void main(String... args) {
    SpringApplication.run(PayrollApplication.class, args);
  }
}

但是此时还没有数据,最好还是加上数据才直观。

package payroll;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
class LoadDatabase {

  private static final Logger log = LoggerFactory.getLogger(LoadDatabase.class);

  @Bean
  CommandLineRunner initDatabase(EmployeeRepository repository) {

    return args -> {
      log.info("Preloading " + repository.save(new Employee("Bilbo Baggins", "burglar")));
      log.info("Preloading " + repository.save(new Employee("Frodo Baggins", "thief")));
    };
  }
}

右键单击并运行PayRollApplication,将显示数据预加载的控制台输出片段

...2018-08-09 11:36:26.169 INFO 74611 --- [main] payroll.LoadDatabase:预加载员工(id=1,name=Bilbo Baggins,role=burglar)2018-08-09 11:36:26.174 INFO 74611 --- [main] payroll.LoadDatabase:预加载员工(id=2,姓名=Frodo Baggins,角色=小偷)...

首先运行CommandLineRunner beans;然后该运行器将请求您刚刚创建EmployeeRepository的副本。将创建两个实体并存储它们。

3.使用HTTP平台访问

package payroll;

import java.util.List;

import org.springframework.web.bind.annotation.DeleteMapping;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
class EmployeeController {

  private final EmployeeRepository repository;

  EmployeeController(EmployeeRepository repository) {
    this.repository = repository;
  }


  // Aggregate root
  // tag::get-aggregate-root[]
  @GetMapping("/employees")
  List<Employee> all() {
    return repository.findAll();
  }
  // end::get-aggregate-root[]

  @PostMapping("/employees")
  Employee newEmployee(@RequestBody Employee newEmployee) {
    return repository.save(newEmployee);
  }

  // Single item
  
  @GetMapping("/employees/{id}")
  Employee one(@PathVariable Long id) {
    
    return repository.findById(id)
      .orElseThrow(() -> new EmployeeNotFoundException(id));
  }

  @PutMapping("/employees/{id}")
  Employee replaceEmployee(@RequestBody Employee newEmployee, @PathVariable Long id) {
    
    return repository.findById(id)
      .map(employee -> {
        employee.setName(newEmployee.getName());
        employee.setRole(newEmployee.getRole());
        return repository.save(employee);
      })
      .orElseGet(() -> {
        newEmployee.setId(id);
        return repository.save(newEmployee);
      });
  }

  @DeleteMapping("/employees/{id}")
  void deleteEmployee(@PathVariable Long id) {
    repository.deleteById(id);
  }
}
  • @RestController表示每种方法返回的数据将直接写入响应主体,而不是渲染模板。

  • 构造函数将EmployeeRepository注入控制器。

  • 我们有每个操作的路由(@@GetMapping@PostMapping@PutMapping@DeleteMapping,对应HTTP GETPOSTPUTDELETE调用)。

  • EmployeeNotFoundException是用于指示员工被查找但未找到时的例外。

package payroll;

class EmployeeNotFoundException extends RuntimeException {

  EmployeeNotFoundException(Long id) {
    super("Could not find employee " + id);
  }
}
package payroll;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

@ControllerAdvice
class EmployeeNotFoundAdvice {

  @ResponseBody
  @ExceptionHandler(EmployeeNotFoundException.class)
  @ResponseStatus(HttpStatus.NOT_FOUND)
  String employeeNotFoundHandler(EmployeeNotFoundException ex) {
    return ex.getMessage();
  }
}
  • @ResponseBody表明此建议直接传达给响应机构。

  • @ExceptionHandler将建议配置为仅在抛出EmployeeNotFoundException时做出响应。

  • @ResponseStatus说要发布HttpStatus.NOT_FOUND,即HTTP 404

  • 建议的主体生成内容。在这种情况下,它会给出异常的信息。

4.最终结果

除了直接在网站的url上进行操作,还可以使用命令行

$ curl -v localhost:8080/employees/99
$ curl -X POST localhost:8080/employees -H 'Content-type:application/json' -d '{"name": "Samwise Gamgee", "role": "gardener"}'
$ curl -X PUT localhost:8080/employees/3 -H 'Content-type:application/json' -d '{"name": "Samwise Gamgee", "role": "ring bearer"}'
$ curl -X DELETE localhost:8080/employees/3
#现在如果我们再看一遍,它就不见了
$ curl localhost:8080/employees/3
#找不到员工3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值