一个小小的restful api demo

背景

最近需要抽离出一个复用模块作为服务端代码供其他多个项目调用,选用的是作为restful风格的api。先写个demo做测试,直接贴代码吧,供自己以后回顾参考。

demo

  1. 开发工具:eclipse;
  2. 数据库:oracle。
项目结构

项目结构

配置文件
testService-servlet.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:aop="http://www.springframework.org/schema/aop"  
             xmlns:tx="http://www.springframework.org/schema/tx"  
             xmlns:mvc="http://www.springframework.org/schema/mvc"  
             xsi:schemaLocation="http://www.springframework.org/schema/beans  
                     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
                     http://www.springframework.org/schema/context  
                     http://www.springframework.org/schema/context/spring-context-3.0.xsd  
                     http://www.springframework.org/schema/aop  
                     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
                     http://www.springframework.org/schema/tx  
                     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
                     http://www.springframework.org/schema/mvc   
                     http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"  
                     default-autowire="byName"  
                     >
                     
                     <!-- initial bean -->
                     <context:component-scan base-package="test.*"></context:component-scan>
                     
                     <!-- news config -->
                     <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
                     	<property name="messageConverters">
                     		<list>
                     			<!-- json convert -->
                     			<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
                     		</list>
                     	</property>
                     </bean>
                     
                     <!-- spring MVC注解驱动 -->
                     <mvc:annotation-driven/>
                     
</beans>                     
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:web="http://java.sun.com/xml/ns/javaee" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
						http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
			id="WebApp_ID" 
			version="3.0">
  <display-name>testService</display-name>
  <servlet>
    <servlet-name>testService</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>testService</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
  <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>utf-8</param-value>
    </init-param>
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>
实体类
package test.entity;

import java.io.Serializable;

public class Person implements Serializable{
	
	private static final long serialVersionUID = -3727979363425652597L;
	
	private int id;
	private String name;
	private int age;
	
	public int getId() {
		return id;
	}
	public String getName() {
		return name;
	}
	public int getAge() {
		return age;
	}
	public void setId(int id) {
		this.id = id;
	}
	public void setName(String name) {
		this.name = name;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	
}

service接口类
package test.service;

import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public interface IAcctService {
	
	@RequestMapping(value="/hello",produces="text/plain;charset=UTF-8")
	public @ResponseBody
	String hello();
	
	@RequestMapping(value="/say/{msg}",produces="application/json;charset=UTF-8")
	public @ResponseBody
	String say(@PathVariable(value="msg")String msg);
	
	@RequestMapping(value="/getAcctString",params={"hkid","email"},method=RequestMethod.GET,produces="application/json;charset=UTF-8")
	public @ResponseBody
	String getAcctString(@RequestParam String hkid, @RequestParam String email);
	
	@RequestMapping(value="/getAcctList",params={"hkid", "email"},method=RequestMethod.GET,produces="application/json;charset=UTF-8")
	public @ResponseBody
	List getAcctList(@RequestParam String hkid, @RequestParam String email);

	@RequestMapping(value="/person/{id:\\d+}",method=RequestMethod.GET,produces="application/json;charset=UTF-8")
	public @ResponseBody
	String getPerson(@PathVariable("id") int id);
}


service实现类
package test.service.impl;

import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import test.dao.GetAccountDao;
import test.service.IAcctService;

import net.sf.json.JSONArray;

@Controller
public class AcctServiceImpl implements IAcctService{
	
	 /** 日志实例 */  
    private static final Logger logger = Logger.getLogger(AcctServiceImpl.class);  

	
	public @ResponseBody
	String hello() {
		return "hello";
	}

	
	public @ResponseBody
	String say(@PathVariable(value="msg")String msg) {
		return "{\"msg\":\"you say:'"+msg+"'\"}";
	}

	
	public @ResponseBody
	String getAcctString(@RequestParam String hkid, @RequestParam String email) {
		GetAccountDao gad = new GetAccountDao();
		List<String> acctList = gad.getAccount(hkid, email);
		JSONArray json = new JSONArray();
		json = JSONArray.fromObject(acctList);
		String acctStr = json.toString();
		System.out.println(acctStr);
		return acctStr;		
	}
	
