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 {@ContextHttpServletResponse resp;@ContextHttpServletRequest req;//资源信息,可获取处理请求的资源类和方法,常用在自定义注解中@ContextResourceInfo resourceInfo;//访问地址信息@ContextUriInfo 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")@POSTpublic 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")@POSTpublic 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; // 3MBfinal int MAX_FILE_SIZE = 1024 * 1024 * 40; // 40MBfinal 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;}
}