今天学习的是Restful实战
Dao层的完成
通过前面的学习,我们知道Dao 是直接面向数据库的,所以我们配好数据库环境。
创建一个名为restful_crud的数据库
sql
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for employee
-- ----------------------------
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '员工名字',
`age` int NULL DEFAULT NULL COMMENT '年龄',
`email` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '邮箱',
`gender` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '性别',
`address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '住址',
`salary` decimal(10, 2) NULL DEFAULT NULL COMMENT '薪资',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of employee
-- ----------------------------
INSERT INTO `employee` VALUES (1, '张三', 11, 'aa@qq.com', '男', '西安', 9999.00);
INSERT INTO `employee` VALUES (4, 'leifengyang', 10, 'aaa', '男', 'sss', 100.00);
SET FOREIGN_KEY_CHECKS = 1;
然后在application.properities配置数据库信息
bash
spring.application.name=springmvc-restful-crud
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/restful_crud
spring.datasource.username=root
spring.datasource.password=123456
Employee
java
package com.atguigu.rest.crud.bean;
import lombok.Data;
import java.math.BigDecimal;
public class Employee {
private Long id;
private String name;
private Integer age;
private String email;
private String gender;
private String address;
private BigDecimal salary;
@Override
public String toString() {
return "Employee{" +
"address='" + address + '\'' +
", id=" + id +
", name='" + name + '\'' +
", age=" + age +
", email='" + email + '\'' +
", gender='" + gender + '\'' +
", salary=" + salary +
'}';
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getSalary() {
return salary;
}
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
}
在controller文件夹下创建EmployeeDao接口
bash
package com.atguigu.rest.crud.dao;
import com.atguigu.rest.crud.bean.Employee;
public interface EmployeeDao {
Employee getEmployeeById(Long id);
void addEmployee(Employee employee);
void updateEmployee(Employee employee);
void deleteEmployee(Long id);
}
在controller/impl创建EmployeeDaoImpl实现类
需要补充的点
BeanPropertyRowMapper 是 Spring JDBC 框架中的一个实用类,用于将数据库查询结果集(ResultSet)自动映射到 Java Bean 对象。它通过反射机制,根据列名与 Bean 属性名的匹配关系进行自动映射,大大简化了手动从结果集提取数据并赋值给对象的过程。
bash
package com.atguigu.rest.crud.dao.impl;
import com.atguigu.rest.crud.bean.Employee;
import com.atguigu.rest.crud.dao.EmployeeDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
@Component
public class EmployeeDaoImpl implements EmployeeDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public Employee getEmployeeById(Long id) {
String sql = "select * from employee where id = ?";
Employee employee = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Employee.class), id);
return employee;
}
@Override
public void addEmployee(Employee employee) {
String sql = "insert into employee (name, age , email,gender,address,salary) values (?, ? , ? , ? , ? , ?)";
int update = jdbcTemplate.update(sql
, employee.getName()
, employee.getAge()
, employee.getEmail()
, employee.getGender()
, employee.getAddress()
, employee.getSalary());
System.out.println("新增成功,影响行数" + update);
}
@Override
public void updateEmployee(Employee employee) {
String sql = "update employee set name=?,age=?,email=?,gender=?,address=?,salary=? where id = ?";
int update = jdbcTemplate.update(sql , employee.getName()
, employee.getAge()
, employee.getEmail()
, employee.getGender()
, employee.getAddress()
, employee.getSalary()
, employee.getId());
System.out.println("新增成功,影响行数" + update);
}
@Override
public void deleteEmployee(Long id) {
String sql = "delete from employee where id = ?";
int update = jdbcTemplate.update(sql, id);
}
}
Service层的完成
需要注意到的一点就是,Dao层的update操作中,如果某些参数为空的时候,会出现修改后仍为空的情况,作为controller直接调用的层,可以对数据做预处理。
代码
/service/impl/EmployeeService
java
package com.atguigu.rest.crud.service;
import com.atguigu.rest.crud.bean.Employee;
public interface EmployeeService {
Employee getEmp(Long id);
void updateEmp(Employee employee);
void addEmp(Employee employee);
void deleteEmp(Long id);
}
/service/impl/EmployeeServiceImpl
StringUtils可以判断 字符是否非空非空白,如果是,则返回true
java
package com.atguigu.rest.crud.service.impl;
import ch.qos.logback.core.util.StringUtil;
import com.atguigu.rest.crud.bean.Employee;
import com.atguigu.rest.crud.dao.EmployeeDao;
import com.atguigu.rest.crud.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@Service //controller 调用 service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeDao employeeDao;//静态代理
@Override
public Employee getEmp(Long id) {
Employee empById = employeeDao.getEmployeeById(id);
return null;
}
@Override
public void updateEmp(Employee employee) {
//防null 处理。考虑到service是被controller调用的
//controller层传过来的employee的某些属性可能为null,所以先处理一下
// 先查一下找原始数据
// 把页面带来的数据覆盖原有的值
Long id = employee.getId();
if(id == null) return ;//没有带id
System.out.println(id);
Employee empById = employeeDao.getEmployeeById(id);
//StringUtils可以判断 字符是否非空非空白
if(!StringUtils.hasText(employee.getAddress())){
empById.setAddress(employee.getAddress());
}
if(!StringUtils.hasText(employee.getName())){
empById.setName(employee.getName());
}
if(!StringUtils.hasText(employee.getGender())){
empById.setGender(employee.getGender());
}
if(!StringUtils.hasText(employee.getEmail())){
empById.setEmail(employee.getEmail());
}
if(!StringUtils.hasText(employee.getName())){
empById.setName(employee.getName());
}
if(employee.getSalary() != null){
empById.setSalary(employee.getSalary());
}
if(employee.getAge() != null){
empById.setAge(employee.getAge());
}
employeeDao.updateEmployee(employee);
}
@Override
public void addEmp(Employee employee) {
employeeDao.addEmployee(employee);
}
@Override
public void deleteEmp(Long id) {
employeeDao.deleteEmployee(id);
}
}
Controller层的完成
设计目标
路径变量 PathVariable
我们可以在路径上定义一个动态变量接收一个参数,比如"/employee/{id}"
get方法的编写如下,相对于之前学习的@RequestParam,这里用到了@PathVariable去接收路径上的参数信息。
java
package com.atguigu.rest.crud.controller;
import com.atguigu.rest.crud.bean.Employee;
import com.atguigu.rest.crud.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class EmployeeRestController {
@Autowired
private EmployeeService employeeService;
@RequestMapping("/employee/{id}")//路径变量,动态的,{id}可以随机取值
public Employee get(@PathVariable Long id) {//PathVariable路径变量,因为路径是动态的
Employee employee = employeeService.getEmp(id);
System.out.println(employee);
return employee;
}
}
crud的实现全代码
bash
package com.atguigu.rest.crud.controller;
import com.atguigu.rest.crud.bean.Employee;
import com.atguigu.rest.crud.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
public class EmployeeRestController {
@Autowired
private EmployeeService employeeService;
@RequestMapping(value = "/employee/{id}" , method = RequestMethod.GET)//路径变量,动态的,{id}可以随机取值
public Employee get(@PathVariable Long id) {//PathVariable路径变量,因为路径是动态的
Employee employee = employeeService.getEmp(id);
System.out.println(employee);
return employee;
}
@RequestMapping(value = "/employee/{id}" , method = RequestMethod.DELETE)//路径变量,动态的,{id}可以随机取值
public String delete(@PathVariable("id") Long id) {//PathVariable路径变量,因为路径是动态的
employeeService.deleteEmp(id);
return "ok";
}
@PostMapping("/employee")
public String add(@RequestBody Employee employee) {
employeeService.addEmp(employee);
return "ok";
}
@PutMapping("/employee")
public String update(@RequestBody Employee employee) {//必须携带id
employeeService.updateEmp(employee);
return "ok";
}
}
崩溃ing,找错误找半天,最终才发现是因为定义R类的时候没加getter方法,是因为我在用@Data的时候,总是爆神秘错误,然后我就手动getter and setter了,但是没加getter,可能是因为没getter获取不到里面的数据吧,然后就无法转换成功,呜呜呜。
不过查询相关资料,好像有个神秘的解决该错误的方法
神秘方法,然后用这个方法确实成功解决了问题。
在pom.xml注释掉该段,加上刷新一下maven即可。
class类R的编写
java
package com.atguigu.rest.crud.common;
import lombok.Data;
@Data
public class R<T> {
private Integer code;
private String msg;
private T data;
public static <T> R<T> ok(T data) {
R<T> r = new R<>();
r.setCode(200);
r.setMsg("ok");
r.setData(data);
return r;
}
public static <T> R<T> ok() {
R<T> r = new R<>();
r.setCode(200);
r.setMsg("ok");
return r;
}
}
查询所有员工的实现
EmployeeImpl的实现,用的是query接口
java
@Override
public List<Employee> getList() {
String sql = "select * from employee";
List<Employee> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Employee.class));
return list;
}