JSF 2 cc: передайте атрибут в отступающий боб

Я создаю пользовательский компонент, который является программой просмотра изображений для данного номера продуктов. Я получаю доступ к этим файлам с помощью измененной версии ImageServlet BalusC:

@WebServlet(name="ImageLoader", urlPatterns={"/ImageLoader"})
public class ImageLoader extends HttpServlet {

    private static final int DEFAULT_BUFFER_SIZE = 10240; // 10KB.

    private static String imagePath = "\\\\xxx.xxx.x.x\\root\\path\\to\\images\\";

    /** 
      * This code is a modified version of the ImageServlet found at balusc.blogspot.com.
     * It expects the parameters id and n.
     * 
    *
  • id: the product number
  • *
  • n: the image number to load.
  • */ public void goGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String productNumber = URLDecoder.decode(request.getParameter("id"),"utf-8"); String img = URLDecoder.decode(request.getParameter("n"),"utf-8"); if (productNumber == null || img == null) { response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404. return; } String path = generatePath(productNumber); File image = new File(generatePath(productNumber), generateImageName(img)); // Check if file actually exists in filesystem. if (!image.exists()) { response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404. return; } String contentType = getServletContext().getMimeType(image.getName()); if (contentType == null || !contentType.startsWith("image")) { response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404. return; } // Init servlet response. response.reset(); response.setBufferSize(DEFAULT_BUFFER_SIZE); response.setContentType(contentType); response.setHeader("Content-Length", String.valueOf(image.length())); response.setHeader("Content-Disposition", "inline; filename=\"" + image.getName() + "\""); // Prepare streams. BufferedInputStream input = null; BufferedOutputStream output = null; try { // Open streams. input = new BufferedInputStream(new FileInputStream(image), DEFAULT_BUFFER_SIZE); output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE); // Write file contents to response. 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); } } private String generateImageName(String n) { int imageNum = Integer.parseInt(n); StringBuilder ret = new StringBuilder("img-"); if (imageNum < 10) { ret.append("00"); } else if(imageNum < 100) { ret.append("0"); } ret.append(n); ret.append(".jpg"); return ret.toString(); } public static String generatePath(String productNumber) { Long productNumberLng = Long.parseLong(productNumber); StringBuilder ret = new StringBuilder(imagePath); Long thousandPath = productNumberLng - (productNumberLng % 1000); ret.append(thousandPath); ret.append("s\\"); ret.append(productNumber); ret.append("\\"); ret.append(productNumber); ret.append("\\"); return ret.toString(); } private static void close(Closeable resource) { if (resource != null) { try { resource.close(); } catch (IOException e) { e.printStackTrace(); } } } }

Затем я создал составной компонент:





  
  
      
      
  

  
  
      

Как Вы видите, я просто захватываю список изображений от управляемого компонента. Единственная причина это действительно необходимо, состоит в том, потому что я должен знать, сколько изображения там для данного продукта. Это может варьироваться значительно (где угодно от 8 до 100). Вот то, что код:

@ManagedBean
@RequestScoped
public class ImageLoaderUtilBean {

    @ManagedProperty(value = "#{param.id}")
    private Long productNumber;

    private List images;

    public List getImages() {

        if (images == null) {
            setImages(findImages());
        }
        return images;
    }

    public void setImages(List images) {
        this.images = images;
    }    

    public Long getProductNumber() {
        return productNumber;
    }

    public void setProductNumber(Long productNumber) {
        this.productNumber = productNumber;
    }

    private List findImages() {


        FilenameFilter jpegFilter = new FilenameFilter() {

            @Override
            public boolean accept(File directory, String filename) {
                return filename.toLowerCase().endsWith(".jpg");
            }
        };

        File directory = new File(ImageLoader.generatePath(productNumber.toString()));
        if (!directory.exists()) {
            return new ArrayList();
        }
        File[] files = directory.listFiles(jpegFilter);

        List ret = new ArrayList();

        for (int i = 1; i <= files.length; i++) {
            EvfImage img = new EvfImage();
            img.setName("file.getName()");
            img.setUrl("/ImageLoader?id=" + productNumber + "&n=" + i);
            ret.add(img);
        }

        return ret;
    }

}

Существует простой объект для содержания данных, которых я выполняю итерации:

public class EvfImage {

    private String url;
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

}

Наконец, я тестирую этот составной компонент с помощью URL http://localhost:8080/project-name/testImages.xhtml?id=213123. Вот код для testImages.xhtml:




    
        Facelet Title
    
    
        
    

Вот проблема: единственная точка взаимодействия между приложением и составным компонентом должна быть тегом . Однако это - текучая абстракция. Управляемому компоненту дают номер продуктов на основе запроса id параметр. Это очень нежелательно. Это создает намного более трудную связь между компонентом и приложением, которое использует его. Идеально, я должен использовать тег следующим образом: . Однако я не могу выяснить способ сделать это и все еще знать, сколько изображений я должен создать.

Заранее спасибо, Zack

Править: Было бы совершенно приемлемо назвать сервлет, который берет в номере продуктов и возвращает количество изображений, которые имеет тот продукт. Однако я должен все же найти способ выполнить цикл n времена (для цикла) в противоположность выполнению его однажды для каждого объекта в Наборе (цикл foreach). Я в значительной степени доволен любым решением, которое включает удаление это @ManagedProperty("#{param.id}") от отступающего боба.

1
задан BalusC 23 June 2010 в 20:51
поделиться

1 ответ

Замена @ManagedProperty(value="#{param. id}") в ImageLoaderUtilBean будет

<sdCom:imageViewer listID="test" productNumber="#{param.id}" />

в сочетании со следующим в cc:implementation before ui:repeat:

<c:set target="#{imageLoaderUtilBean}" property="productNumber" value="#{cc.attrs.productNumber}" />

Где c: - это встроенная JSTL библиотека Facelets, которая должна быть объявлена следующим образом:

xmlns:c="http://java.sun.com/jsp/jstl/core"

У Facelets нет замены для c:set (пока? ).

2
ответ дан 2 September 2019 в 23:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: