SSM integra EasyPoi para resolver el problema de ArrayIndexOutOfBoundsException al exportar imágenes

 

Blog de referencia:

https://blog.csdn.net/qq_34988540/article/details/83050187

https://blog.csdn.net/breakaway_01/article/details/103895099

Prefacio

Recientemente, debido a las necesidades de los trabajos finales de JavaWeb, EasyPoi se introdujo en el proyecto SSM para exportar datos de pedidos a Excel. Hablar de los dos pozos encontrados

Importar manualmente el paquete jar

Dado que el proyecto está codificado con los miembros del equipo, importo manualmente el paquete jar desde el principio, sin usar maven. La documentación oficial de EasyPoi no dice qué paquetes jar deben incluirse en la importación manual, y se informa del error java.lang.NoClassDefFoundError , que obviamente es una falta de paquetes jar.

En Eclipse, no hay forma de rastrear el código fuente importando manualmente el paquete jar. No sé qué paquete jar falta después de leer el error.

Más tarde, no había manera, así que creé un nuevo proyecto maven, importé EasyPoi usando maven y lo exporté como un paquete de guerra. Luego descomprima el paquete war y descubrió que EasyPoi 3.2.0 necesita importar los siguientes paquetes jar en total

commons-lang3-3.2.1.jar

guava-16.0.1.jar

easypoi-base-3.2.0.jar

easypoi-annotation-3.2.0.jar

easypoi-web-3.2.0.jar

Error de exportación de imagen ArrayIndexOutOfBoundsException

En cuanto a la razón, el blog de referencia en el prefacio es muy detallado, aquí hablaré sobre cómo reemplazar la configuración predeterminada de EasyPoi en el proyecto SSM para resolver el problema de resolución de ruta.

package easymall.component;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;

import javax.imageio.ImageIO;

import org.apache.commons.io.IOUtils;

import com.google.common.cache.CacheLoader;

import cn.afterturn.easypoi.cache.manager.POICacheManager;

/**
 * 自定义EasyPoiFixedCacheLoader,以替换EasyPoi的默认CacheLoader实现
 * 解决图片路径解析的bug
 * 参考博客:https://blog.csdn.net/qq_34988540/article/details/83050187
 * 
 * @author	passerbyYSQ
 * @date	2020-12-29 15:26:04
 */
public class EasyPoiFixedCacheLoader extends CacheLoader<String, byte[]> {

	@Override
	public byte[] load(String imagePath) throws Exception {
		InputStream is = POICacheManager.getFile(imagePath);
        BufferedImage bufferImg = ImageIO.read(is);
        ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
        try {
            ImageIO.write(bufferImg,
            		// lastIndexOf 为修改源码的地方
                    imagePath.substring(imagePath.lastIndexOf(".") + 1, imagePath.length()),
                    byteArrayOut);
            return byteArrayOut.toByteArray();
        } finally {
            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(byteArrayOut);
        }
	}

}
package easymall.component;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.afterturn.easypoi.cache.manager.FileLoaderImpl;
import cn.afterturn.easypoi.cache.manager.IFileLoader;

/**
 * 解决EasyPoi网络图片下载并导出的问题
 * 参考博客:https://blog.csdn.net/breakaway_01/article/details/103895099
 * 
 * @author	passerbyYSQ
 * @date	2020-12-29 15:33:22
 */
public class EasyPoiFixedFileLoaderImpl implements IFileLoader {

    private static final Logger LOGGER = LoggerFactory.getLogger(FileLoaderImpl.class);

    @Override
    public byte[] getFile(String url) {
        InputStream fileis = null;
        ByteArrayOutputStream baos = null;
        try {

            //判断是否是网络地址
            if (url.startsWith("http")) {
                URL urlObj = new URL(url);
                URLConnection urlConnection = urlObj.openConnection();
                urlConnection.setConnectTimeout(3 * 1000);
                urlConnection.setReadTimeout(60 * 1000);
                urlConnection.setDoInput(true);
                urlConnection.setRequestProperty("Accept-Charset", "UTF-8");
                fileis = urlConnection.getInputStream();

            } else {
                //先用绝对路径查询,再查询相对路径
                try {
                    fileis = new FileInputStream(url);
                } catch (FileNotFoundException e) {
                    //获取项目文件
                    fileis = FileLoaderImpl.class.getClassLoader().getResourceAsStream(url);
//                    if (fileis == null) {
//                        //最后再拿相对文件路径
//                        String path = PoiPublicUtil.getWebRootPath(url);
//                        fileis = new FileInputStream(path);
//                    }
                }
            }

            baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len = fileis.read(buffer)) > -1) {
                baos.write(buffer, 0, len);
            }
            baos.flush();
            return baos.toByteArray();
        } catch (IOException e) {
            LOGGER.error(e.getMessage(), e);
        } finally {
            IOUtils.closeQuietly(fileis);
            IOUtils.closeQuietly(baos);
        }
        LOGGER.error(fileis + "这个路径文件没有找到,请查询");
        return null;
    }
}

Cuando se inicia Tomcat, leerá la configuración del archivo web.xml e inicializará nuestro contenedor Spring. Después de que se complete la inicialización del contenedor Spring, podemos realizar una operación de "reemplazo" para corregir los errores de EasyPoi. Por lo tanto, necesitamos personalizar nuestro propio ContextLoaderListener 

package easymall.component;

import java.util.concurrent.TimeUnit;

import javax.servlet.ServletContextEvent;

import org.springframework.web.context.ContextLoaderListener;

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.LoadingCache;

import cn.afterturn.easypoi.cache.ImageCache;
import cn.afterturn.easypoi.cache.manager.POICacheManager;

/**
 * @author	passerbyYSQ
 * @date	2020-12-29 15:15:41
 */
public class MyContextLoaderListener extends ContextLoaderListener {

	@Override
	public void contextInitialized(ServletContextEvent event) {
		
		super.contextInitialized(event); // 不能去掉
		
		// 容器初始化完成后,替换EasyPoi的ImageCache
		// 以解决EasyPoi源码中导出本地图片的路径解析的bug
		
		EasyPoiFixedCacheLoader cacheLoader = new EasyPoiFixedCacheLoader();
		LoadingCache<String, byte[]> loadingCache = CacheBuilder.newBuilder()
				.expireAfterWrite(1, TimeUnit.DAYS)
                .maximumSize(2000).build(cacheLoader);
		// 替换
		ImageCache.setLoadingCache(loadingCache);
		
		// 替换
		EasyPoiFixedFileLoaderImpl fileLoader = new EasyPoiFixedFileLoaderImpl();
		POICacheManager.setFileLoder(fileLoader);
		
		System.out.println("容器初始化完毕!!!");
	}

}

web.xml

 <!-- 指定一ContextLoaderListener方式启动Spring容器
  原本:org.springframework.web.context.ContextLoaderListener
  修改后:easymall.component.MyContextLoaderListener(自定义的ContextLoaderListener的路径)
   -->
  <listener>
  	<listener-class>
  		easymall.component.MyContextLoaderListener
  	</listener-class>
  </listener>

 

Supongo que te gusta

Origin blog.csdn.net/qq_43290318/article/details/111932803
Recomendado
Clasificación