前段时间项目中需要生成商品条码,使用 Barcode4J 库实现的,直接使用了内部的 BarcodeServlet ,仅在 Spring MVC 的 Controller 里简单的封装了下提供个访问路径,使用上没有遇到任何问题。代码如下:
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.krysalis.barcode4j.servlet.BarcodeServlet;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
*
* 条码生成控制器
* 直接继承barcode4j的BarcodeServlet实现
*
*/
@Controller
@RequestMapping(value = "/barcode")
public class BarcodeController extends BarcodeServlet {
private static final long serialVersionUID = 2454174797419872114L;
/**
*
* 根据 request 中传递的参数生成条码,如:http://localhost/barcode/genbc?type=code128&msg=123456&ext=.svg
* type:条码类型,默认值为 code128
* msg:条码号,默认值为 1234567890
* ext:输入类型,默认值为 svg
* 详细文档:http://barcode4j.sourceforge.net/2.1/index.html
*
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
@RequestMapping(value = "/genbc")
public void genbc(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
super.doGet(request, response);
}
}
近期项目改造,由 Eclipse J2EE Web 改为 Gradle 构建方式。将所有WEB-INF\lib 下的 jar 根据经验转换为 build.gradle 配置文件中的依赖配置,部分内容如下:
// 其他配置省略...
dependencies {
// 增加 barcode4j 依赖
compile 'net.sf.barcode4j:barcode4j:2.1'
// 其他依赖省略...
}
这个转换过程中是会遇到很多问题的,就说 Barcode4J 的这个
2018-10-07 13:50:05.068 ERROR 12096 --- [ost-startStop-1] o.s.b.web.embedded.tomcat.TomcatStarter :
Error starting Tomcat context. Exception: org.springframework.beans.factory.BeanCreationException. Message:
Error creating bean with name 'barcodeController':
Lookup method resolution failed;
nested exception is java.lang.IllegalStateException:
Failed to introspect Class [org.krysalis.barcode4j.servlet.BarcodeServlet] from ClassLoader [sun.misc.Launcher$AppClassLoader@58644d46]
这个错误很棘手,直接导致项目无法启动,会影响团队成员的开发工作。
原始的web项目中是直接将 jar 放入 lib 文件下面,Barcode4J barcode4j-2.1.0 官方下载的里面有所依赖的 jar,如下:
而使用 Gradle barcode4j-2.1.0 的 Maven 依赖,如下:
avalon-framework
avalon-framework-impl
4.2.0
javax.servlet
servlet-api
2.2
provided
commons-cli
commons-cli
1.0
org.apache.ant
ant
1.7.1
仔细的看的话就会发现 官网下载的包里面是 avalon-framework-4.2.0,而使用 Maven 时里面的却是 avalon-framework-impl 4.2.0,在排除问题,读 barcode4j 的 BarcodeServlet 源码时 IDEA 提示:
Cannot resolve symbol ‘Configuration’
Cannot resolve symbol ‘Logger’
意思是找不到 org.apache.avalon.framework.configuration.Configuration 与 org.apache.avalon.framework.logger.Logger 这两个类。
查看org.apache.avalon.framework.configuration内确实是没有Configuration 这个类,如下图:
查看org.apache.avalon.framework.logger 内确实也没有 Logger 这个类,如下图:
既然这个依赖的名称后面又 impl,那么是否有接口呢?
查询 Maven 库 https://search.maven.org/classic/#search|ga|1|g%3A"avalon-framework" 有和 avalon-framework-impl 对应的 avalon-framework-api 而且版本也是一一对应的。
那么就来看下 avalon-framework-api 里面是否有这两个疑似接口的类吧,如下图:
果真在这里面,那么手动在 build.gradle 里面加入 avalon-framework-api 依赖,如下:
// 其他配置省略...
dependencies {
// 增加 barcode4j 依赖
compile 'net.sf.barcode4j:barcode4j:2.1'
// 手动添加的 :avalon-framework-api 依赖
compile 'avalon-framework:avalon-framework-api:4.2.0'
// 其他依赖省略...
}
手动加入依赖后,重新编译问题解决了。看来的确是 barcode4j 的依赖中缺少依赖 avalon-framework-api 。
那么,为什么下载的 barcode4j-2.1.0-bin.zip 中的 lib 文件夹内的 avalon-framework-4.2.0.jar 就好使呢?看了下 avalon-framework-4.2.0.jar 的文件是85KB ,而依赖下载的
avalon-framework-api-4.2.0.jar 是 34KB 和 avalon-framework-impl-4.2.0.jar 是 60KB。由此看来应该是 avalon-framework-4.2.0.jar 里面包含了 avalon-framework-api-4.2.0.jar 和 avalon-framework-impl-4.2.0.jar 的内容。