MyRest,自己编写的REST接口,类似SpringMVC

废话

使用过RESTful风格访问资源(要获取的数据)的我想大多都知道有种方式是使用SpringMVC(我做的一个项目中使用的是Restlet,不过个人感觉还是SpringMVC方便)。
虽然目前可用的RESTful框架提供的REST风格资源访问方式已经很适用了。但是本人始终觉得自己写的东西扩展性高,而且有助于理解其他类似框架的结构和中心思想,即使自己的东西BUG多些,但是如果需要一些“隔路”的url访问资源,那么还是很容易实现的。比如说: /rest/hash_{参数}(当然好像也没有这么用的,给自己找个台阶)。

正文

MyRest(我的项目就叫这个名字)实现RESTful风格的访问方式使用的技术如下:

  • Servlet、反射、自定义注解、好像没了、是的,没有了。

实现过程:

  • 创建一个Servlet(当然你得先创建一个WEB工程)

  • 在web.xml的<web-app>中配上这个servlet
    <servlet>
    	<servlet-name>MyRest</servlet-name>
    	<servlet-class>gemu.rest.servlet.MyRestServlet</servlet-class>
    	<init-param>
    		<param-name></param-name>
    		<param-value></param-value>
    	</init-param>
    </servlet>
    <servlet-mapping>
    	<servlet-name>MyRest</servlet-name>
    	<url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

  • 编写自定义的注解(这个注解的注解啥意思,我给忘了,以后补上吧)
    /**
     * URL路径
     * @author Gemu
     * @version	1.0 
     * @date Aug 9, 2015 7:02:09 PM
     */
    
    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface MyUrl {
    
    	// 参数格式 /**/*@param@*  其中两个@之间的是参数
    	String value();
    	
    	String method() default "GET";
    	
    	ReturnType type() default ReturnType.STRING;
    	
    }

  • 写个枚举,用作表示返回值。这里我就写了3个。返回字符串、返回文件、返回JSON对象。
    /**
     * 返回值类型
     * @author Gemu
     * @version	Nov 17, 2015 10:10:59 AM
     */
    public enum ReturnType {
    	
    	STRING,TEXT("text/plain"),JSON("application/json; charset=utf-8"); //TODO 添加其他格式
    	
    	private String value;
    
    	
    	private ReturnType() {
    	}
    
    	private ReturnType(String value) {
    		this.value = value;
    	}
    
    	public String getValue() {
    		return value;
    	}
    
    	public void setValue(String value) {
    		this.value = value;
    	}
    	
    }
    


  • 都写好了就要写个资源文件了,也就是相当于那个什么层,就是与前端进行数据交互的那层,我不是不知道那层叫什么,只是说的通俗点儿没啥不好的。
    @MyUrl("/hello")
    public class HelloResource {
    
    	// 还是给你个实例URL吧! http://localhost:8080/MyRest2/rest/hello/say/idabc1-hash!abc2test/!abc3$abc4/hello
    	@MyUrl(value="/say/id@param1@-hash!@param2@test/!@param3@$@param4@/hello", type=ReturnType.STRING)
    	public String sayHello(MyRestParams paramsObj) {
    		System.out.println(paramsObj.getParams());
    		return "hello : " + paramsObj;
    	}
    
    	@MyUrl(value="/download", type=ReturnType.TEXT)
    	private File downLoad() {
    		return new File("F:/1.json");
    	}
    
    	@MyUrl(value="/getJson/@op@", type=ReturnType.JSON)
    	private String getJSON(MyRestParams paramsObj) {
    		System.out.println(paramsObj.getParams().get("op"));
    		JSONObject obj = new JSONObject();
    		JSONArray arr = new JSONArray();
    		obj.put("key", "demo1");
    		for(int i = 0; i < 10; i ++) {
    			arr.add("value" + i);
    		}
    		obj.put("value", arr);
    		return obj.toString();
    	}
    	
    }


在加载Servlet的时候,需要在init()方法中初始化一些内容。一些内容:解析得到项目中的所有类,并反射获取其对应的MyUrl注解。代码如下:

<span style="white-space:pre">	</span>@Override
	public void init() throws ServletException {
		List<String> clazzNames = new ArrayList<String>();
		String path = Thread.currentThread().getContextClassLoader()
				.getResource("").getPath();
		path = path.substring(1) + pkg.replace(".", File.separator);
		try {
			path = URLDecoder.decode(path, "utf-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		File file = new File(path);
		if (file.isDirectory()) {
			File[] fileObjs = file.listFiles();
			List<File> fileList = new ArrayList<File>();
			for (File f : fileObjs) {
				fileList.add(f);
			}
			// 广度遍历文件目录(减少内存开销,参见:http://blog.csdn.net/gemuandyou/article/details/44082001)
			while (fileList != null && !fileList.isEmpty()) {
				List<File> tmp = new ArrayList<File>();
				for (File currFile : fileList) {
					if (currFile.isDirectory()) {
						for (File subFile : currFile.listFiles()) {
							tmp.add(subFile);
						}
					} else {
						String fileName = currFile.getAbsolutePath();
						if (fileName.endsWith(".class")) {
							clazzNames.add(getClassQualifiedName(fileName));
						}
					}
				}
				// 为fileList赋新值,执行下一层的遍历
				fileList = tmp;
			}
		} else {
			clazzNames.add(file.getName());
		}
		for (String clazzName : clazzNames) {
			try {
				Class<?> clazz = Class.forName(clazzName);
				MyUrl myAnno = clazz.getAnnotation(MyUrl.class);
				if (myAnno != null) // 过滤获取MyUrl注释文件
					url_class_mapping.put(myAnno, clazz);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
	}

最后一步就是在Servlet的service中拦截请求的URL然后解析,看看和哪个类的MyUrl注解匹配。这个挺麻烦的,下次写吧,打局Dota2。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值