服务器启动后,Tomcat不从上下文路径加载新映像

时间:2016-04-01 12:42:36

标签: java tomcat

在我的tomcat文件夹的server.xml内,我在<Host>标记下有一个虚拟文件夹:

<Context docBase="C:\app_files\" path="/app_files"/>

所以我可以通过网址http://localhost:8080/app_files/some_file.jpg

访问此文件夹中的文件

但是只有在服务器启动之前图像或文件已经存在的情况下,这才有效。如果我转到指向服务器启动后创建的映像的URL,则会出现404错误。重新启动服务器后,图像正确加载。

如何解决这个问题?

4 个答案:

答案 0 :(得分:0)

尝试将属性autoDeploy="true"添加到您的上下文配置中,这将告诉catalina监控您的文档库位置以进行更改

答案 1 :(得分:0)

如果您使用Tomcat应用程序管理器,您可以取消部署/部署单个应用程序而无需重新启动整个服务器(并且不会影响其他Web应用程序),或者更残酷的是,您可以从webapps目录替换所需的战争(再次取消部署/部署随之而来)。如果您必须保证应用程序的正常运行时间,即使在这种情况下您也必须进行并行部署(here a guide for tomcat 8

答案 2 :(得分:0)

我实际上设法做了我想要的,而不使用server.xml上的Context。 它基于BalusC's solution通过servlet提供静态文件 方法如下:

  • 首先,我在我的系统中创建了一个环境变量(可以在每个操作系统中完成,只需谷歌“如何在Windows,Linux等上创建环境变量”),称为 MANAGEMENT_FILES ,我案例中的变量值为 c:/ management_files /
  • 然后,在创建应该向用户显示的图像的方法上,我将图像保存在此文件夹(这是上一步中环境变量的值):< / LI>

public String imageUrl;

public void createAndShowImage() {
    try {
        String imageName = "/nice_images_folder/cool_image.jpg";
        File imageFile = new File(System.getenv("MANAGEMENT_FILES") + imageName);
        //Here goes your logic to create the file
        createImage(imageFile);
        //Here i use a fixed URL, you can do it as you see fit
        this.imageUrl = "http://localhost:8080/MyCoolApp/" + CoolFileServlet.BASE_URL + imageName + "?delete=true";
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • 这是你必须创建的servlet,这个servlet返回你放在文件夹中的图像或任何其他文件:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLDecoder;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name="CoolFileServlet", urlPatterns={CoolFileServlet.BASE_URL + "*"})
public class CoolFileServlet extends HttpServlet {

    public static final String BASE_URL = "/shiny_happy_files/";

    private static final int DEFAULT_BUFFER_SIZE = 10240;

    private String filePath;

    public void init() throws ServletException {
        this.filePath = System.getenv("MANAGEMENT_FILES");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        String requestedFile = request.getPathInfo();

        if (requestedFile == null) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.
            return;
        }

        File file = new File(filePath, URLDecoder.decode(requestedFile, "UTF-8"));

        if (!file.exists()) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.
            return;
        }

        String contentType = getServletContext().getMimeType(file.getName());
        if (contentType == null) {
            contentType = "application/octet-stream";
        }

        response.reset();
        response.setBufferSize(DEFAULT_BUFFER_SIZE);
        response.setContentType(contentType);
        response.setHeader("Content-Length", String.valueOf(file.length()));
        response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");

        BufferedInputStream input = null;
        BufferedOutputStream output = null;

        try {
            input = new BufferedInputStream(new FileInputStream(file), DEFAULT_BUFFER_SIZE);
            output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);

            byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
            int length;
            while ((length = input.read(buffer)) > 0) {
                output.write(buffer, 0, length);
            }
        } finally {
            close(output);
            close(input);
            try {
                if ("true".equals(request.getParameter("delete"))) {
                    if (!file.delete()) {
                        throw new RuntimeException("File could not be deleted");
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private static void close(Closeable resource) {
        if (resource != null) {
            try {
                resource.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

请注意,访问时可以在url中传递参数delete = true,在恢复后立即将其删除(如果不再需要它)。

在我的情况下,我需要在用户执行某些操作后在页面上显示图像,所以我所要做的就是显示图像网址:

<h:graphicImage url="#{myManagedBean.imageUrl}"/>

就是这样,您可以使用此servlet为任何类型的文件提供服务,它将立即返回您想要的文件,并且文件将在服务器重新启动/重新部署之间保持活动状态(如果未通过{{1}删除它}。

答案 3 :(得分:0)

如果您希望使用其他方法,也可以通过在指定媒体类型的同时在返回IOUtils对象的控制器中映射函数,然后在img的src中调用该函数的URL,来实现此目的。

@ResponseBody
@RequestMapping(value="/load_photo", params = {"myPhoto"}, method = RequestMethod.GET, produces = MediaType.IMAGE_PNG_VALUE)
public byte[] loadPhoto(@RequestParam(value = "myPhoto") String myPhoto) throws IOException {
    
    File file = new File(servletContext.getRealPath("")+Constants.PATH_TO_FILE+myPhoto);
    
    FileInputStream fis = new FileInputStream(file);
    return IOUtils.toByteArray(fis);
}

然后您在JSP中调用img:

<img class="photo" src="/app/controller/load_photo?myPhoto=${myPhoto}">

借助此功能,您可以提供动态生成的图像。