rest
Resource representational state transfer:资源表述性状态转移。
Resource :网络中一切皆资源;
representation:表现层,数据呈现的形式,txt.、json、xml都是表现层,呈现出来是什么样的,资源的表现层一般在响应头中content-type能体现;
state transfer:状态转移,通过http的动作(get,post,put,delete,patch等)使资源的状态发生改变。
uri规范
URI规则:一般和数据库表名相同,且为复数,如:/project/v1/users。对用户的操作,数据库表user是用户的集合,故为复数。
又如:/project/v1/users/id/,获取某个用户;/project/v1/users/id/books,获取某个用户的所有书籍。
uri不出现动词,都是名词
http动作
get:获取;post:新建;delete:删除;put:更新资源全部属性;patch:更新资源部分属性。
将符合rest规范和动作的程序视为restful,本质上是种前后端分离的开发风格,一种程序的开发约束。
jersey实现restful
导入核心jar包:jersey-bundle-1.18.jar,其他jar包根据业务需要导入,如需要文件上传处理需jersey-media-multipart-2.0-m04.jar。在web.xml中添加如下配置:
<servlet>
<servlet-name>jersey</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
常用注解
@Path("service")与@Path("/service")效果一样,指定当前url路径,如:/project/api/service/test
@Context 对象注入
@GET/@POST/@DELETE/@PUT/@PATCH 方法类型
@QueryParam 获取在url中的参数
@FormParam 获取RequestBody中的数据,且此时请求的content-type:application/x-www-form-urlencode,也就是常用的表单提交方式
当参数是json方式时,只能通过JSONObject或者参数对应的实体来接收
@Produces 指定返回结果类型
@Consumes 指定请求该方法的参数类型
@Path("/service")
public class Rest {
@Context
HttpServletResponse resp;
@Context
HttpServletRequest req;
//资源信息,可获取处理请求的资源类和方法,常用在自定义注解中
@Context
ResourceInfo resourceInfo;
//访问地址信息
@Context
UriInfo uriInfo;
/**
* @QueryParam 只能获取url中的参数(不管是get还是post)
* @param name
* @param age
* @return
*/
@Path("/testGet")
@POST
@Produces(MediaType.TEXT_PLAIN)
public String testUriGet(@QueryParam("name") String name,@QueryParam("age") int age){
User u = new User();
u.setAge(age);
u.setName(name);
return JSONObject.fromObject(u).toString();
}
/**
* @FormParam 只能获取content-type为application/x-www-form-urlencoded时的requestbody中的数据
*/
@Path("testPost")
@POST
public String testUriPost(@FormParam("name") String name,@FormParam("age") int age){
User u = new User();
u.setAge(age);
u.setName(name);
return JSONObject.fromObject(u).toString();
}
/**
* 当RequestBody中的content-type为application/json时,@FormParam将无法获取请求体中的参数,
* 请求的json数据使用JSONObject接收或直接用对应的实体接收
* @param w
* @return
*/
@Path("/test")
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes("application/json")
public User test(JSONObject w){
// resp.setContentType("text/plain");
// JSONObject u = w;
User u = new User();
u.setAge(w.getInt("age"));
u.setName(w.getString("name"));
return u;
}
/**
* 当url中的参数不确定时,@QueryParam不好指定入参,使用@Context UriInfo info获取url中的参数,
* @Context 获取的参数范围仅对应@QueryParam能获取到的参数,
* req.getParameter("name");也是获取不到RequestBody里的参数的
* @param info
* @return
*/
@Path("testContext")
@POST
public String testUriContext(@Context UriInfo info){
User u = new User();
String name = req.getParameter("name");
// u.setAge(age);
// u.setName(name);
MultivaluedMap<String,String> queryParam = info.getQueryParameters();
MultivaluedMap<String,String> pathParam = info.getPathParameters();
return JSONObject.fromObject(u).toString();
}
@Path("testContext")
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
public void testUpload() throws Exception{
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
// 上传配置
final int MEMORY_THRESHOLD = 1024 * 1024 * 3; // 3MB
final int MAX_FILE_SIZE = 1024 * 1024 * 40; // 40MB
final int MAX_REQUEST_SIZE = 1024 * 1024 * 50; // 50MB
// 设置内存临界值 - 超过后将产生临时文件并存储于临时目录中
factory.setSizeThreshold(MEMORY_THRESHOLD);
// 设置临时存储目录
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
// 设置最大文件上传值
upload.setFileSizeMax(MAX_FILE_SIZE);
// 设置最大请求值 (包含文件和表单数据)
upload.setSizeMax(MAX_REQUEST_SIZE);
// 中文处理
upload.setHeaderEncoding("UTF-8");
Map<String, String> parameterMap = new HashMap<String, String>();
@SuppressWarnings("unchecked")
List<FileItem> formItems = upload.parseRequest(req);
if (formItems != null && formItems.size() > 0) {
// 迭代表单数据
for (FileItem item : formItems) {
// 处理表单中的字段
if (item.isFormField()) {
parameterMap.put(item.getFieldName(), item.getString());
}
if (!item.isFormField()) {
String fileName = new File(item.getName()).getName();
Long fileSize = item.getSize();
String filePath = "filePath" + File.separator + fileName;
File storeFile = new File(filePath);
// 在控制台输出文件的上传路径
// System.out.println(filePath);
// 保存文件到硬盘
item.write(storeFile);
}
}
}
}
}
SpringMVC实现restful
主要jar包(spring在4.0之后才支持@RestController注解)
web.xml配置
<servlet>
<servlet-name>chen</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 当没有指定mvc配置文件时,默认去WEB-INF下寻找名为chen-servlet.xml文件, 在FrameworkServlet中
org.springframework.web.context.ConfigurableWebApplicationContext 来生成文件中定义的bean -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:muchen1-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>chen</servlet-name>
<url-pattern>/interface/*</url-pattern>
<!-- 跟随容器启动 -->
<load-on-startup>1</load-on-startup>
</servlet-mapping>
SpringMvc配置
<!-- 注解扫描路径 -->
<context:component-scan base-package="com.muchen"></context:component-scan>
<!-- 注册注解bean -->
<mvc:annotation-driven/>
<!-- 文件上传的处理 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8"></property>
<property name="maxInMemorySize" value="-1"></property>
<property name="maxUploadSize" value="10240000"></property>
</bean>
主方法Controller
常用注解
@RestController 为 @Controller + @ResponseBody
@ResponseBody 将返回数据转为json串写入response缓冲区,不同版本有的只能转化json形式的字符串,有的能转化JSONObject(高版本MVC支持)
@RequestMapping 相当于 jersey 的 @Path
@GetMapping、@PostMapping 相当于指定方法类型为get或post...的@RequestMapping
@PathVariable 获取url中的参数
@RequestParam 用于获取1:url中参数;2:content-type为application/x-www-form-urlencoded的表单参数
当相于:request.getParameter(“name”)
@RequestBody 处理请求参数类型为json格式的情况,后台使用 @RequestBody 来接收请求体中的json参数,
后台接收赋值方式有3种:
1. 字符串接收 @RequestBody String o
2. JSONObject对象接收 @RequestBody JSONObject o
3. 实体接收 @RequestBody User u
还有一种就是通过request.getInputStream()或request.getReader()流的方式获取,或像jersey中转化为List<FileItem>后再进行处理
@RestController
@RequestMapping("/restful")
public class MvcRest {
/**
* @GetMapping 指定方法类型get
* @param res
* @param resp
* @throws Exception
*/
@GetMapping("testGet")
public void testGet(HttpServletRequest res, HttpServletResponse resp) throws Exception {
String pa = res.getParameter("pa");
resp.getWriter().print(pa);
}
/**@PostMapping 指定方法类型post
* @ResponseBody 将返回结果转换成json串写入response缓冲区
* @param res
* @return
*/
@ResponseBody
@PostMapping("/testPost")
public String testPost(HttpServletRequest res){
Map<String,String> map = new HashMap<String,String>();
map.put("name", res.getParameter("name"));
map.put("age", res.getParameter("age"));
JSONObject o = JSONObject.fromObject(map);
return o.toString();
}
/**
* 无@ResponseBody时,上一方法相当于此方法
* @param res
* @param resp
* @throws IOException
*/
@RequestMapping("testPost1")
public void testPost(HttpServletRequest res,HttpServletResponse resp) throws IOException{
Map<String,String> map = new HashMap<String,String>();
map.put("name", res.getParameter("name"));
map.put("age", res.getParameter("age"));
JSONObject o = JSONObject.fromObject(map);
resp.getWriter().print(o);
}
/**
* url: http://110.237.199.148:7070/muweb/interface/restful/testUrl/zhangsan/18
* @PathVariable 获取url中的参数
* @param name
* @param age
* @return
*/
@RequestMapping("/testUrl/{name}/{age}")
public String testGetPath(@PathVariable("name") String name,@PathVariable("age") int age){
Map<String,Object> map = new HashMap<String,Object>();
map.put("name", name);
map.put("age", age);
JSONObject o = JSONObject.fromObject(map);
return o.toString();
}
/**
* @RequestParam 用于获取1:url中参数;2:content-type为application/x-www-form-urlencoded的表单参数
* @param name
* @param age
* @return
*/
@RequestMapping("/testUrl1")
public String testGetPath1(@RequestParam("name") String name, @RequestParam("age") int age){
Map<String,Object> map = new HashMap<String,Object>();
map.put("name", name);
map.put("age", age);
// String json = JSON.toJSONString(map);
return "";
}
/**
* consumes 指定方法参数类型
* 相当于配置了 headers="Content-Type=application/json"
* produces 指定方法返回参数类型
* 相当于响应头中添加了content-type=application/json 和 请求头中 headers="accept=application/json"
* @param o
* @return
*/
@RequestMapping(value="jsonBody",consumes="application/json",produces="aplication/json")
public String testBody(@RequestBody String o){
System.out.println(o.toString());
JSONObject j = JSONObject.fromObject(o);
System.out.println(j.toString());
return o.toString();
}
/**
* headers 指定请求中必须带有的头信息
* @param o
* @return
*/
@RequestMapping(value="jsonBody0",headers="accept=application/json")
public String testBody0(@RequestBody JSONObject o){
System.out.println(o.toString());
JSONObject j = JSONObject.fromObject(o);
System.out.println(j.toString());
return o.toString();
}
/**
* @RequestBody 处理请求参数类型为json格式的情况,后台使用 @RequestBody 来接收请求体中的json参数,
* 后台接收赋值方式有3种:
* 1. 字符串接收 @RequestBody String o
* 2. JSONObject对象接收 @RequestBody JSONObject o
* 3. 实体接收 @RequestBody User u
* @param u
* @return
*/
@RequestMapping("jsonBody1")
public String testBody1(@RequestBody User u){
System.out.println(u.toString());
return u.toString();
}
/**
* MultipartFile paramName 文件上传,paramName必须与前端保持一致
* @param file
* @param request
* @return
* @throws Exception
*/
@RequestMapping("upload")
public String upload(MultipartFile file,HttpServletRequest request) throws Exception{
String fileName = file.getOriginalFilename();
String name = file.getName();// 文件类型
System.out.println(fileName);
System.out.println(name);
String path = request.getServletContext().getRealPath("/") + fileName;
// 文件复制保存
file.transferTo(new File(path));
// InputStream in = file.getInputStream();
// OutputStream out = new FileOutputStream(path);
// byte[] b = new byte[1024];
// int i = 0;
// while((i=in.read(b))!=-1){
// out.write(b, 0, i);
// }
// in.close();
// out.close();
return null;
}
}