0 引言
作者正在学习SpringMVC相关内容,学到了一些知识,希望分享给需要短时间想要了解SpringMVC的读者朋友们,想用通俗的语言讲述其中的知识,希望与诸位共勉,共同进步!
本系列会持续更新!!可以放心食用!
ps:RestFul架构风格会分为上中下三篇来描述,名字分别为系列五-系列七,这三篇会同一时间发布!!!
1 Restful软件架构风格
系列五中已经介绍了初步准备工作以及介绍了大致的架构风格,本篇就来把里面的相关代码进行完善,下面我将继续介绍业务结构的代码书写
1.1 dao包代码
写具体代码之前 我们回顾一下dao包的代码结构:
主要包括接口以及对应的实现。
系列五中已经阐述了dao包内的数据主要用与数据库进行交互,所以可以想象得到这里是代码部分进行SQL语句的编写实现与数据库的交互。
1)具体实现代码如下:
EmployeeDao接口中的代码:
import org.example.restful.bean.Employee;
public interface EmployeeDao {
/*
根据id查询员工
*/
Employee getEmployeeById(Long id);
/*
添加员工
*/
void addEmp(Employee employee);
/*
修改员工
*/
void updateEmp(Employee employee);
/*
按照id删除员工
*/
void deleteById(Long id);
}
主要定义了对员工表进行正常的在那个删改查的操作的方法范式,这些方法在实现类中进行实现。
EmployeeDao实现中的代码:
import org.example.restful.bean.Employee;
import org.example.restful.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 addEmp(Employee employee) {
String sql = "insert into employee(name,age,email,gender,address,salary) values(?,?,?,?,?,?)";
jdbcTemplate.update(sql, employee.getName(), employee.getAge(), employee.getEmail(), employee.getGender(), employee.getAddress(), employee.getSalary());
System.out.println("添加成功");
}
@Override
public void updateEmp(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 deleteById(Long id) {
String sql = "delete from employee where id = ?";
int update = jdbcTemplate.update(sql, id);
}
我们可以很清晰的看到dao包中的实现类都是围绕着编写SQL语句对数据库进行操作的相关方法,所以我们也能明确dao包的作用主要是和数据库的数据进行交互。
2)简单对dao包中的两种方法进行测试:
单独创建一个测试:
测试getEmployeeById方法:
import org.example.restful.bean.Employee;
import org.example.restful.dao.EmployeeDao;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.math.BigDecimal;
@SpringBootTest
public class DaoTest {
@Autowired
EmployeeDao employeeDao;
@Test
void testEmployeeDao(){
Employee employee = employeeDao.getEmployeeById(1L);
System.out.println(employee);
}
测试结果:
可以顺利打印出数据表中id为1的对象,可打开数据表中的数据进行查看,结果是一致的:
测试addEmp方法:
import org.example.restful.bean.Employee;
import org.example.restful.dao.EmployeeDao;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.math.BigDecimal;
@SpringBootTest
public class DaoTest {
@Autowired
EmployeeDao employeeDao;
@Test
void testEmployeeDao(){
Employee employee = new Employee();
employee.setId(5L);
employee.setName("张三");
employee.setAge(18);
employee.setEmail("aaa");
employee.setGender("男");
employee.setAddress("上海");
employee.setSalary(new BigDecimal(1000));
employeeDao.addEmp(employee);
}
}
刷新一下数据库,结果增加了一项员工数据:
1.2 service包代码
同样,写具体代码之前 我们回顾一下service包的代码结构:
主要包括接口以及对应的实现。
听这个名字,服务层,那可以大概猜测这里的代码是实现具体业务的代码。
1)具体实现代码如下:
EmployeeService接口中的代码:
import org.example.restful.bean.Employee;
public interface EmployeeService {
Employee getEmp(Long id);
/*
添加员工
*/
void saveEmp(Employee employee);
/*
修改员工
*/
void updateEmp(Employee employee);
/*
按照id删除员工
*/
void deleteEmp(Long id);
EmployeeServiceImpl实现中的代码:
import org.example.restful.bean.Employee;
import org.example.restful.dao.EmployeeDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.example.restful.service.EmployeeService;
@Service
public class EmployeeServiceImpl implements org.example.restful.service.EmployeeService {
@Autowired
private EmployeeDao employeeDao;
@Override
public Employee getEmp(Long id) {
Employee employee = employeeDao.getEmployeeById(id);
return employee;
}
@Override
public void saveEmp(Employee employee) {
employeeDao.addEmp(employee);
}
@Override
public void updateEmp(Employee employee) {
//防空处理:controll可能默写属性值没填,那就需要保存修改的数值
Long id = employee.getId();
if (id == null) {
return;
}
Employee employee1 = employeeDao.getEmployeeById(id);
//校验数据的完整性,进行修改
if(StringUtils.hasText(employee.getName())){employee1.setName(employee.getName());}
if(employee.getAge() != null){employee1.setAge(employee.getAge());}
if(StringUtils.hasText(employee.getEmail())){employee1.setEmail(employee.getEmail());}
if(StringUtils.hasText(employee.getGender())){employee1.setGender(employee.getGender());}
if(StringUtils.hasText(employee.getAddress())){employee1.setAddress(employee.getAddress());}
if(employee.getSalary() != null){employee1.setSalary(employee.getSalary());}
employeeDao.updateEmp(employee1);
}
@Override
public void deleteEmp(Long id) {
employeeDao.deleteById(id);
}
}
我们可以看到这里的接口代码几乎与dao包中的接口代码一致,实现类中只是简单调用一下dao包中的方法来实现,因为这些只是最简单的增删改查业务,那为什么我们还需要service包呢?
我们可以关注一下updateEmp方法。我们在调用employeeDao.updateEmp(employee1);之前还做其他一些功能,相当于是提供一种静态的代理,在真正执行数据库操作之前进行一些其他操作,在这里增加了一些数据校验的功能,目的是只对controller传入的数据进行修改,而对comtroller没有传过来的数据保持原数值!!!
2)对updateEmp方法进行测试:
测试代码:
import org.example.restful.bean.Employee;
import org.example.restful.service.EmployeeService;
import org.example.restful.service.Impl.EmployeeServiceImpl;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class ServiceTest {
@Autowired
EmployeeService employeeService;
@Test
public void testUpdateEmp()
{
Employee employee = new Employee();
employee.setId(1L);
employee.setName("小林学编程");
employeeService.updateEmp(employee);
}
}
上述测试方法中我只修改的名字,将名字从张三改成小林学编程,其余均不变,测试结果如下:
原数据库数据:
修改后的数据库数据:
1.3 controller包代码
同样,写具体代码之前 我们回顾一下controller包的代码结构:
一个数据表对应一个名称的controller(service和dao都是如此)
我们在上文说过controller包最能体现Restful代码风格是因为它就是用于响应前端请求的部分,主要代码提供各种前端请求的API!!!
具体代码如下:
import org.example.restful.bean.Employee;
import org.example.restful.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.lang.reflect.Method;
@RestController
@RequestMapping("/employee")
public class EmployeeRestController {
@Autowired
EmployeeService employeeService;
@GetMapping(value = "/{id}")
public String getEmployee(@PathVariable Long id) {
Employee emp = employeeService.getEmp(id);
return "get" + emp;
}
@DeleteMapping(value = "/{id}")
public String deleteEmployee(@PathVariable Long id) {
employeeService.deleteEmp(id);
return "delete" + id;
}
@PostMapping()
public String saveEmployee(@RequestBody Employee employee) {
employeeService.saveEmp(employee);
return "save" + employee;
}
@PutMapping()
public String updateEmployee(@RequestBody Employee employee) {
employeeService.updateEmp(employee);
return "update" + employee;
}
}
体现Restful风格的点:
1)@RequestMapping("/employee")
这行代码写在我们controller类的头上,表达出这个controller下的所有请求的前缀均为"/employee",优化了代码风格。
2)@XXXMapping注解
例如存在@GetMapping(value = "/{id}")等等,先介绍一下些注解@GetMapping、@PostMapping等注解,其实下面这两段代码是一致的,就是将请求方式限定为某个类型,比如Get
@GetMapping(value = "/{id}")
@RequestMapping(value = "/{id}",method = RequestMethod.GET)
因为我们说Restful风格它可以依靠请求类型的不同来区分不同的业务请求,所以@XXXMapping这样的注解形式也能清晰的展示出是何种请求,即使在请求url一致的情况下!
1.4 总结
以上说明了一个对员工进行增删改查的功能的代码具体的业务风格如下图:
如果想直接看完整代码可以直接去这个地址:
lin/Restful_codehttps://gitee.com/lin2002wei/restful_code
参考:
P108-P110