lib의 JAR 내부에서 JSP를 제공 할 수 있습니까? 아니면 해결 방법이 있습니까?
Tomcat 7에 WAR 파일로 배포 된 웹 응용 프로그램이 있습니다. 응용 프로그램은 다중 모듈 프로젝트로 빌드됩니다.
- core-JAR로 패키징되며 대부분의 백엔드 코드를 포함합니다.
- core-api-JAR로 패키징되고 코어에 대한 인터페이스 포함
- webapp-WAR로 패키징되고 프런트 엔드 코드를 포함하며 코어에 따라 다릅니다.
- 고객 확장-JAR로 패키지 된 선택적 모듈
일반적으로 JSP 파일을 webapp 프로젝트에 넣고 컨텍스트와 관련하여 참조 할 수 있습니다.
/WEB-INF/jsp/someMagicalPage.jsp
문제는 WAR에 항상 포함되어서는 안되는 고객 확장 프로젝트에 특정한 JSP 파일에 대해 수행하는 작업입니다. 불행히도 JAR 파일 내에서 JSP를 참조 할 수 없습니다. 시도 classpath:jsp/customerMagicalPage.jsp
하면 JspServlet에서 ServletContext.getResource()
.
전통적으로 우리는 maven이 고객 확장 JAR의 압축을 풀고 JSP를 찾은 다음이를 빌드 할 때 WAR에 넣는 것으로 "해결"했습니다. 그러나 이상적인 상황은 Tomcat에서 폭발 한 WAR에 JAR을 드롭하고 확장이 발견되는 경우입니다. 이는 JSP를 제외한 모든 작업에서 작동합니다.
어쨌든 이것을 해결할 방법이 있습니까? 표준 방법, Tomcat 특정 방법, 해킹 또는 해결 방법? 예를 들어, 애플리케이션 시작시 JSP의 압축을 풀려고 생각했습니다 ...
Tomcat 7이 지원하는 Servlet 3.0에는 jsps를 jar로 패키지화하는 기능이 포함되어 있습니다.
다음을 수행해야합니다.
META-INF/resources
jar 디렉토리에 jsps를 배치하십시오.- 선택적으로 항아리
web-fragment.xml
의META-INF
디렉토리에를 포함하십시오. WEB-INF/lib
전쟁 디렉토리에 항아리를 놓으십시오.
그런 다음 컨텍스트에서 jsps를 참조 할 수 있어야합니다. 예를 들어 jsp가있는 경우 META-INF/resources/test.jsp
컨텍스트의 루트에서이를 다음과 같이 참조 할 수 있어야합니다.test.jsp
해결 방법으로 jar 파일을 열고 특정 패턴과 일치하는 파일을 찾은 다음 해당 파일을 컨텍스트 경로에 상대적인 지정된 위치로 추출하는 클래스를 만들었습니다.
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import javax.annotation.PostConstruct;
import javax.servlet.ServletContext;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.context.ServletContextAware;
/**
* Allows extraction of contents of a JAR file. All files matching a given Ant path pattern will be extracted into a
* specified path.
*/
public class JarFileResourcesExtractor implements ServletContextAware {
private String resourcePathPattern;
private String jarFile;
private String destination;
private ServletContext servletContext;
private AntPathMatcher pathMatcher = new AntPathMatcher();
/**
* Creates a new instance of the JarFileResourcesExtractor
*
* @param resourcePathPattern
* The Ant style path pattern (supports wildcards) of the resources files to extract
* @param jarFile
* The jar file (located inside WEB-INF/lib) to search for resources
* @param destination
* Target folder of the extracted resources. Relative to the context.
*/
private JarFileResourcesExtractor(String resourcePathPattern, String jarFile, String destination) {
this.resourcePathPattern = resourcePathPattern;
this.jarFile = jarFile;
this.destination = destination;
}
/**
* Extracts the resource files found in the specified jar file into the destination path
*
* @throws IOException
* If an IO error occurs when reading the jar file
* @throws FileNotFoundException
* If the jar file cannot be found
*/
@PostConstruct
public void extractFiles() throws IOException {
try {
String path = servletContext.getRealPath("/WEB-INF/lib/" + jarFile);
JarFile jarFile = new JarFile(path);
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (pathMatcher.match(resourcePathPattern, entry.getName())) {
String fileName = entry.getName().replaceFirst(".*\\/", "");
File destinationFolder = new File(servletContext.getRealPath(destination));
InputStream inputStream = jarFile.getInputStream(entry);
File materializedJsp = new File(destinationFolder, fileName);
FileOutputStream outputStream = new FileOutputStream(materializedJsp);
copyAndClose(inputStream, outputStream);
}
}
}
catch (MalformedURLException e) {
throw new FileNotFoundException("Cannot find jar file in libs: " + jarFile);
}
catch (IOException e) {
throw new IOException("IOException while moving resources.", e);
}
}
@Override
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
public static int IO_BUFFER_SIZE = 8192;
private static void copyAndClose(InputStream in, OutputStream out) throws IOException {
try {
byte[] b = new byte[IO_BUFFER_SIZE];
int read;
while ((read = in.read(b)) != -1) {
out.write(b, 0, read);
}
} finally {
in.close();
out.close();
}
}
}
그런 다음 Spring XML에서 Bean으로 구성합니다.
<bean id="jspSupport" class="se.waxwing.util.JarFileResourcesExtractor">
<constructor-arg index="0" value="jsp/*.jsp"/>
<constructor-arg index="1" value="myJarFile-1.1.0.jar"/>
<constructor-arg index="2" value="WEB-INF/classes/jsp"/>
</bean>
정말 성가신 문제에 대한 최적의 솔루션이 아닙니다. 이제 질문은이 코드를 유지하는 사람이 와서이 일을하면서 잠을 잘 때 나를 죽일까요?
이러한 해결 방법이 있습니다. JSP를 서블릿으로 사전 컴파일 할 수 있습니다. 따라서 JAR에 넣고 web.xml에서 일부 URL에 매핑 할 수있는 .class 파일을 얻을 수 있습니다.
Struts 2 팀은 임베디드 JSP 용 플러그인을 추가했습니다. 아마도 그것은 광고 기반으로 사용될 수 있습니다.
https://struts.apache.org/plugins/embedded-jsp/
이것은 servlet 2.5보다 더 높은 것을 할 수없는 서버를 사용했기 때문에 내가 사용했던 waxwing 답변에 대한 follup입니다.
Bean이 파괴 될 때 추가 된 파일을 제거하는 메소드를 추가했습니다.
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.servlet.ServletContext;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.context.ServletContextAware;
import com.sap.tc.logging.Location;
/**
* Allows extraction of contents of a JAR file. All files matching a given Ant path pattern will be extracted into a
* specified path.
* Copied from http://stackoverflow.com/questions/5013917/can-i-serve-jsps-from-inside-a-jar-in-lib-or-is-there-a-workaround
*/
public class JarFileResourcesExtractor implements ServletContextAware {
private final transient Location logger = Location.getLocation(JarFileResourcesExtractor.class);
private String resourcePathPattern;
private String jarFile;
private String destination;
private ServletContext servletContext;
private AntPathMatcher pathMatcher = new AntPathMatcher();
private List<File> listOfCopiedFiles = new ArrayList<File>();
/**
* Creates a new instance of the JarFileResourcesExtractor
*
* @param resourcePathPattern
* The Ant style path pattern (supports wildcards) of the resources files to extract
* @param jarFile
* The jar file (located inside WEB-INF/lib) to search for resources
* @param destination
* Target folder of the extracted resources. Relative to the context.
*/
public JarFileResourcesExtractor(String resourcePathPattern, String jarFile, String destination) {
this.resourcePathPattern = resourcePathPattern;
this.jarFile = jarFile;
this.destination = destination;
}
@PreDestroy
public void removeAddedFiles() throws IOException{
logger.debugT("I removeAddedFiles()");
for (File fileToRemove : listOfCopiedFiles) {
if(fileToRemove.delete()){
logger.debugT("Tagit bort filen " + fileToRemove.getAbsolutePath());
}
}
}
/**
* Extracts the resource files found in the specified jar file into the destination path
*
* @throws IOException
* If an IO error occurs when reading the jar file
* @throws FileNotFoundException
* If the jar file cannot be found
*/
@PostConstruct
public void extractFiles() throws IOException {
try {
String path = servletContext.getRealPath("/WEB-INF/lib/" + jarFile);
JarFile jarFile = new JarFile(path);
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if (pathMatcher.match(resourcePathPattern, entry.getName())) {
String fileName = entry.getName().replaceFirst(".*\\/", "");
File destinationFolder = new File(servletContext.getRealPath(destination));
InputStream inputStream = jarFile.getInputStream(entry);
File materializedJsp = new File(destinationFolder, fileName);
listOfCopiedFiles.add(materializedJsp);
FileOutputStream outputStream = new FileOutputStream(materializedJsp);
copyAndClose(inputStream, outputStream);
}
}
}
catch (MalformedURLException e) {
throw new FileNotFoundException("Cannot find jar file in libs: " + jarFile);
}
catch (IOException e) {
throw new IOException("IOException while moving resources.", e);
}
}
@Override
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
public static int IO_BUFFER_SIZE = 8192;
private static void copyAndClose(InputStream in, OutputStream out) throws IOException {
try {
byte[] b = new byte[IO_BUFFER_SIZE];
int read;
while ((read = in.read(b)) != -1) {
out.write(b, 0, read);
}
} finally {
in.close();
out.close();
}
}
}
그런 다음 모든 Java 구성을 사용할 수 있도록 생성자를 변경했습니다.
@Bean
public JarFileResourcesExtractor jspSupport(){
final JarFileResourcesExtractor extractor = new JarFileResourcesExtractor("WEB-INF/pages/*.jsp","myJarFile-1.1.0.jar","WEB-INF/pages" );
return extractor;
}
누군가에게 도움이되기를 바랍니다!
'IT Share you' 카테고리의 다른 글
GraphViz에서 범례 / 키 만들기 (0) | 2020.12.01 |
---|---|
피클과 선반의 차이점은 무엇입니까? (0) | 2020.12.01 |
SQL Server 2008 R2에서 원격 프로 시저 호출이 실패했습니다. (0) | 2020.12.01 |
목록 목록을 병합하는 방법은 무엇입니까? (0) | 2020.12.01 |
Intellij 2017.2 / out 디렉토리로 빌드하면 / build 디렉토리의 파일이 중복됩니다. (0) | 2020.12.01 |