我正在尝试从servlet集成XLLoop并尝试通过HTTP协议运行。以下是我的代码:
XlloopServlet.java
@WebServlet(value = "/FunctionServer", name = "FunctionServer", asyncSupported = true)
public class XlloopServlet extends FunctionServlet {
private static final long serialVersionUID = -3845895326255874126L;
@Override
public void init(final ServletConfig config) throws ServletException {
// Create a function information handler to register our functions
FunctionInformationHandler infoHandler = new FunctionInformationHandler();
// Create a reflection function handler and add the required methods
FunctionHandler handler = new FunctionHandler();
infoHandler.add(handler.getFunctions());
// Set the handlers
CompositeFunctionHandler compositeHandler = new CompositeFunctionHandler();
compositeHandler.add(handler);
compositeHandler.add(infoHandler);
// Setting the function handler in the parent servlet
setHandler(compositeHandler);
}
和我注册函数的FunctionHandler类:
public class FunctionHandler implements IFunctionHandler, FunctionProvider {
private ReflectFunctionHandler rfh;
public FunctionHandler() {
// Create a reflection function handler and add the Math methods
rfh = new ReflectFunctionHandler();
rfh.addMethods("Math.", Math.class);
rfh.addMethods("Math.", Maths.class);
rfh.addMethods("CSV.", CSV.class);
rfh.addMethods("Reflect.", Reflect.class);
}
@Override
public XLoper execute(IFunctionContext arg0, String arg1, XLoper[] arg2) throws RequestException {
return rfh.execute(arg0, arg1, arg2);
}
@Override
public boolean hasFunction(String arg0) {
return rfh.hasFunction(arg0);
}
@Override
public FunctionInformation[] getFunctions() {
return rfh.getFunctions();
}
public ReflectFunctionHandler getReflectFunctionHandler() {
return rfh;
}
}
我的XLLoop ini文件如下:
protocol=http
url=http://localhost:8080/MyApp/FunctionServer
现在,当我尝试从我的excel调用一个函数时,我在servlet类中调用了一切,但是所有函数都没有在excel文件上执行。
任何人都知道如何在像tomcat这样的网络服务器上集成XLLoop插件?
答案 0 :(得分:1)
我刚刚用JAX-RS和一点Spring实现了这个。我使用REST端点为正在运行的服务的正确服务器主机/端口填充xlloop.ini文件,然后将我的xlsb,xll和ini文件打包成一个zip供客户端下载。目前它并不是特别漂亮,但web.xml和Startup片段在下面。
我没有花时间的事情是内存管理。如果很多用户加载了大量数据,我需要定期清理它,所以要小心空闲的会话线程!
Web.xml中
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>com.myapp.web.excel.XLLoopStartup</listener-class>
</listener>
XLLoopStartup.java
public class XLLoopStartup implements ServletContextListener {
public static XLLoopStartup INSTANCE;
private FunctionServer fs;
@Inject
private SomeInjectionThing usefulSpringStuff;
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
@Override
public void contextInitialized(ServletContextEvent sce) {
INSTANCE = this;
// Initialize my Spring stuff
if (sce != null){
WebApplicationContextUtils//
.getRequiredWebApplicationContext(sce.getServletContext())//
.getAutowireCapableBeanFactory()//
.autowireBean(this);
}
Executors.newSingleThreadExecutor().execute(new Runnable() {
@Override
public void run() {
registerConverters();
fs = new FunctionServer(Integer.parseInt(System.getProperty("port.tomcat.xlloop", "10606")));
ReflectFunctionHandler rfh = new ReflectFunctionHandler();
rfh.addMethods(ExcelTrades.CATEGORY, ExcelTrades.class);
rfh.addMethods(ExcelUtils.CATEGORY, ExcelUtils.class);
rfh.addMethods(ExcelPositions.CATEGORY, ExcelPositions.class);
rfh.addMethods(ExcelProducts.CATEGORY, ExcelProducts.class);
// Create a function information handler to register our functions
FunctionInformationHandler firh = new FunctionInformationHandler();
firh.add(rfh.getFunctions());
// Set the handlers
CompositeFunctionHandler cfh = new CompositeFunctionHandler();
cfh.add(rfh);
cfh.add(firh);
DebugFunctionHandler debugFunctionHandler = new DebugFunctionHandler(cfh);
fs.setFunctionHandler(new SecureFunctionHandler(debugFunctionHandler));
try {
fs.run();
}
catch (IOException e) {
e.printStackTrace();
}
}
});
}
// For quick testing
public static void main(String[] args) {
new XLLoopStartup().contextInitialized(null);
}
// Function classes can statically access this instance and get spring things from it
public SomeInjectionThing getThing() {
return usefulSpringStuff;
}
}
ExcelService.java
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.apache.commons.io.IOUtils;
import io.swagger.annotations.Api;
@Api("excel")
@Path("/excel")
public class ExcelService {
@Context
UriInfo uri;
@GET
@Path("/download")
@Produces({ MediaType.APPLICATION_OCTET_STREAM })
public Response download() {
StringWriter sw = new StringWriter();
// Create an INI file. We should probably store all default settings in a file and just add the server info to
// it.
sw.write("server=");
sw.write(uri.getBaseUri().getHost());
sw.write(":");
sw.write(System.getProperty("port.tomcat.xlloop", "10605"));
String inifile = sw.toString();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (ZipOutputStream zos = new ZipOutputStream(baos)) {
// Add the ini file to the zip
ZipEntry entry = new ZipEntry("xlloop.ini");
zos.putNextEntry(entry);
zos.write(inifile.getBytes());
zos.closeEntry();
// Add the Excel files
writeFileFromClasspath(zos, "xlloop.xll");
// This is my custom Excel macro sheet with other useful functions for user authentication etc.
writeFileFromClasspath(zos, "xlloop.xlsb");
}
catch (IOException ioe) {
ioe.printStackTrace();
}
return Response.ok(new ByteArrayInputStream(baos.toByteArray()))
.header("Content-Disposition", "attachment; filename=xlloop.zip").build();
}
private void writeFileFromClasspath(ZipOutputStream zos, String filename) throws IOException {
ZipEntry xlFileEntry = new ZipEntry(filename);
zos.putNextEntry(xlFileEntry);
zos.write(IOUtils.toByteArray(ExcelService.class.getClassLoader().getResourceAsStream(filename)));
zos.closeEntry();
}
}