如何在JAVA Web服务器中集成Xlloop?

时间:2017-06-12 06:29:07

标签: java excel servlets

我正在尝试从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插件?

1 个答案:

答案 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();
    }
}