Web基础之使用URL访问资源
2016-11-07 18:26
344 查看
前言
在一些框架中经常看到使用URL访问项目中的资源,这篇文章简单的梳理了一下这个URL的相关内容正文
URL(Uniform Resource Locator)中文名为统一资源定位符具体格式如下
protocol://host:port/path?query#ref
这里protocol可以是下面的内容:HTTP, HTTPS, FTP, 和File;port 为端口号;path为文件路径及文件名
使用URL获取文件系统资源
//context是ServletContext String absolutePath = context.getRealPath("/WEB-INF/classes/utf8.txt"); URL url = new URL("file",null,absolutePath); //absoltePath是普通的文件格式 URLConnection connection = url.openConnection(); InputStream is = connection.getInputStream(); FileUtil.readFileWithInputStream(is, "utf8");
需要注意几点地方
getRealPath获取的是项目中的指定资源在文件系统中的完整路径,以“/”开头表示Web项目的根目录(http://host:port/webName 下的目录(URL)
当前项目用maven多模块构建,读取的资源在一个maven模块中,也就是说部署到tomcat时,资源是在jar包,所以上面指定的路径会找不到,解决办法是获取jar的URL路径(用classloader加载获取jar的URL),然后使用JarURLConnection读取,或者将资源移动到maven项目的webapp所在的模块的src/main/resources中,在部署时会将资源放到classpath下
url.openConnection()的实例可能是FileURLConnection,HttpURLConnection,JarURLConnection还有其它几种,这里协议是file,所以返回的是FileURLConnection的实例,但是FileURLConnection这个类在java中不能找到,所以使用父类来引用,可以完成简单的操作
URL url = new URL(path)这里path必须是URL协议格式,如果是普通的文件路径,那么可以按照上面的3个参数构造函数创建对象也可以使用
new File(resourceLocation).toURI().toURL()返回URL
获取jar包的URL
使用JarFile来完成jar操作
public static void obtainJarFile(String path) { try { JarFile jarFile = new JarFile(path); //jar包路径,创建一个jarFile对象 System.out.println(String.format("%s", jarFile.getName())); Enumeration<JarEntry> entrys = jarFile.entries();//jarFile提供操作jar包的方法 while(entrys.hasMoreElements()) { //会从上到下,从外到里一个一个得到目录以及目录里面的文件 JarEntry entry = entrys.nextElement(); System.out.println(String.format("-%s",entry.getName())); } } catch (IOException e) { e.printStackTrace(); } }
需要注意的几点:
path是jar包所在的路径,可以是完整的文件系统路径,也可以是相对于工程的相对路径
枚举会将所有jar包的文件一一列举出来,包括目录和文件,如果只对文件感兴趣可以
entry.isDirectory();来判断
使用classLoader来完成对jar的操作
需求:运行在tomcat容器中的项目,需要获取classpath下的config目录资源(包括WEB-INF/lib中jar里面的config资源,也包括WEB-INF/classes中的config目录的资源)可行性:上面的需求通过分析发现可以用加载器加载资源来实现:因为web的加载器(WebAppClassLoader)会加载WEB-INF/lib和WEB-INF/classes目录下资源,只要传递相对于上面两个根目录的相对路径就能获取到需要的资源
抽象:将上面的业务抽象成算法如下
得到当前的ClassLoader,因为运行在Tomcat容器中,所以是Tomcat提供的加载器
通过外面给予的相对于加载器classpath的相对路径加载资源,使用getResources(path)来完成
得到资源的URL可能是file:这种格式也可能是jar:格式,如果是file则将URL转成磁盘的文件系统路径,然后用File来读取资源。如果是jar则使用JarURLConnection 来获取JarFile来操作
如果是jar:的URL,先获取jar包下的所有路径,在通过一一对比过滤得到指定目录下的文件,然后使用URL的openStream操作流读取资源
如果是file:的URL,先将URL转成URI然后得到磁盘文件路径,使用File来读取指定目录下的文件资源
代码示例
public static void obtainJarFileWithClassLoader(String path) { try { ClassLoader loader = ClassLoaderUtil.getCurrentClassLoader(); Enumeration<URL> urls = loader.getResources(path); while(urls.hasMoreElements()) { URL url = urls.nextElement(); URLConnection connection = url.openConnection(); //使用父类URLConnection可以做一些简单的操作, //但是这里要做jar复杂一点的操作,明显不够用,所以转成JarURLConnection if(connection instanceof JarURLConnection) { JarURLConnection jarConn = (JarURLConnection) connection; URL jarPath = jarConn.getJarFileURL();//获取jar包所在的路径 System.out.println(String.format("jar包在文件系统中的路径:%s", jarPath.toExternalForm())); //toExternalForm作用URL转成String JarFile jarFile = jarConn.getJarFile(); //获取jar包 JarEntry jarEntry = jarConn.getJarEntry(); //获取当前连接目录的路径 System.out.println(String.format("当前连接目录在jar的相对位置%s", jarEntry.getName())); //获取jar包下的文件,并加载资源 Enumeration<JarEntry> entrys = jarFile.entries(); while(entrys.hasMoreElements()) { JarEntry entry = entrys.nextElement(); if(!entry.isDirectory()) { String relativePath = entry.getName();//文件在jar下的路径 if(relativePath.startsWith(jarEntry.getName())) { //只获取config目录下的资源,url包含了config目录,所以要将relativePath中的config截取掉 URL perResource = new URL(url,relativePath.substring(jarEntry.getName().length())); //使用基地址和相对URL创建 //使用URL加载资源 InputStream is = perResource.openStream(); FileUtil.readFileWithInputStream(is, "utf8"); } } } }else { if(url.getProtocol().startsWith("file")) { try { //参考:http://blog.csdn.net/ocean1010/article/details/6114222 URI uri = new URI(url.getFile().replace(" ", "%20"));//将请求路径中的空格替换成%20 String resources = uri.getSchemeSpecificPart();//获取文件系统的路径,也就是将URL转成文件系统路径 File file = new File(resources); FileUtil.scanFileSystemDirectory(file,""); //显示这个目录结构 } catch (URISyntaxException e) { e.printStackTrace(); } } } } } catch (IOException e) { e.printStackTrace(); } }
ignore
使用JarURLConnection得到当前jar文件:jarConn.getJarFile()得到jar包的URL路径:jarConn.getJarFileURL()或者jarConn.getJarFile().getName()
得到当前相对路径(相对于加载器默认加载目录)下的目录,如外面传递的是“config/”它相对于WEB-INF/lib和WEB-INF/classes目录。JarEntry jarEntry = jarConn.getJarEntry(); 得到结果就是“config/”
public URL(URL context, String url) 使用基地址和相对URL创建。context是已经知道的URL,在context后面连接上指定的相对路径
将URL转成文件系统路径:先转成URI,再使用getSchemeSpecificPart获取文件系统路径
加载jar包下的class
项目使用maven多模块构建,因此每个模块会打成jar包放到WEB-INF/lib下面,那么如何加载jar下面的class呢?这里需要用到加载器,上面讲过了WEB的加载器会加载WEB-INF/lib下的资源,因此这里只要用WebappClassLoader加载器加载资源即可
/** - 加载jar包下的class - @param path org.easyutil.http.HttpClientUtil - @param clazz HttpClientUtil.class */ public static void loadJarClass(String path ,Class<?> clazz) { ClassLoader loader = ClassLoaderUtil.getCurrentClassLoader(); try { //loader加载器和加载当前类FileUtil的加载器相同,所以这里可以赋值 //参考:http://blog.sina.com.cn/s/blog_56d8ea90010127ks.html clazz = loader.loadClass(path); System.out.println(clazz.getName()); } catch (ClassNotFoundException e) { e.printStackTrace(); } }
ignore
Class<?> clazz = loader.loadClass(path);必须保证加载左右两边的两个加载器相同。代码在(编译?执行?)时用当前加载器(从线程中获取?)加载Class尖括号中的类型的class,而后面loader又是我一个新的加载器,因此需要保证这两个加载器必须相同才不会报异常
只要选择对的加载器,就能加载指定目录下的资源
相关文章推荐
- 通过URL,使用HttpURLConnection进行请求/响应,访问web服务器图片等资源。异常报错
- 疯狂安卓实训 第13.2.2讲 使用HttpURLConnection访问网络资源
- 疯狂安卓实训 第13.2.1讲 使用URL和URLConnection访问网络资源
- Android开发之使用URL访问网络资源
- 【Java.Web】JSP —— 语法基础 —— 选择在web.xml配置访问JSP URL
- URL资源跨域访问 跨域使用session信息
- 使用HttpURLConnection访问web页面
- Android开发之使用URL访问网络资源
- [error handle][java web]Spring MVC在类上使用@RequestMapping后对静态资源的访问问题
- 使用HttpURLConnection访问网络资源,返回字符串内容
- 使用servlet 3.0 新特性 @WebServlet(urlPatterns = "/brainT") 访问 url,服务器报404错误
- 使用URL访问网络资源
- 简单使用URLConnection、HttpURLConnection和HttpClient访问网络资源
- Java 网络编程(三) 创建和使用URL访问网络上的资源
- Java 网络编程(三) 创建和使用URL访问网络上的资源
- java SE基础(URL访问网络资源)
- 使用SDWebImage的时候,从服务器请求回来的头像URL没有变化,但图片资源已经变。需要展示最新图片
- 利用WebResource.axd通过一个URL来访问装配件的内置资源
- Android学习--使用url访问网络资源
- 简单使用URLConnection、HttpURLConnection和HttpClient访问网络资源