框架的概念及用反射技术开发框架的原理<br/>getResourceAsStream用法详解

本文介绍了一种利用配置文件和反射机制实现动态加载类的方法。通过具体的Java代码示例展示了如何从配置文件中读取类名,并使用反射创建其实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

反射的作用—>实现框架的功能

框架-用户类-工具类:框架与工具类有区别,工具类被用户的类调用,而框架则是调用用户提供的类。

框架要解决的核心问题:框架如何调用未知的类:通过反射来实现

综合案例: 使用配置文件读取调用类的名字

工程目录

 

ReflectTest测试类

复制代码
1 package com.ljq.test; 2 3 import java.io.FileInputStream; 4 import java.io.InputStream; 5 import java.util.Collection; 6 import java.util.Properties; 7 8  /** 9 * 使用配置文件读取调用者的类 10 * 11 * @author jiqinlin 12 * 13 */ 14  public class ReflectTest { 15 public static void main(String[] args) throws Exception{ 16 //使用绝对路径,否则无法读取config.properties 17 //InputStream inStream=new FileInputStream("F:\\android\\test\\src\\com\\ljq\\test\\resource\\config.properties"); 18 19 //ReflectTest.class.getClassLoader().getResourceAsStream(String path): 默认则是从ClassPath根下获取,path不能以’/'开头,最终是由ClassLoader获取资源。 20 //InputStream inStream = ReflectTest.class.getClassLoader().getResourceAsStream("com/ljq/test/resource/config.properties"); 21 22 // ReflectTest.class.getResourceAsStream(String path): path不以’/'开头时默认是从此类所在的包下取资源,以’/'开头则是从ClassPath根下获取。 23 //其只是通过path构造一个绝对路径,最终还是由ClassLoader获取资源。 24 //InputStream inStream = ReflectTest.class.getResourceAsStream("/com/ljq/test/resource/config.properties"); 25 26 //config.properties配置文件所在目录是ReflectTest类所在子目录,才可以;否则报空指针异常 27   InputStream inStream = ReflectTest.class.getResourceAsStream("resource/config.properties"); 28 29 Properties props=new Properties(); 30 props.load(inStream); 31 inStream.close(); 32 33 String className=props.getProperty("className"); 34 Collection collection=(Collection)Class.forName(className).newInstance(); 35 collection.add("123"); 36 System.out.println("size="+collection.size()); //size=1 37   } 38 }
复制代码

config.properties配置文件

className=java.util.HashSet

getResourceAsStream用法大致有以下几种:

复制代码
1 第一:要加载的文件和.class文件在同一目录下,例如:com.ljq.test目录下有类ReflectTest.class,同时有资源文件config.properties 2 3 那么,应该有如下代码: 4 ReflectTest.class.getResourceAsStream("config.properties"); 5 6 第二:在ReflectTest.class目录的子目录下,例如:com.ljq.test下有类ReflectTest.class,同时在com.ljq.test.resource目录下有资源文件config.properties 7 8 那么,应该有如下代码: 9 ReflectTest.class.getResourceAsStream("resource/config.properties"); 10 11 第三:不在ReflectTest.class目录下,也不在子目录下,例如:com.ljq.test下有类ReflectTest.class ,同时在com.ljq.resource目录下有资源文件config.properties 12 13 那么,应该有如下代码: 14 ReflectTest.class.getResourceAsStream("/com/ljq/resource/config.properties"); 15 16 总结一下,可能只是两种写法 17 18 第一:前面有 “/” ,“/”代表了工程的根目录,例如工程名叫做test,“/”代表了test 19 ReflectTest.class.getResourceAsStream("/com/ljq/resource/config.properties"); 20 21 第二:前面没有 “/” ,代表当前类的目录 22 ReflectTest.class.getResourceAsStream("config.properties"); 23 ReflectTest.class.getResourceAsStream("resource/config.properties"); 24 25 最后,总结 26 getResourceAsStream读取的文件路径只局限在工程的源文件夹中,包括在工程src根目录下,以及类包里面任何位置,但是如果配置文件路径是在除了源文件夹之外的其他文件夹中时,该方法是用不了的。
复制代码
<think>嗯,用户的问题是关于如何将HTML字符串转换为PDF并存储到OSS中,使用Java和ByteArrayOutputStream。首先,我需要回顾之前的对话历史。用户之前已经得到了一个详细的代码示例,包括生成PDF到内存流和上传到OSS的步骤。现在用户再次提问,可能需要更具体的实现细节,或者对某些部分有疑问。 用户提到HTML包含表格样式和内容,这可能意味着需要处理CSS样式,特别是表格的布局,比如边框、背景色等。之前的回答中提到了使用openhtmltopdf,这个库支持CSS,但用户可能需要更详细的指导,比如如何确保表格样式正确渲染。此外,用户可能需要处理中文字体的问题,这在之前的回答中也有涉及,比如显式指定字体。 接下来,用户需要使用ByteArrayOutputStream,避免生成临时文件,这对性能有好处,特别是在云环境中。我需要确认之前的代码示例是否正确使用了这个流,并且是否覆盖了所有必要的配置,比如字体和资源加载。 上传到OSS的部分,用户可能需要了解如何配置OSS客户端,处理大文件,或者设置权限。之前的回答提到了分片上传和异常处理,这些是否足够详细?是否需要补充更多关于阿里云OSS SDK的使用细节? 然后,用户的问题可能涉及到实际应用中的常见问题,比如内存溢出、中文乱码、CSS支持不完全等。需要确保回答中包含这些问题的解决方案,比如如何指定中文字体,处理外部CSS/JS资源,或者优化内存使用。 另外,用户可能希望代码示例更完整,包括依赖管理,比如Maven或Gradle的配置,因为使用openhtmltopdf需要特定的库。之前的回答可能没有提到这些,需要补充。 最后,用户可能需要验证PDF生成是否正确,以及上传后的完整性。可能需要建议使用MD5校验或OSS的自动校验功能。同时,生成预签名URL也是一个相关的问题,之前的回答中有提到,但可能需要更详细的步骤。 总结一下,用户的需求是明确的,但需要更详细的步骤和解决潜在问题的方案。需要确保回答覆盖HTML到PDF的转换(特别是表格样式)、内存流处理、OSS上传、依赖管理、常见问题解决以及完整性验证。同时,参考之前的回答,避免重复,但补充可能遗漏的细节。</think>### 分步实现 HTML转PDF并上传至OSS --- #### 一、环境准备(Maven依赖) ```xml <!-- OpenHTMLToPDF核心库 --> <dependency> <groupId>com.openhtmltopdf</groupId> <artifactId>openhtmltopdf-core</artifactId> <version>1.1.6</version> </dependency> <!-- PDFBox适配 --> <dependency> <groupId>com.openhtmltopdf</groupId> <artifactId>openhtmltopdf-pdfbox</artifactId> <version>1.1.6</version> </dependency> <!-- 阿里云OSS SDK --> <dependency> <groupId>com.aliyun.oss</groupId> <artifactId>aliyun-sdk-oss</artifactId> <version>3.15.1</version> </dependency> ``` --- #### 二、HTML表格样式处理要点 1. **CSS打印优化** ```html <style> table { width: 100%; border-collapse: collapse; margin: 15px 0; } td, th { border: 1px solid #ddd; padding: 8px; font-family: 'SimSun'; /* 显式声明中文字体 */ } tr:nth-child(even) { background-color: #f8f9fa; } @media print { .no-print { display: none } /* 打印隐藏元素 */ } </style> ``` 2. **表格结构示例** ```html <table> <thead> <tr> <th>订单号</th> <th>客户名称</th> <th>金额</th> </tr> </thead> <tbody> <tr> <td>202308001</td> <td>张三</td> <td>¥1,200.00</td> </tr> </tbody> </table> ``` --- #### 三、完整Java实现代码 ```java import com.aliyun.oss.OSS; import com.aliyun.oss.OSSClientBuilder; import org.jsoup.Jsoup; import org.jsoup.helper.W3CDom; import org.jsoup.nodes.Document; import org.openhtmltopdf.pdfboxout.PdfRendererBuilder; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; public class HtmlToPdfOss { // OSS配置 private static final String ENDPOINT = "oss-cn-hangzhou.aliyuncs.com"; private static final String ACCESS_KEY = "AK**************"; private static final String SECRET_KEY = "SK****************"; private static final String BUCKET_NAME = "my-pdf-bucket"; public static void main(String[] args) { String htmlContent = "<html><body>...包含表格的HTML内容...</body></html>"; try { // 1. HTML转PDF字节流 byte[] pdfBytes = convertHtmlToPdf(htmlContent); // 2. 上传到OSS uploadToOss(pdfBytes, "report.pdf"); System.out.println("PDF生成并上传成功"); } catch (IOException e) { e.printStackTrace(); } } private static byte[] convertHtmlToPdf(String html) throws IOException { try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { // 使用JSoup解析HTML Document jsoupDoc = Jsoup.parse(html); jsoupDoc.outputSettings().syntax(Document.OutputSettings.Syntax.xml); // 强制XML模式 // 转换为W3C Document W3CDom w3cDom = new W3CDom(); org.w3c.dom.Document w3cDoc = w3cDom.fromJsoup(jsoupDoc); // PDF生成配置 PdfRendererBuilder builder = new PdfRendererBuilder(); builder.useFastMode() .withW3cDocument(w3cDoc, null) .useFont(new File("fonts/simsun.ttf"), "SimSun") // 必须加载字体 .toStream(baos) .run(); return baos.toByteArray(); } } private static void uploadToOss(byte[] data, String objectKey) { OSS ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY, SECRET_KEY); try { ossClient.putObject(BUCKET_NAME, objectKey, new ByteArrayInputStream(data)); } finally { ossClient.shutdown(); } } } ``` --- #### 四、关键技术细节 1. **中文字体解决方案** - 下载字体文件(如simsun.ttf)到项目`resources/fonts`目录 - 代码中显式注册字体: ```java builder.useFont(getClass().getResourceAsStream("/fonts/simsun.ttf"), "SimSun", 700, FontStyle.NORMAL, true); ``` - CSS中必须声明匹配的字体族: ```css body { font-family: SimSun; } ``` 2. **表格边框渲染优化** - 使用`border-collapse: collapse`避免虚线间隙 - 添加打印媒体查询保障分页效果: ```css @media print { table { page-break-inside: avoid } tr { page-break-inside: avoid } } ``` 3. **内存控制技巧** - 限制单个PDF最大尺寸: ```java builder.usePdfUaAccessbility(false) // 关闭UA特性节省内存 .usePdfAConformance(PdfRendererBuilder.PdfAConformance.NONE); ``` - 启用对象池复用: ```java PdfBoxFontResolver fontResolver = new PdfBoxFontResolver(); builder.useFontResolver(fontResolver); // 复用字体解析实例 ``` --- #### 五、验证与调试 1. **本地文件校验** ```java // 生成后立即保存到本地检查 Files.write(Paths.get("debug.pdf"), pdfBytes); ``` 2. **OSS元数据验证** ```java ObjectMetadata meta = ossClient.getObjectMetadata(BUCKET_NAME, "report.pdf"); System.out.println("文件大小: " + meta.getContentLength() + " bytes"); System.out.println("MD5校验: " + meta.getContentMD5()); ``` 3. **样式调试技巧** ```html <!-- 添加调试边界 --> <div style="border: 1px solid red; margin: 5px"> ... </div> ``` --- ### 相关问题 1. 如何处理HTML中的外部CSS/JS文件引用? 2. 如何为OSS中的PDF文件设置访问权限策略? 3. 如何实现PDF生成进度监控?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值