2009-11-12 9 views
11

프로그래밍 방식으로 JSP 페이지를 렌더링해야합니다. 늘어나는만큼 이해, JSP로 일부 컴파일러가 있어야합니다. 질문은 JspServlet과 다른 컴파일러없이 dirrectly이 컴파일러를 사용할 수 있습니까? 필요한 것은 JSP 컴파일러 (Jasper, 예를 들어)를 사용하는 방법에 대한 문서입니다.JSP 프로그래밍 방식으로 렌더링

몇 가지 추가 정보가 상황을 명확하게 할 것이라고 생각합니다. 표준 JspServlet을 사용할 수 없습니다. 나는 JSP 컴파일러를 직접 사용하여 InputStream (또는 Reader)에서 JSP 결과를 컴파일하는 방법이 필요하다.

두 JSP의 병합은 레이아웃 요구 사항입니다. 당신은 물을 수 있습니다 : "하지만이 사람은 왜 이런 식으로 SiteMesh를 사용하지 않습니까?". JSP 페이지 중 하나가 정적이지 않습니다. 그것은 사용자가 제공하고 데이터베이스에 저장됩니다. 우리는이 JSP 레이아웃을 sanitify 및 검증합니다 (사용자는 태그의 하위 세트 만 사용할 수 있으며 모든 태그는 standart가 아니라 특별히 생성되었습니다). 하지만 이제는 사용자가 요청한 모든 JSP 페이지의 레이아웃으로 메모리에 저장된 JSP 페이지를 사용하는 방법이 필요합니다.

+1

나는 유사한 문제가 있었는데, 내가 발견 한 "가장 쉬운"해결책은 전체 프로젝트를 Velocity (또는 다른 템플릿 엔진)로 전환하는 것이었고 그러한 작업은 사소한 작업이었습니다. 그런 변화를 만들기 위해 이미 너무 멀리 개발 된 것처럼 보이지만 단지 말하고있는 것 같습니다 ... – serg

답변

8

내가 programmaticaly JSP 페이지를 렌더링하는 필요를 위해 다음과 같습니다 : 나는 JSP를 추천 할 것입니다.

결국 기능적 요구 사항은 무엇입니까? 당신은 분명히 잘못된 방향으로 해결책을 찾고 있습니다. 이것이 해결책이라고 생각하는 문제/요구 사항은 무엇입니까? 우리는 더 나은 제안을 내놓을 수 있습니다.

출력 예 : 출력이일까요? 그렇다면 java.net.URLConnection면 충분합니다.

편집 : 당신은 당신의 질문 편집 :

나는 어떤 방법으로 컴파일 전에 소스 JSP를 변경하려면

(정확히 말하면 두 개의 JSP를 병합)를, 그래서 JSP 결과를 컴파일하는 방법이 필요합니다 JSP 컴파일러를 직접 사용하여 InputStream (또는 Reader)에서.

확인, 그건 비트 더 분명하다. 그러나 당신은 이것을 위해 무엇을 필요로합니까? JSP가 실제로 무엇을 나타 냅니까? 사용 된 최종 결과는 무엇입니까?

예를 들어 하나의 JSP를 다른 JSP에 포함하고 싶습니까? 예 : main.jsphead.jsp을 포함하고 있습니까? 그렇다면 <jsp:include>이면 충분합니다. 아니면 재사용하고 싶었던 특정 코드로 원시 Java 코드를 포함하고 있습니까? 그렇다면 일반 Java 클래스를 사용하고 필요한 경우 taglib을 사용해야합니다.

편집 2 : 당신이 주석으로 :

