继上一篇博客--javaweb通过接口来实现多个文件压缩和下载(包括单文件下载,多文件批量下载)

通过动态分配地址来提升javaweb文件下载接口的其兼容性和可扩展性:

(上篇博文地址:https://blog.csdn.net/weixin_37766296/article/details/80044000)


log4j.properties 文件:

log4j.rootLogger = debug,stdout,D,Elog4j.logger.java.sql.ResultSet=INFOlog4j.logger.java.sql.apache=INFOlog4j.logger.java.sql.Connnection=DEGUGlog4j.logger.java.sql.Statement=DEGUGlog4j.logger.java.sql.PreparedStatement=DEGUGlog4j.appender.D = org.apache.log4j.DailyRollingFileAppenderlog4j.appender.D.File = log4j.appender.D.Append = truelog4j.appender.D.Threshold = DEBUG log4j.appender.D.layout = org.apache.log4j.PatternLayoutlog4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%nlog4j.appender.E = org.apache.log4j.DailyRollingFileAppenderlog4j.appender.E.File = log4j.appender.E.Append = truelog4j.appender.E.Threshold = ERROR log4j.appender.E.layout = org.apache.log4j.PatternLayoutlog4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n 

你会发现:

log4j.appender.D.File =

这里是空的,不急,容我慢慢解释。

上面是日志文件的配置。下面是web.xml文件的配置:

	<!-- log4j文件的配置 (千万要注意的是下面的classes记得加上去,虽然工程目录可能没有,但是实际目录可能是有的)-->
<servlet>    <servlet-name>lo4jInit</servlet-name>    ()<servlet-class>com.fx.init.Lo4jInit</servlet-class>    (这里要慎重,servlet类名:由package+class名组成)<init-param>    <param-name>log4j_init_path</param-name>           (这里是用来初始化的一些参数,在init()方法中通过getInitParameter()方法获得)<param-value>WEB-INF\classes\log4j.properties</param-value>   (跟上面一个参数匹配,类似于一对键值对) </init-param>      <load-on-startup>0</load-on-startup>    </servlet> 

web容器启动时是先 初始化web.xml文件,然后在根据web.xml中的配置进行部署

接下来就是init()方法的实现了。。



public class Lo4jInit extends HttpServlet {private static final long serialVersionUID = 1L;private static Logger logger = Logger.getLogger(Lo4jInit.class);/* web容器初始化 */public void init() {/* 部署在tomcat下的绝对路径 */String path = this.getServletContext().getRealPath("/");/* 获取web.xml文件中name为log4j_init_path的value值 */String file = this.getInitParameter("log4j_init_path");if (file != null) {Properties prop = new Properties();String root = path;/* 设置文件输出的路径 */String root1 = root + "/logs/log.txt";String root2 = root + "logs/error.txt";System.out.println("root1:" + root1);System.out.println("root2:" + root2);try {prop.load(new FileInputStream(path + file)); // 加载log4j.propertiesprop.setProperty("log4j.appender.D.File", root1); // 设置日志文件的输出路径prop.setProperty("log4j.appender.E.File", root2); // 设置日志文件的输出路径PropertyConfigurator.configure(prop); // 加载配置项} catch (Exception e) {System.out.println("any exception??");logger.info("初始化log4j日志输入路径异常,请检查web.xml参数配置是否正常,异常发生在" + this.getClass().getName()+ "类的public void init()方法,异常的愿意是:" + e.getMessage(), e.fillInStackTrace());}}}protected void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {}}

最后附上download接口的实现:(在之前一篇博文我有详细介绍,这里就不详细介绍了)

@Controller
public class FilesController {@RequestMapping(value = "/download")public void download(HttpServletRequest request, HttpServletResponse response) throws Exception {String zipBasePath = request.getSession().getServletContext().getRealPath("/logs");System.out.println("starting download...");/* 判断文件夹是否有文件,遍历文件夹中的文件。。。 */String path = zipBasePath;Vector<String> vecFile = new Vector<String>();recursion(path, vecFile);System.out.println("文件路径分别是:");for (String fileName : vecFile) {System.out.println(fileName);}/* 设置下载文件的名称 */String fileName = "logs.zip";response.setContentType("text/html; charset=UTF-8"); // 设置编码字符response.setContentType("application/x-msdownload"); // 设置内容类型为下载类型response.setHeader("Content-disposition", "attachment;filename=" + fileName);// 设置下载的文件名称OutputStream out = response.getOutputStream(); // 创建页返回方式为输出流,会自动弹出下载框/* 创建压缩文件需要的空的zip包 ,这里是自动生成的,不用我们自己去生成 */String zipFilePath = zipBasePath + "temp.zip";System.out.println("create the empty zip file successfully...");/* 根据临时的zip压缩包路径,创建zip文件 */File zip = new File(zipFilePath);if (!zip.exists()) {zip.createNewFile();}System.out.println("create the  zip file successfully...");/* 创建zip文件输出流 */FileOutputStream fos = new FileOutputStream(zip);ZipOutputStream zos = new ZipOutputStream(fos);System.out.println("create the empty zip stream successfully....");/* 循环读取文件路径集合,获取每一个文件的路径(将文件一个一个进行压缩) */for (String fp : vecFile) {File f = new File(fp); // 根据文件路径创建文件zipFile(f, zos); // 将每一个文件写入zip文件包内,即进行打包}zos.close();System.out.println("files zipped over, starting to download");/* 将打包后的文件写到客户端,有两种方法可以实现(下面会进行介绍),这里使用缓冲流输出 */InputStream fis = new BufferedInputStream(new FileInputStream(zipFilePath));byte[] buff = new byte[4096];int size = 0;while ((size = fis.read(buff)) != -1) {out.write(buff, 0, size);}System.out.println("package is download successfully");// 释放和关闭输入输出流out.flush();out.close();fis.close();}public void zipFile(File inputFile, ZipOutputStream zipoutputStream) {try {if (inputFile.exists()) { // 判断文件是否存在if (inputFile.isFile()) { // 判断是否属于文件,还是文件夹// 创建输入流读取文件FileInputStream fis = new FileInputStream(inputFile);BufferedInputStream bis = new BufferedInputStream(fis);// 将文件写入zip内,即将文件进行打包ZipEntry ze = new ZipEntry(inputFile.getName()); // 获取文件名zipoutputStream.putNextEntry(ze);// 写入文件的方法,同上byte[] b = new byte[1024];long l = 0;while (l < inputFile.length()) {int j = bis.read(b, 0, 1024);l += j;zipoutputStream.write(b, 0, j);}// 关闭输入输出流bis.close();fis.close();} else { // 如果是文件夹,则使用穷举的方法获取文件,写入ziptry {File[] files = inputFile.listFiles();for (int i = 0; i < files.length; i++) {zipFile(files[i], zipoutputStream);}} catch (Exception e) {e.printStackTrace();}}}} catch (Exception e) {e.printStackTrace();}}public void recursion(String root, Vector<String> vecFile) {String path = root;File file = new File(root);if (file.exists()) {System.out.println("this file is exit!");File[] subFile = file.listFiles();for (int i = 0; i < subFile.length; i++) {if (subFile[i].isDirectory()) {recursion(subFile[i].getAbsolutePath(), vecFile);} else {String filename = subFile[i].getName();vecFile.add(path + File.separator + filename);}}} else {System.out.println("this file is not exit!");}}} 


最后总结一下编程过程中遇到一些困难以及解决方法:

1. 在编写Spring的applicationContext.xml文件时,无缘无故出现了:

cvc-complex-type.2.3: Element 'beans' cannot have character [children], because the type's content type is element-only.错误。


错误原因:Spring在初始化的时候无法识别applicationContext.xml中的元素。

可能产生该错误的原因:网上复制的代码直接粘贴到了xml文件中,而网上的代码可能不符合xml规范


解决办法:1.去掉xml文件中的中文注解,因为复制的有些注解Spring不能识别。 

                  2.若仍然有错,则尝试修改多余的空格,因为中文空格Spring有可能识别错误。

                  3.最后的绝招:重新手动抄写一遍文件内容,保存。

参考博文:https://blog.csdn.net/mafan121/article/details/43266733


2. 在配置web.xml 文件中对配置的元素不是很熟悉:


        可以看到,在配置Servlet时,有两个地方需要配置,一个是<servlet>,另一个是<servlet-Mapping>,这两个一个是配置Servlet,一个是配置其映射信息,其中<servlet>中的<servlet-name>可以随意指定,但要有一定的意义,一般取为类的名称,例如我的类名为ServletDemo,这里取名为ServletDemo,下面的<servlet-class>是类的全路径,package+classname,一定要是全路径!

        <servlet-Mapping>是映射信息,它也有一个<servlet-name>,里面的名字是对应的Servlet名,也就是我们上面配置的Servlet名字,这里是ServletDemo,下面的是映射路径,也就是访问Servlet的名称,这里也是以方便和有意义为前提的,是我们在访问Servlet在浏览器地址栏后面输入的那个信息,例如我的映射路径命名为/servlet,在地址栏中输入http://localhost:8080/servlet

注意:这里的映射路径一定不能丢掉/,否则就会出错了一定要写成/servlet,不能是servlet




参考博文:https://blog.csdn.net/m0_37630602/article/details/65443660

3. 

eclipse项目一直显示有错,但是一直找不到错误在哪里

这天在写项目的时候碰到了这么个问题,项目上一直提示着红叉,但不管是文件里还是java buildpath里都找不到报错,然后我就郁闷了。

后来给我找到一个解决方案,能查看当前错误是什么: 

eclipse–>Window–>show View–>Markers,出现一个面板,然后在这个面板里就能查看到底是什么在出错啦。

参考博文:https://blog.csdn.net/zhagzheguo/article/details/51660908

4. 

参考博文:http://lpcjrflsa.iteye.com/blog/1101796(Log4j日志文件输出为相对路径的解决方法
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/559038.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

服务器主机启动不显示,服务器主机不启动怎么回事

服务器主机不启动怎么回事 内容精选换一换本文介绍了主机迁移服务SMS各特性版本的功能发布和对应的文档动态&#xff0c;新特性将在各个区域(Region)陆续发布&#xff0c;欢迎体验。源端服务器数据收集声明。源端服务器上安装和配置完迁移Agent后&#xff0c;迁移Agent会把源端…

最简明扼要的 Systemd 教程,只需十分钟

systemctl常用命令介绍~~~Systemctl是一个systemd工具&#xff0c;主要负责控制systemd系统和服务管理器。 Systemd是一个系统管理守护进程、工具和库的集合&#xff0c;用于取代System V初始进程。Systemd的功能是用于集中管理和配置类UNIX系统。启动及服务大多数主流发行版要…

Java常用设计模式————抽象工厂模式

简介 每一个具体工厂类只负责创建抽象产品的某一个具体子类的实例。 与工厂方法模式的区别 工厂方法模式针对的是一个产品等级结构&#xff0c;而抽象工厂模式针对的是多个产品等级结构&#xff0c;因此抽象工厂模式在结构上要比工厂方法模式更加复杂和抽象&#xff0c;也更…

CSS新手入门教程~~~~

CSS新手入门教程~~~~CSS简介&#xff1a;什么是 CSS? CSS 指层叠样式表 (Cascading Style Sheets)样式定义如何显示 HTML 元素样式通常存储在样式表中把样式添加到 HTML 4.0 中&#xff0c;是为了解决内容与表现分离的问题外部样式表可以极大提高工作效率外部样式表通常存储在…

Docker必备知识整理

Docker简介 Docker是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中&#xff0c;然后发布到任何流行的Linux机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙箱机制&#xff0c;相互之间不会有任何接口。 Docker是用Go语言…

Exception和Error深入分析~~~

Exception和Error深入分析~~~Exception 和 Error 都是继承了 Throwable 类&#xff0c;在 Java 中只有 Throwable 类型的实例才可以被抛出&#xff08;throw&#xff09;或者捕获&#xff08;catch&#xff09;&#xff0c;它是异常处理机制的基本组成类型。 Exception 和 Erro…

Java常用设计模式————原型模式(二)之深拷贝与浅拷贝

引言 clone顾名思义就是复制&#xff0c; 在Java语言中&#xff0c; clone方法被对象调用&#xff0c;所以会复制对象。所谓的复制对象&#xff0c;首先要分配一个和源对象同样大小的空间&#xff0c;在这个空间中创建一个新的对象。那么在java语言中&#xff0c;有几种方式可…

Java面试宝典————基础篇

参考原文&#xff1a;《Java面试题全集&#xff08;上&#xff09;》 1.Java中的基本数据类型有哪些&#xff1f; 类型&#xff1a;byte short int long float double boolean char 字节&#xff1a;1 2 4 8 4 8 1 2 2.面向…

Git初学札记(零)————EGIT完成Eclipse到GitHub一条龙

eclipse安装Egit插件 首先我们要找到所需的egit插件的url更新地址。百度一大堆&#xff0c;但是我还是希望自己去寻找。 打开Eclipse Downloads官网&#xff0c;在页面底部直接输入“egit”关键字&#xff0c;并直接点击第一条搜索到的结果。然后点击Downloads标签页&#xff0…

Eclipse生成SSH传输密钥并实现GitHub的SSH代码提交

生成公私密钥 打开eclipse首选项完成如下操作&#xff1a;保存密钥&#xff1a;这里注意&#xff0c;博主之前已经生成过密钥了&#xff0c;因此这里只是演示截图&#xff0c;如果此时点击保存&#xff0c;会弹出“是否覆盖”提示框。 其中&#xff0c;id_rsa代表非对称加密算法…

SpringBoot————快速搭建springboot项目

完成项目的创建信息 浏览器打开SPRING INITIALIZR网址&#xff1a; http://start.spring.io/ 如下图所示完成配置&#xff1a; 1.完成基础项目配置 2.相关名称 3.依赖jar包&#xff0c;如果是web项目&#xff0c;那么这里选择的Web依赖已经包含了开发web项目所必须的服务器…

史上最容易理解————GET和POST两种基本请求方法的区别

GET和POST两种基本请求方法的区别GET和POST是HTTP请求的两种基本方法&#xff0c;要说它们的区别&#xff0c;接触过WEB开发的人都能说出一二。最直观的区别就是GET把参数包含在URL中&#xff0c;POST通过request body传递参数。你可能自己写过无数个GET和POST请求&#xff0c;…

SpringBoot————JPA快速使用

本篇博客源码地址&#xff1a;https://github.com/DragonWatcher/ease-run 概述 Hibernate与JPA 本篇博客中的web项目选用Hibernate作为持久层框架。在Spring Boot中&#xff0c;我们需要了解另一个概念&#xff1a;JPA 上一句话可能有些歧义&#xff0c;并不是说JPA就是Sp…

MySQL优化建议汇总~~~

MySQL优化建议汇总~~~1、将经常要用到的字段&#xff08;比如经常要用这些字段来排序&#xff0c;或者用来做搜索&#xff09;&#xff0c;则最好将这些字段设为索引 2、字段的种类尽可能用int或者tiny int类型。另外字段尽可能用not null 3、当然无可避免某些字段会用到text&a…

Spring Boot————静态方法如何调用Spring容器中的Bean

问题分析 在使用静态方法的时候&#xff0c;某些情况下&#xff0c;需要使用类似自动注入的Bean来实现某些业务逻辑。 一般的非静态方法&#xff0c;可以很容易的通过在方法所在的类中Autowired自动将依赖的Bean注入到本类中&#xff0c;并操作。 静态方法在使用同样的操作流…

内部类详解————匿名内部类

内部类三连击&#xff1a; 《内部类详解————匿名内部类》 《内部类详解————局部内部类》 《内部类详解————静态嵌套类》 应用场景 由于匿名内部类不利于代码的重用&#xff0c;因此&#xff0c;一般在确定此内部类只会使用一次时&#xff0c;才会使用匿名内部…

内部类详解————局部内部类

内部类三连击&#xff1a; 《内部类详解————匿名内部类》 《内部类详解————局部内部类》 《内部类详解————静态嵌套类》 定义 在方法或某个作用域内的内部类&#xff0c;称为局部内部类。匿名内部类就是一种局部内部类。 实现方式 public class OutterType …

内部类详解————静态内部类

内部类三连击&#xff1a; 《内部类详解————匿名内部类》 《内部类详解————局部内部类》 《内部类详解————静态内部类》 定义 静态内部类&#xff0c;又叫静态嵌套类或嵌套类。是使用static关键字修饰的内部类。 静态内部类可以用 private 修饰&#xff0c;这…

jvm gc垃圾回收机制和参数说明amp;amp;Java JVM 垃圾回收(GC 在什么时候,对什么东西,做了什么事情)

jvm gc&#xff08;垃圾回收机制&#xff09; Java JVM 垃圾回收&#xff08;GC 在什么时候&#xff0c;对什么东西&#xff0c;做了什么事情&#xff09; 前言&#xff1a;&#xff08;先大概了解一下整个过程&#xff09;作者&#xff1a;知乎用户 链接&#xff1a;https:…

【Mathematical Model】Ransac线性回归Python代码

Ransac算法&#xff0c;也称为随机抽样一致性算法&#xff0c;是一种迭代方法&#xff0c;用于从一组包含噪声或异常值的数据中估计数学模型。Ransac算法特别适用于线性回归问题&#xff0c;因为它能够处理包含异常值的数据集&#xff0c;并能够估计出最佳的线性模型。 1 简介 …