基于SpringMVC进行REST服务开发

背景

REST的概念这里不多过多阐述。在REST中,资源通过URL进行识别和定位。一般来说,以下这些HTTP方法通常会匹配为如下的CRUD动作:

Create:POST

Read:GET

Update:PUT或PATCH

Delete:DELETE


@ResponseBody:此注解会告知Spring,我们要将返回的对象作为资源发送给客户端,并将其转化为客户端可接受的表现形式。如果客户端的Accept头部信息表明它接受"application/json",并且jackson JSON库位于应用程序的路径下,那么会将返回结果列表转化为json格式。

@RestController:此注解能为控制器的所有处理方法应用消息转化功能。不必为每个方法都添加@ResponseBody了。

@ResponseEntity:作为@ResponseBody的替代方案,@ResponseEntity中可以包含响应相关的元数据(如头部信息和状态码)以及要转换成资源表述的对象。

@ResponseStatus:此注解可以指定状态码。

 


环境搭建相关

SpringMVC相关的jar包全部引入便是

                               

c3p0相关jar包:

                              

jackson相关jar包:

                            

oracle jdbc 相关jar包:

                             

spring.xml 文件代码如下图所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    	http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">  
       <!-- 定义要扫描 controller的包 -->
       <context:component-scan base-package="cn.com.restapi.controller" />
       <context:component-scan base-package="cn.com.restapi.daoimpl"/>
       <context:component-scan base-package="cn.com.restapi.serviceimpl"/>

       <mvc:default-servlet-handler /> 
       <!-- 启动注解驱动 SpringMVC 功能 -->
       <mvc:annotation-driven />
       
       <!-- 引用配置文件 -->
       <context:property-placeholder location="classpath:jdbc.properties"/>

       <!-- 配置视图解析器解析路径 -->
       <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
              <!-- 定义视图存放路径 -->
              <property name="prefix" value="/WEB-INF/jsp/" />
              <!-- 定义视图后缀 -->
              <property name="suffix" value=".jsp" />
       </bean>
       
       <!-- 1、声明数据源对象:C3P0连接池 -->
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <!-- 加载jdbc驱动 -->
            <property name="driverClass" value="${driverClass}"></property>
            <!-- jdbc连接地址 -->
            <property name="jdbcUrl" value="${jdbcUrl}"></property>
            <!-- 连接数据库的用户名 -->
            <property name="user" value="${user}"></property>
            <!-- 连接数据库的密码 -->
            <property name="password" value="${password}"></property>
            <!-- 数据库的初始化连接数 -->
            <property name="initialPoolSize" value="3"></property>
            <!-- 数据库的最大连接数 -->
            <property name="maxPoolSize" value="10"></property>
            <!-- 数据库最多执行的事务 -->
            <property name="maxStatements" value="100"></property>
            <!-- 连接数量不够时每次的增量 -->
            <property name="acquireIncrement" value="2"></property>           
        </bean>
        
        <!--  创建jdbcTemplate对象 -->
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource">
            </property>
        </bean>
      
</beans>

 jdbc.properties 配置文件如下图所示:

               

 

整个项目的目录如下图所示:

                                

实体类Employee.java代码:

package cn.com.restapi.model;

public class Employee {

	private int employeeID;
	private String employeeName;
	private int age;
	private String address;
	private String sex;
	
	@Override
	public String toString(){
		return "Employee[EMPLOYEE_ID=" + employeeID + ",EMPLOYEENAME=" + employeeName + ",AGE=" + age + ",ADDRESS=" + address + ",SEX=" + sex + "]";
	}

    //get and set........
}

 

dao层代码:

import java.util.List;
import cn.com.restapi.model.Employee;

public interface EmployeeDao {
	public List<Employee> getEmployees();
	public Employee getEmployeeByID(int id);
	public int createEmployee(Employee employee);
	public int updateEmployee(Employee employee);
	public int deleteEmployee(Employee employee);
	public boolean ifEmployeeExist(Employee employee);
}

daoimpl层代码,此处使用c3p0数据源和Spring中的JdbcTemplate模板。

package cn.com.restapi.daoimpl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import cn.com.restapi.dao.EmployeeDao;
import cn.com.restapi.model.Employee;

@Repository
public class EmployeeDaoImpl implements EmployeeDao{
	@Autowired
	private JdbcTemplate jdbcTemplate;
	private Log log = LogFactory.getLog(EmployeeDaoImpl.class.getName());
	
	@Override
	public List<Employee> getEmployees() {
		// TODO Auto-generated method stub
		String sql = "SELECT EMPLOYEE_ID,EMPLOYEE_NAME,AGE,ADDRESS,SEX FROM EMPLOYEE";
		log.info(sql);
		return jdbcTemplate.query(sql, new EmployeeRowMapper());
	}