	public @ResponseBody
	List getAcctList(@RequestParam String hkid, @RequestParam String email) {
		GetAccountDao gad = new GetAccountDao();
		List<String> acctList = gad.getAccount(hkid, email);
		System.out.println(acctList);
		return acctList;		
	}

	public @ResponseBody  
	String getPerson(@PathVariable("id") int id) {
		logger.info("获取人员信息id=" +id);
		Person p = new Person();
		p.setName("tom");
		p.setAge(30);
		p.setId(id);
		
		JSONObject jo = JSONObject.fromObject(p);
		logger.info(jo);
		logger.info(jo.toString());
		return jo.toString();
	}
	
	
}

测试类
package test.client;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import org.apache.log4j.Logger;
import org.junit.Test;
import org.springframework.web.client.RestTemplate;

public class AcctClientTest {
	
	private static Logger logger = Logger.getLogger(AcctClientTest.class);
	
	@Test
	public void testHello(){
		logger.info("enter hello Method start...");
		System.out.println("enter hello Method start...");
		String url = "http://localhost:8080/testService/hello";
		RestTemplate restTemplate = new RestTemplate();
		/**
		 * 第一个参数是restful接口请求路径
		 * 第二个参数是相应的类型String.class
		 */
		String result = restTemplate.getForObject(url, String.class);
		logger.info("输出结果:"+result);
		logger.info("enter hello Method end...");
		System.out.println("enter hello Method end...");
	}
	
	
	@Test
	public void testGetAcctString(){
		logger.info("enter getAcctString Method start...");
		System.out.println("enter getAcct Method start...");
		String url="http://localhost:8080/testService/getAcctList?hkid={hkid}&email={email}";
		RestTemplate restTemplate = new RestTemplate();
		Map<String, Object> params = new HashMap<>();
		params.put("hkid", "xxxxxxxx");
	    params.put("email", "xxxxxxxx");
	    try{
	    	String result = restTemplate.getForObject(url, String.class, params);
	    	logger.info("output:" + result);
			System.out.println("output:" + result);
	    }catch(Exception e){
	    	System.out.println("error :"+ e.getMessage());
	    }    
    	logger.info("enter getAcctString Method end...");
		System.out.println("enter getAcctString Method end...");
		
	}
	
	
	@Test
	public void testGetAcctList(){
		logger.info("enter getAcctList Method start...");
		System.out.println("enter getAcct Method start...");
		String url="http://localhost:8080/testService/getAcctList?hkid={hkid}&email={email}";
		RestTemplate restTemplate = new RestTemplate();
		Map<String, Object> params = new HashMap<>();
		params.put("hkid", "xxxxxxxx");
	    params.put("email", "xxxxxxxx");
	    try{
	    	ArrayList result = restTemplate.getForObject(url, ArrayList.class, params);
	    	logger.info("output:" + result);
			System.out.println("output:" + result);
	    }catch(Exception e){
	    	System.out.println("error :"+ e.getMessage());
	    }    
    	logger.info("enter getAcctList Method end...");
		System.out.println("enter getAcctList Method end...");	
	}

