Hintergrund des Problems
Das erste, was zu verstehen ist folgende: Es ist Frühling nicht, welche die jsp Dateien macht. Es ist JspServlet (org.apache.jasper.servlet.JspServlet), die es tut. Dieses Servlet kommt mit Tomcat (Jaspis Compiler) nicht mit Feder. Dieses JspServlet weiß, wie man die JSP-Seite kompiliert und sie als HTML-Text an den Client zurückgibt. Das JspServlet in tomcat verarbeitet standardmäßig nur Anforderungen, die zwei Mustern entsprechen: * .jsp und * .jspx.
Nun, wenn der Frühling die Ansicht mit InternalResourceView
macht (oder JstlView
), drei Dinge wirklich stattfindet:
- erhalten alle Modellparameter aus Modell (von dem Controller-Handler-Methode, dh
"public ModelAndView doSomething() { return new ModelAndView("home") }"
zurückgegeben)
- aussetzen Diese Modellparameter als Anforderungsattribute (so dass sie von JspServlet gelesen werden können)
- Weiterleiten von Anforderung an JspServlet.
RequestDispatcher
weiß, dass jeder * .jsp Anfrage an JspServlet weitergeleitet werden soll (da diese Standardkonfiguration des Katers ist)
Wenn Sie einfach den Namen home.html Kater Ansicht ändern nicht wissen, wie die Anfrage zu bearbeiten. Dies liegt daran, dass keine Servlet-Handling * .html-Anfragen vorliegen.
Lösung
wie diese zu lösen. Es gibt drei naheliegendste Lösung:
- die HTML als Datei
- Ressource setzen die JspServlet anweisen, auch handhaben * .html fordert
- Ihre eigenen Servlet schreiben (oder auf einen anderen bestehenden Servlet-Anforderungen werden an * .html).
Erstkonfiguration (nur Umgang mit jsp)
Zuerst nehmen wir an, wir Frühling ohne XML-Dateien (nur gründend auf @Configuration Anmerkung und Feder der WebApplicationInitializer Schnittstelle) konfigurieren.
Grundkonfiguration würde folgende
public class MyWebApplicationContext extends AnnotationConfigWebApplicationContext {
private static final String CONFIG_FILES_LOCATION = "my.application.root.config";
public MyWebApplicationContext() {
super();
setConfigLocation(CONFIG_FILES_LOCATION);
}
}
public class AppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
WebApplicationContext context = new MyWebApplicationContext();
servletContext.addListener(new ContextLoaderListener(context));
addSpringDispatcherServlet(servletContext, context);
}
private void addSpringDispatcherServlet(ServletContext servletContext, WebApplicationContext context) {
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet",
new DispatcherServlet(context));
dispatcher.setLoadOnStartup(2);
dispatcher.addMapping("/");
dispatcher.setInitParameter("throwExceptionIfNoHandlerFound", "true");
}
}
package my.application.root.config
// (...)
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Autowired
@Qualifier("jstlViewResolver")
private ViewResolver jstlViewResolver;
@Bean
@DependsOn({ "jstlViewResolver" })
public ViewResolver viewResolver() {
return jstlViewResolver;
}
@Bean(name = "jstlViewResolver")
public ViewResolver jstlViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/internal/");
resolver.setViewClass(JstlView.class);
resolver.setSuffix(".jsp");
return resolver;
}
}
Im obigen Beispiel ich mit Rückenansicht Klasse JstlView mit UrlBasedViewResolver, aber Sie können wie in Ihrem Beispiel verwenden InternalResourceViewResolver es keine Rolle spielt.
Das obige Beispiel konfiguriert die Anwendung mit nur einem Ansichtsresolver, der JSP-Dateien behandelt, die mit .jsp
enden. HINWEIS: Wie bereits am Anfang erwähnt, verwendet JstlView Tomcat's RequestDispatcher, um die Anfrage an JspSevlet weiterzuleiten, um das JSP in HTML zu kompilieren.
Implementierung auf Lösung 1 - Setzen Sie die HTML als eine Ressource-Datei:
Wir haben die WebConfig-Klasse ändern, um neue Ressourcen Anpassung hinzuzufügen.Auch müssen wir die jstlViewResolver so modifizieren, dass es nicht weder Präfix noch Suffix nehmen:
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Autowired
@Qualifier("jstlViewResolver")
private ViewResolver jstlViewResolver;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/someurl/resources/**").addResourceLocations("/resources/");
}
@Bean
@DependsOn({ "jstlViewResolver" })
public ViewResolver viewResolver() {
return jstlViewResolver;
}
@Bean(name = "jstlViewResolver")
public ViewResolver jstlViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix(""); // NOTE: no preffix here
resolver.setViewClass(JstlView.class);
resolver.setSuffix(""); // NOTE: no suffix here
return resolver;
}
// NOTE: you can use InternalResourceViewResolver it does not matter
// @Bean(name = "internalResolver")
// public ViewResolver internalViewResolver() {
// InternalResourceViewResolver resolver = new InternalResourceViewResolver();
// resolver.setPrefix("");
// resolver.setSuffix("");
// return resolver;
// }
}
Damit fügen wir sagen, dass jeder, dass jeder Antrag auf http://my.server/someurl/resources/ gehen auf Ressourcen-Verzeichnis unter Ihrem Web-Verzeichnis zugeordnet. Also, wenn Sie Ihre home.html in Ressourcen-Verzeichnis setzen und Ihren Browser auf http://my.server/someurl/resources/home.html zeigen, wird die Datei geliefert. Um damit umzugehen, indem Sie Ihre Controller kehren Sie dann den vollständigen Pfad zu der Ressource:
@Controller
public class HomeController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView home(Locale locale, Model model) {
// (...)
return new ModelAndView("/someurl/resources/home.html"); // NOTE here there is /someurl/resources
}
}
Wenn Sie im selben Verzeichnis legen einige jsp Dateien (nicht nur * .html-Dateien), sagen home_dynamic.jsp in den gleichen Ressourcen Verzeichnis können Sie auf ähnliche Weise zugreifen, aber Sie müssen den tatsächlichen Pfad auf dem Server verwenden. Der Pfad tut nicht Start mit/Someurl/weil dies die Zuordnung nur für HTML-Ressourcen mit Endung .html ist). In diesem Kontext ist jsp eine dynamische Ressource, auf die am Ende von JspServlet mit dem tatsächlichen Pfad auf der Festplatte zugegriffen wird. So richtige Weg, um die jsp zuzugreifen, ist:
@Controller
public class HomeController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView home(Locale locale, Model model) {
// (...)
return new ModelAndView("/resources/home_dynamic.jsp"); // NOTE here there is /resources (there is no /someurl/ because "someurl" is only for static resources
}
dies in Config XML-basierte Um dies zu erreichen müssen Sie verwenden:
<mvc:resources mapping="/someurl/resources/**" location="/resources/" />
und ändern Sie Ihre jstl Ansicht Resolver:
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <!-- Please NOTE that it does not matter if you use InternalResourceViewResolver or UrlBasedViewResolver as in annotations example -->
<beans:property name="prefix" value="" />
<beans:property name="suffix" value="" />
</beans:bean>
Implementierung auf Lösung 2:
In dieser Option verwenden wir den Tomcat 's JspServlet, um auch statische Dateien zu verarbeiten. Als Folge können Sie JSP-Tags in Ihren HTML-Dateien verwenden :) Es ist natürlich Ihre Wahl, ob Sie es tun oder nicht. Höchstwahrscheinlich möchten Sie plain html verwenden, also verwenden Sie einfach keine jsp Tags und der Inhalt wird so geliefert, als wäre es statisches html.
Zuerst haben wir preffix und Suffix für Ansicht Resolver als in vorherigen Beispiel löschen:
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Autowired
@Qualifier("jstlViewResolver")
private ViewResolver jstlViewResolver;
@Bean
@DependsOn({ "jstlViewResolver" })
public ViewResolver viewResolver() {
return jstlViewResolver;
}
@Bean(name = "jstlViewResolver")
public ViewResolver jstlViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver(); // NOTE: this time I'm using InternalResourceViewResolver and again it does not matter :)
resolver.setPrefix("");
resolver.setSuffix("");
return resolver;
}
}
Nun fügen wir JspServlet für die Handhabung auch * .html-Dateien:
public class AppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
WebApplicationContext context = new MyWebApplicationContext();
servletContext.addListener(new ContextLoaderListener(context));
addStaticHtmlFilesHandlingServlet(servletContext);
addSpringDispatcherServlet(servletContext, context);
}
// (...)
private void addStaticHtmlFilesHandlingServlet(ServletContext servletContext) {
ServletRegistration.Dynamic servlet = servletContext.addServlet("HtmlsServlet", new JspServlet()); // org.apache.jasper.servlet.JspServlet
servlet.setLoadOnStartup(1);
servlet.addMapping("*.html");
}
}
wichtig das ist, dies zu machen Klasse verfügbar Sie müssen das jasper.jar nur zur Kompilierzeit aus der Tomcat-Installation hinzufügen. Wenn Sie Maven App haben, ist dies relativ einfach, indem Sie den für das Glas vorgesehenen scope = verwenden. Die Abhängigkeit in maven wird wie folgt aussehen:
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper</artifactId>
<version>${tomcat.libs.version}</version>
<scope>provided</scope> <!--- NOTE: scope provided! -->
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jsp-api</artifactId>
<version>${tomcat.libs.version}</version>
<scope>provided</scope>
</dependency>
Wenn Sie es auf XML-Weise tun möchten. Sie müßten jsp Servlet registrieren * .html Anfragen zu bearbeiten, so müssen Sie folgenden Eintrag in Ihrem web.xml
<servlet>
<servlet-name>htmlServlet</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>htmlServlet</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
Jetzt in Ihrem Controller hinzuzufügen, die Sie HTML und JSP-Dateien ebenso wie in vorherigem Beispiel zugreifen können . Der Vorteil ist, dass es keine "/ someurl /" zusätzliche Zuordnung gibt, die in Lösung 1 benötigt wurde.Ihr Controller wird wie folgt aussehen:
@Controller
public class HomeController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView home(Locale locale, Model model) {
// (...)
return new ModelAndView("/resources/home.html");
}
zu Ihrem jsp Punkt Sie tun genau das gleiche:
@Controller
public class HomeController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView home(Locale locale, Model model) {
// (...)
return new ModelAndView("/resources/home_dynamic.jsp");
}
Implementierung auf Lösung 3:
dritte Lösung ist etwas eine Kombination aus Lösung 1 und Lösung 2. Also hier wollen wir alle Anfragen an * .html an ein anderes Servlet übergeben. Sie können Ihre eigenen schreiben oder nach einem guten Kandidaten für ein bereits bestehendes Servlet suchen.
Wie oben zuerst reinigen wir das Präfix und Suffix für die Ansicht Resolver auf:
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Autowired
@Qualifier("jstlViewResolver")
private ViewResolver jstlViewResolver;
@Bean
@DependsOn({ "jstlViewResolver" })
public ViewResolver viewResolver() {
return jstlViewResolver;
}
@Bean(name = "jstlViewResolver")
public ViewResolver jstlViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver(); // NOTE: this time I'm using InternalResourceViewResolver and again it does not matter :)
resolver.setPrefix("");
resolver.setSuffix("");
return resolver;
}
}
Anstatt nun die Tomcats JspServlet verwenden wir unsere eigenen Servlet schreiben (oder wieder verwenden einige bestehende):
public class StaticFilesServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
String resourcePath = request.getRequestURI();
if (resourcePath != null) {
FileReader reader = null;
try {
URL fileResourceUrl = request.getServletContext().getResource(resourcePath);
String filePath = fileResourceUrl.getPath();
if (!new File(filePath).exists()) {
throw new IllegalArgumentException("Resource can not be found: " + filePath);
}
reader = new FileReader(filePath);
int c = 0;
while (c != -1) {
c = reader.read();
if (c != -1) {
response.getWriter().write(c);
}
}
} finally {
if (reader != null) {
reader.close();
}
}
}
}
}
zu * .html zu unserem Servlet
Wir weisen nun die Feder um alle Anfragen zu passieren
public class AppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
WebApplicationContext context = new MyWebApplicationContext();
servletContext.addListener(new ContextLoaderListener(context));
addStaticHtmlFilesHandlingServlet(servletContext);
addSpringDispatcherServlet(servletContext, context);
}
// (...)
private void addStaticHtmlFilesHandlingServlet(ServletContext servletContext) {
ServletRegistration.Dynamic servlet = servletContext.addServlet("HtmlsServlet", new StaticFilesServlet());
servlet.setLoadOnStartup(1);
servlet.addMapping("*.html");
}
}
Der Vorteil (oder Nachteil, hängt davon ab, was Sie wollen) ist, dass JSP-Tags offensichtlich nicht verarbeitet werden. Sie Controller sieht wie gewohnt:
@Controller
public class HomeController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView home(Locale locale, Model model) {
// (...)
return new ModelAndView("/resources/home.html");
}
Und für jsp:
@Controller
public class HomeController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView home(Locale locale, Model model) {
// (...)
return new ModelAndView("/resources/home_dynamic.jsp");
}
Wenn es sich um eine statische Datei ist, dann müssen Sie Feder mvc statische Ressourcenzuordnung –
Ex ' ' –
und Sie können den 'InternalResourceViewResolver' entfernen, da keine Verarbeitung erforderlich ist –