하지만 지금 우리가 사용하는 모든 JSP 페이지에 대한 레이아웃 등 (저장소 방법으로 메모리에있는)이 JSP 페이지를 사용하는 방법이 필요합니다 합니다 (ServletContext#getRealPath() 여기에 구조에 올 수)

그냥 웹 애플리케이션의 웹 콘텐츠 내부의 디스크 파일 시스템에있는 JSP 파일을 저장할 요청하고 시험을 사용하여 두 JSP 파일이 포함 자신의 주 JSP 파일에 대한 요청을 전달 PLE :

<jsp:include page="${page1}" /> 
<jsp:include page="${page2}" /> 

편집 3 : 나는 그것의 작업을 증명하기 위해 SSCCE를 만들었습니다.

package mypackage; 

import java.io.BufferedWriter; 
import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.OutputStreamWriter; 

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

public class TestServlet extends HttpServlet { 

    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
     throws ServletException, IOException 
    { 
     File root = new File(getServletContext().getRealPath("/")); 

     String main = "<jsp:include page=\"${page1}\" /><jsp:include page=\"${page2}\" />"; 
     write(main, new File(root, "main.jsp")); 

     String page1 = "<p>We are in ${data1}"; 
     write(page1, new File(root, "page1.jsp")); 
     request.setAttribute("page1", "page1.jsp"); 
     request.setAttribute("data1", "first jsp"); 

     String page2 = "<p>We are in ${data2}"; 
     write(page2, new File(root, "page2.jsp")); 
     request.setAttribute("page2", "page2.jsp"); 
     request.setAttribute("data2", "second jsp"); 

     request.getRequestDispatcher("main.jsp").forward(request, response); 
    } 

    private static void write(String content, File file) throws IOException { 
     BufferedWriter writer = null; 
     try { 
      writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8")); 
      writer.write(content); 
     } finally { 
      if (writer != null) try { writer.close(); } catch (IOException ignore) {} 
     } 
    } 

} 

http://localhost:8080/playground/test (또는 당신이 사용하는 어떤 호스트/contextname)에 그것을 실행하고 당신은

We are in first jsp 
We are in second jsp 

가보다 효율적으로 내가 모든 자원을 캐시 할 수 있도록하기 위해보고에 File#exists()의 사용을 만들 수 있습니다 특정 페이지가 이미 디스크에 저장되어 있는지 확인하십시오.

+0

좋습니다, 필요 조건으로 뛰어 들게하십시오. 두 개의 JSP 병합은 레이아웃 요구 사항입니다. 당신은 물을 수 있습니다 : "하지만이 사람은 왜 이런 식으로 SiteMesh를 사용하지 않습니까?". JSP 페이지 중 하나는 정적 페이지가 아닙니다. 그것은 사용자가 제공하고 데이터베이스에 저장됩니다. 우리는이 JSP 레이아웃을 sanitify 및 검증합니다 (사용자는 태그의 하위 세트 만 사용할 수 있으며 모든 태그는 standart가 아니라 특별히 생성되었습니다). 하지만 이제는 사용자가 요청한 모든 JSP 페이지의 레이아웃으로 이러한 JSP 페이지 (저장소가 메모리에 있음)를 사용하는 방법이 필요합니다. –

+0

좋습니다. 작동합니다. 하지만 JSP를 좀 더 깨끗하게 보이기를 바랍니다. ...처럼 페이지 태그의 하위 페이지가 페이지를 설명합니다. 컴파일시에 페이지 태그가 자동으로 레이아웃으로 대체됩니다. 가능한가요? –

+0

JSP 컨텐츠 상단에 taglib를 포함하면됩니다. 평소 JSP로 코드를 작성하십시오. webapp의 웹 콘텐츠에 저장하기 만하면됩니다. 마지막에 추가 한 SSCCE를 참조하십시오. – BalusC

1

아마도 Tomcat's JspC ant task을 사용할 수 있습니까?

+0

정확히는 아닙니다. 나 혼자서 서버 측에서 JSP를 컴파일해야한다. 그래서 개미 작업은 내가 찾는 것이 아닙니다. 하지만이 작업의 소스 코드를 살펴볼 것입니다. 아마도 도움이 될 것입니다. 고맙습니다. –

1

JSTL은 JSP 파일 내에서 사용되는 태그 라이브러리입니다. 그래서이 문맥에서 정말로 중요하지 않습니다.

JSP 컴파일러가 JSP 파일을 Java Servlet으로 변환하기 때문에 컴파일러가 JSP 파일을 직접 실행하거나 컴파일러에서 JSP 파일을 렌더링 할 수 있는지 의심 스럽습니다.

실제로 찾고있는 질문에 대해 이해하기가 실제로 어렵습니다.

편집 : 작업

+0

예, JSTL이이 컨텍스트에서 불편하다는 언급은 동의합니다. 맞습니다. JSP 페이지는 컴파일 후에 서블릿이됩니다. 필자가 필요로하는 것은 JSP 페이지를 직접 서블릿에 컴파일하는 방법입니다.나는 조금 더 깊은 일을 설명 할 수있다. 두 가지 JSP 파일을 어떤 방식으로 (소스에서) 병합 한 다음 결과를 컴파일해야합니다. –

+0

다른 JSP 파일 중 하나를 포함하는 것으로 충분하지 않습니까? jsp : include 및 <%@include%> –

+0

을 참조하십시오. JSP 병합을위한 규칙은 간단합니다. 근원의 이것은 이것 자체에 의하여 문제, 그러나 ... –

1

JSP가 이미 appserver에 의해 사전 컴파일 된 경우 생성 된 .class 파일을 찾을 수 있습니다. Tomcat에서는 $ CONTEXT_ROOT/org/apache/jsp/디렉토리에 있어야합니다. 어떻게 든이 클래스를 실행하고 출력을 생성 할 수 있습니다.

EDIT : JSP 소스 수정에 대한 편집을 놓쳤습니다.

org.apache.jasper.compiler.AntCompiler (Tomcat의 jasper.jar에 있음)를 살펴보십시오. 재정의 할 수있는 generateClass라는 보호 된 메서드가 있습니다.

1

당신이해야하는 이유는 무엇입니까? 처리 할 2 JSP 파일을 병합해야하는 경우 을 사용하는 경우 또는 다른 아이디어가 필요합니까? 귀하의 요청에 대한 견본을 줄 수 있습니까?

4

찾고있는 것이 확실하지 않지만 WebContext.forwardToString이라는 메서드는 현재 요청과 가짜 응답 개체를 URL에 전달한 다음 버퍼 내용을 메모리로 읽습니다. 당신은 JSP로 rednering의 결과를 얻을 수 및 메모리에 저장하려면이 옵션을 사용할 수

StringWriter sout = new StringWriter(); 
StringBuffer buffer = sout.getBuffer(); 

HttpServletResponse realResponse = getHttpServletResponse(); 
HttpServletResponse fakeResponse = new SwallowingHttpServletResponse(realResponse, sout, realResponse.getCharacterEncoding()); 

HttpServletRequest realRequest = getHttpServletRequest(); 
realRequest.setAttribute(WebContext.ATTRIBUTE_DWR, Boolean.TRUE); 

getServletContext().getRequestDispatcher(url).forward(realRequest, fakeResponse); 

return buffer.toString(); 

다음은 코드의 샘플입니다. SwallowingHttpServletResponse가 어떻게 작동하는지 보려면 위의 링크에서 소스를 다운로드하십시오.

관련 문제