	@Test
	public void testPerson(){
		logger.info("enter testPerson Method start...");
		
		String url = "http://localhost:8080/testService/person/100";
		RestTemplate rt = new RestTemplate();
		String person = rt.getForObject(url, String.class);
		logger.info("person: "+person);
		
		logger.info("enter testPerson Method end...");
	}
	
}

返回结果

getAcctList
testPerson

注意

Spring 3.x 和4.X处理JSON的一个类不一样,而这个东西又配置在xml文件中,所以编译时又无法发现,在运行时就会报无法找到合适转换类型的错误
spring3.x是org.springframework.http.converter.json.MappingJacksonHttpMessageConverter
spring4.x是org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
在使用不同版本的spring包时,需要修改testService-servlet.xml
并且替换成高版本的fastjackson包。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
(1)项目简介 这个demo很简单,是一个记账小工程。用户可以注册、修改密码,可以记账、查找记账记录等。 (2)接口介绍 用户操作相关: post /users 用户注册 post /users/login 用户登录(这里我把login当成一个名词) put /users/pwd?userId=xxx&sign=xxx 用户修改密码 delete /users?uerId=xxx&sign=xxx 删除用户 记账记录操作相关: post /records?userId=xxx&sign=xxx 增加一条记账记录 get /records/:id?userId=xxx&sign=xxx 查询一条记账记录详情 put /records/:id?userId=xxx&sign=xxx 修改一条记账记录详情 get /records?查询参数&userId=xxx&sign=xxx 分页查询记账记录 delete /records/:id?userId=xxx&sign=xxx 删除一条记账记录 其中url中带sign参数的表示该接口需要鉴权,sign必须是url中最后一个参数。具体的鉴权方法是:用户登录后,服务器生成返回一个token,然后客户端要注意保存这个token,需要鉴权的接口加上sign签名,sign=MD5(url+token),这样可以避免直接传token从而泄露了token。这里我觉得接口最好还带一个时间戳参数timestamp,然后可以在服务端比较时间差,从而避免重放攻击。而且这样还有一个好处,就是如果有人截获了我们的请求,他想伪造我们的请求则不得不改时间戳参数(因为我们在服务器端会比较时间),这样一来sign势必会改变,他是无法得知这个sign的。如果我们没有加时间戳参数的话,那么,他截获了请求url,再重发这个请求势必又是一次合法的请求。我在这里为了简单一些,就不加时间戳了,因为这在开发测试阶段实在是太麻烦了。 (3)关于redis和数据库的说明 服务端在用户登录后,生成token,并将token保存到redis中。后面在接口鉴权的时候会取出token计算签名MD5(除sign外的url+token),进行比对。 这个demo搭建了一个redis主从复制,具体可以参考:http://download.csdn.net/detail/zhutulang/9585010 数据库使用mysql,脚本在 src/main/resources/accounting.sql
以下是一个简单的 C# RESTful API 示例,它使用ASP.NET Core框架和Microsoft.EntityFrameworkCore库: ```csharp using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; // 定义一个数据模型 public class TodoItem { public int Id { get; set; } public string Name { get; set; } public bool IsComplete { get; set; } } // 定义一个数据上下文 public class TodoContext : DbContext { public TodoContext(DbContextOptions<TodoContext> options) : base(options) { } public DbSet<TodoItem> TodoItems { get; set; } } // 定义一个控制器 [Route("api/[controller]")] [ApiController] public class TodoController : ControllerBase { private readonly TodoContext _context; public TodoController(TodoContext context) { _context = context; } // GET: api/todo [HttpGet] public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems() { return await _context.TodoItems.ToListAsync(); } // GET: api/todo/5 [HttpGet("{id}")] public async Task<ActionResult<TodoItem>> GetTodoItem(int id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return todoItem; } // POST: api/todo [HttpPost] public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem item) { _context.TodoItems.Add(item); await _context.SaveChangesAsync(); return CreatedAtAction(nameof(GetTodoItem), new { id = item.Id }, item); } // PUT: api/todo/5 [HttpPut("{id}")] public async Task<IActionResult> PutTodoItem(int id, TodoItem item) { if (id != item.Id) { return BadRequest(); } _context.Entry(item).State = EntityState.Modified; await _context.SaveChangesAsync(); return NoContent(); } // DELETE: api/todo/5 [HttpDelete("{id}")] public async Task<IActionResult> DeleteTodoItem(int id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return NoContent(); } } ``` 上面的代码定义了一个名为`TodoController`的控制器,它处理对`TodoItem`数据模型的RESTful API请求。该控制器包括以下操作: - GET: api/todo - 获取所有待办事项 - GET: api/todo/{id} - 根据ID获取特定的待办事项 - POST: api/todo - 创建一个新的待办事项 - PUT: api/todo/{id} - 更新一个待办事项 - DELETE: api/todo/{id} - 删除一个待办事项 注意:这个示例只是演示了如何定义RESTful API。要让这个示例运行起来,您需要配置一个数据库连接,并根据需要更改`Startup.cs`文件中的配置选项。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值