Java Web шаблонизатор или один сервлет на все запросы

Java Web шаблонизатор или один сервлет на все запросы Тема шаблонизатора уже поднималась на нашем ресурсе в разделе  PHP сайтостроения. Напомню про простейший принцип формирования страниц сайта - загрузка единого шаблона с текстовыми ключами в буфер и замена ключей на их значения. В качестве значений могут быть контент, картинки, рекламные блоки, скрипты, которые работают в браузере и многое другое. Данный пост это попытка на Java Web или правильнее JavaEE организовать примерно то же самое.

Начнем с того, что для построения шаблонизатора на Java, не обойтись без сервлета. Сервлет это собственно класс расширяющий класс HttpServlet который входит в библиотеку javax.servlet.http.HttpServlet JavaEE. Класс имеет методы doGet, DoPost, processRequest, которые можно использовать для организации в одном из них загрузки шаблона в буфер, замену ключей на значения и передачу преобразованного шаблона клиенту (браузеру).

Нужно понимать, что это простейший вариант построения Web ресурса на Java. Да и вообще JavaEE не предназначена для таких простых вещей. Но тем не менее все же попробуем, хотя бы потому, что на PHP таким макаром строятся неплохие блоги с хорошей функциональностью и защищенностью, полностью на текстовых файлах.

Итак, не будем раcсусоливать и создадим в NetBeans проект JavaWebTest и сервлет ServletTest в пакете test. 

Проет NetBeans

В методе processRequest создадим обработчик который будет выполнять простейшую операцию по загрузке одного и того же файла index.html, тобиш шаблона, с текстовыми ключами, в буфер, замену текстовых ключей на соответствующие им значения и выдачу результата клиенту.

Предварительно подготовим сам файл index.html с текстовым ключом $textCont, а также два файла с простыми html тегами и с простейшим но разным контентом - Контент1 Контент2. Пусть файлы будут иметь расширение .html и обзываться text1.html и text2.html.

HTML шаблон

В класс сервлета добавим несколько методов необходимых для чтения файла в буфер, формирования пути к файлам контента по имени запроса и др. Необходимо обратить внимание на анотацию к сервлету (@WebServlet(name = "ServletTest", urlPatterns = {"*.html"})) которая говорит о том, что сервлет будет реагировать на все запросы имеющие в своем составе строку *.html В коде это выглядит так:


@WebServlet(name = "ServletTest", urlPatterns = {"*.html"})
public class ServletTest extends HttpServlet {
    // путь к папке с файлами шаблона и страниц 
    private String $pathMainFolder = "../../../../web/"; 
    // кодировка страниц
    private String fileEncoding = "UTF-8";

    // объект ассоциативного массива
    private HashMap selects = new HashMap();
    
    // чтение файла в строку
    private String readFileAsString(String filePath, String fileEncoding) throws IOException {
        DataInputStream dis = new DataInputStream(new FileInputStream(filePath));
        try {
            long len = new File(filePath).length();
            if (len > Integer.MAX_VALUE) {
                throw new IOException("File "+filePath+" too large, was "+len+" bytes.");
            }
            byte[] bytes = new byte[(int) len];
            dis.readFully(bytes);
            return new String(bytes, fileEncoding);
        } finally {
            dis.close();
        }
    }  
    // метод получения пути к файлу
    private class ReadFile
    {
        public String getContents(File aFile) {
        StringBuilder contents = new StringBuilder();
	    
	    try {
            BufferedReader input =  new BufferedReader(new FileReader(aFile));
            try {
                String line = null; //not declared within while loop
	      
                while (( line = input.readLine()) != null){
                contents.append(line);
                contents.append(System.getProperty("line.separator"));
                }
            }
            finally {
	        input.close();
            }
	    }
	    catch (IOException ex){
	    }
	    
	    return contents.toString();
        }
    }  
    // получене URI в строке
    private String actionURI(HttpServletRequest request) {
        
        String contextPath = request.getServletContext().getContextPath() ;
        String uri = request.getRequestURI() ;
        if ( contextPath == null ) {
            return uri ;
        }
        if ( contextPath.isEmpty()) {
            return uri ;
        }
        String x = uri ;
        if ( uri.startsWith(contextPath) ) {
            x = uri.substring(contextPath.length()) ;
        }
        //log.info("uriWithoutContextPath: uri = "+uri+" contextPath="+contextPath+ "--> x="+x) ;
        return x ;
    }

    // сравнение строк
    private boolean equals(String str1, String str2) {
        return str1 == null ? str2 == null : str1.equals(str2);
    }    
    
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        // строка шаблона
        String html;
        // строка контента
        String cont;
        // получить URI в строке 
        String uriPg = actionURI(request);
        // если запрос по домену то на первую страницу
        if(equals(uriPg, "/")) {
            uriPg = "/text1.html";
        }
        // URI на консоль
        System.out.println("uriPg - " + uriPg);
        // прочитать файл шаблона в строку html
        File fileTempl = null;  
        try {
            fileTempl = new File(ReadFile.class.getResource($pathMainFolder + "index.html").toURI());
        } catch (URISyntaxException ex) {
            Logger.getLogger(ServletTest.class.getName()).log(Level.SEVERE, null, ex);
        }
        // путь к файлу шаблона
        String templPath = fileTempl.toString();
        // шаблон в буфер 
        html = readFileAsString(templPath, fileEncoding);
        // строка шаблона на консль 
        System.out.println("html - " + html);
        
        // чтение контента в переменную-строку
        File fileCont = null; 
        try {
            fileCont = new File(ReadFile.class.getResource($pathMainFolder + uriPg).toURI());
        } catch (URISyntaxException ex) {
            Logger.getLogger(ServletTest.class.getName()).log(Level.SEVERE, null, ex);
        }
        // путь к файлу страницы
        String filePath = fileCont.toString();
        // получить страницу в строку
        cont = readFileAsString(filePath, fileEncoding);
        // добавить в ассоц. массив контент с ключом $textCont
        selects.put("$textCont", cont);
        
        // замена ключей на значения в шаблоне
        for(Map.Entry entry : selects.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            html = html.replace(key, value);
        }
          
        // вывод в браузер
        PrintWriter out = response.getWriter();
        try {
            out.println(html);
        } finally {            
            out.close();
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    @Override
    public String getServletInfo() {
        return "Short description";
    }// 
}
  

Развертывание проекта на сервере и набор в браузере http://localhost:8080/JavaWebTest/text1.html даст результат

Набор в браузере http://localhost:8080/JavaWebTest/text2.html даст результат

В конечном итоге мы получили шаблонизатор на Java который реагирует на любой запрос с расширением .html и отдает клиенту шаблон index.html с контентом в зависимости от URI запроса.

Кому пригодился данный материал или просто пробудил некоторый интерес оставьте пожалуйста свой коммент.

Top.Mail.Ru