	@Override
	public Employee getEmployeeByID(int id) {
		// TODO Auto-generated method stub
		String sql = "SELECT EMPLOYEE_ID,EMPLOYEE_NAME,AGE,ADDRESS,SEX FROM EMPLOYEE WHERE EMPLOYEE_ID = ?";
		log.info(sql);
		List<Employee> employees = this.jdbcTemplate.query(sql, new EmployeeRowMapper(),id);
		if (employees.isEmpty()) {
			return null;
		}
		return employees.get(0);
	}

	@Override
	public int createEmployee(Employee employee) {
		// TODO Auto-generated method stub
		String sql = "INSERT INTO EMPLOYEE(EMPLOYEE_ID,EMPLOYEE_NAME,AGE,ADDRESS,SEX) VALUE(?,?,?,?,?)";
		log.info(sql);
		int rowNum = this.jdbcTemplate.update(sql,employee.getEmployeeID(),employee.getEmployeeName(),employee.getAge(),employee.getAddress(),employee.getSex());
		return rowNum;
	}

	@Override
	public int updateEmployee(Employee employee) {
		// TODO Auto-generated method stub
		String sql  = "UPDATE EMPLOYEE SET EMPLOYEE_NAME = ?,AGE = ?,ADDRESS = ?,SEX = ? WHERE EMPLOYEE_ID = ?";
		log.info(sql);
		int rowNum = this.jdbcTemplate.update(sql,employee.getEmployeeName(),employee.getAge(),employee.getAddress(),employee.getSex(),employee.getEmployeeID());
		return rowNum;
	}

	@Override
	public int deleteEmployee(Employee employee) {
		// TODO Auto-generated method stub
		String sql = "DELETE EMPLOYEE WHERE EMPLOYEE_ID = ?";
		log.info(sql);
		int rowNum = this.jdbcTemplate.update(sql,employee.getEmployeeID());
		return rowNum;
	}
	
	public class EmployeeRowMapper implements RowMapper<Employee>{
		@Override
		public Employee mapRow(ResultSet rSet, int rowNum) throws SQLException {
			// TODO Auto-generated method stub
			Employee employee = new Employee();
			employee.setEmployeeID(rSet.getInt("EMPLOYEE_ID"));
			employee.setEmployeeName(rSet.getString("EMPLOYEE_NAME"));
			employee.setAddress(rSet.getString("ADDRESS"));
			employee.setAge(rSet.getInt("AGE"));
			employee.setSex(rSet.getString("SEX"));
			return employee;
		}

	}

	@Override
	public boolean ifEmployeeExist(Employee employee) {
		// TODO Auto-generated method stub
		Employee employee2 = this.getEmployeeByID(employee.getEmployeeID());
		if (employee2 == null) {
			return true;
		}
		return false;
	}

}

Service层代码:

package cn.com.restapi.service;

import java.util.List;
import cn.com.restapi.model.Employee;

public interface EmployeeService {
	public List<Employee> getEmployees();
	public Employee getEmployee(int id);
	public int createEmployee(Employee employee);
	public int updateEmployee(Employee employee);
	public int deleteEmployee(Employee employee);
	public boolean ifEmployeeExist(Employee employee);
}

ServiceImpl层代码:

package cn.com.restapi.serviceimpl;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.com.restapi.dao.EmployeeDao;
import cn.com.restapi.model.Employee;
import cn.com.restapi.service.EmployeeService;


@Service
public class EmployeeServiceImpl implements EmployeeService{
	@Autowired
	private EmployeeDao employeeDao;
	@Override
	public List<Employee> getEmployees() {
		// TODO Auto-generated method stub
		List<Employee> employees = employeeDao.getEmployees();
		return employees;
	}

	@Override
	public Employee getEmployee(int id) {
		// TODO Auto-generated method stub
		Employee employee = employeeDao.getEmployeeByID(id);
		return employee;
	}

	@Override
	public int createEmployee(Employee employee) {
		// TODO Auto-generated method stub
		int rowNum = employeeDao.createEmployee(employee);
		return rowNum;
	}

	@Override
	public int updateEmployee(Employee employee) {
		// TODO Auto-generated method stub
		int rowNum = employeeDao.updateEmployee(employee);
		return rowNum;
	}

	@Override
	public int deleteEmployee(Employee employee) {
		// TODO Auto-generated method stub
		int rowNum = employeeDao.deleteEmployee(employee);
		return rowNum;
	}

	@Override
	public boolean ifEmployeeExist(Employee employee) {
		// TODO Auto-generated method stub
		boolean b = employeeDao.ifEmployeeExist(employee);
		return b;
	}
	
}

 Controller层代码,分别对Employee表实现CRUD操作:

package cn.com.restapi.controller;

import java.net.URI;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriComponentsBuilder;
import cn.com.restapi.model.Employee;
import cn.com.restapi.model.EmployeeNotFoundException;
import cn.com.restapi.model.Error;
import cn.com.restapi.service.EmployeeService;

@RestController
public class EmployeeController {
	@Autowired
	public EmployeeService employeeService;
	public Log log = LogFactory.getLog(EmployeeController.class.getName());
	
	@RequestMapping(value="/employee",method = RequestMethod.GET)
	public ResponseEntity<List<Employee>> getEmployees(){
		log.info("getEmployee method called");
		List<Employee> employees = employeeService.getEmployees();
		if (employees.isEmpty()) {
			return new ResponseEntity<List<Employee>>(employees,HttpStatus.NO_CONTENT);
		}
		return new ResponseEntity<List<Employee>>(employees,HttpStatus.OK);
	}
	
	@RequestMapping(value="/employee/{id}",method = RequestMethod.GET)
	public Employee getEmployeeByID(@PathVariable("id") int id){
		log.info("getEmployeeByID method called");
		Employee employee = employeeService.getEmployee(id);
		if (employee == null) {throw new EmployeeNotFoundException(id);}
		return employee;
	}
	
	@ExceptionHandler(EmployeeNotFoundException.class)
	@ResponseStatus(HttpStatus.NOT_FOUND)
	public ResponseEntity<Error> EmployeeNotFound(EmployeeNotFoundException e){
		int employeeId = e.getEmployeeId();
		Error error = new Error(4, "Employee [" + employeeId + "] not found");
		return new ResponseEntity<Error>(error,HttpStatus.NOT_FOUND);
	}
	
	@RequestMapping(value="/employee",method = RequestMethod.POST,consumes="application/json")
	public ResponseEntity<?> creatEmployee(@RequestBody Employee employee,UriComponentsBuilder ucb){
		if (employeeService.ifEmployeeExist(employee)) {
			Error error = new Error(4, "Employee [id=" + employee.getEmployeeID() + "] already exist");
			return new ResponseEntity<Error>(error,HttpStatus.CONFLICT);
		}
		employeeService.createEmployee(employee);
		HttpHeaders headers = new HttpHeaders();
		URI locationUri = ucb.path("/RESTAPI/").path(String.valueOf(employee.getEmployeeID())).build().toUri();
		headers.setLocation(locationUri);
		ResponseEntity<Employee> responseEntity = new ResponseEntity<Employee>(employee,headers,HttpStatus.CREATED);
		return responseEntity;
	}
	
	@RequestMapping(value="/employee",method = RequestMethod.PUT,consumes="application/json")
	public ResponseEntity<?> updateEmployee(@RequestBody Employee employee,UriComponentsBuilder ucb){
		if (!employeeService.ifEmployeeExist(employee)) {
			Error error = new Error(4, "Employee [id=" + employee.getEmployeeID() + "] not found");
			return new ResponseEntity<Error>(error,HttpStatus.NOT_FOUND);
		}
		employeeService.updateEmployee(employee);
		HttpHeaders headers = new HttpHeaders();
		URI locationUri = ucb.path("/RESTAPI/").path(String.valueOf(employee.getEmployeeID())).build().toUri();
		headers.setLocation(locationUri);
		ResponseEntity<Employee> responseEntity = new ResponseEntity<Employee>(employee,headers,HttpStatus.OK);
		return responseEntity;
	}
	
	@RequestMapping(value="/employee",method=RequestMethod.DELETE,consumes="application/json")
	public ResponseEntity<?> deleteEmployee(@RequestBody Employee employee){
		if (!employeeService.ifEmployeeExist(employee)) {
			Error error = new Error(4, "Employee [id=" + employee.getEmployeeID() + "] not found");
			return new ResponseEntity<Error>(error,HttpStatus.NOT_FOUND);
		}
		employeeService.deleteEmployee(employee);
		return new ResponseEntity<Employee>(HttpStatus.NO_CONTENT);
	}
	
}

 Controller层中有两个实体类Error,EmployeeNotFoundException。用于返回错误信息:

package cn.com.restapi.model;

public class Error {
	private int code;
	private String message;
	
	public Error(int code,String message){
		this.code = code;
		this.message = message;
	}
	
	public int getCode(){
		return code;
	}
	
	public String getMessage(){
		return message;
	}
}
package cn.com.restapi.model;

public class EmployeeNotFoundException extends RuntimeException{
	private int EmployeeId;
	
	public EmployeeNotFoundException(int employeeId){
		this.EmployeeId = employeeId;
	}
	public int getEmployeeId(){
		return EmployeeId;
	}
}

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值