1. Introduction
1.引言
This article will provide an overview of how to register a servlet within Jakarta EE and Spring Boot. Specifically, we will look at two ways to register a Java Servlet in Jakarta EE — one using a web.xml file, and the other using annotations. Then we’ll register servlets in Spring Boot using XML configuration, Java configuration, and through configurable properties.
本文将提供如何在Jakarta EE和Spring Boot中注册servlet的概述。具体而言,我们将研究在Jakarta EE中注册Java Servlet的两种方法–一种是使用web.xml文件,另一种是使用注解。然后,我们将在Spring Boot中使用XML配置、Java配置,以及通过可配置的属性来注册Servlet。
A great introductory article on servlets can be found here.
关于servlets的一篇很好的介绍性文章可以在这里找到。
2. Registering Servlets in Jakarta EE
2.在Jakarta EE中注册Servlet[/strong]
Let’s go over two ways to register a servlet in Jakarta EE. First, we can register a servlet via web.xml. Alternatively, we can use the Jakarta EE @WebServlet annotation.
让我们来看看在Jakarta EE中注册servlet的两种方法。首先,我们可以通过web.xml注册一个servlet。或者,我们可以使用Jakarta EE的@WebServlet注解。
2.1. Via web.xml
2.1.通过web.xml
The most common way to register a servlet within your Jakarta EE application is to add it to your web.xml file:
在Jakarta EE应用程序中注册servlet的最常见方法是将其添加到web.xml文件中。
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Example</servlet-name>
<servlet-class>com.baeldung.Example</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Example</servlet-name>
<url-pattern>/Example</url-pattern>
</servlet-mapping>
As you can see, this involves two steps: (1) adding our servlet to the servlet tag, making sure to also specify the source path to the class the servlet resides within, and (2) specifying the URL path the servlet will be exposed on in the url-pattern tag.
正如你所看到的,这涉及两个步骤。(1)在servlet标签中添加我们的Servlet,确保同时指定Servlet所在类的源路径,以及(2)在url-pattern标签中指定Servlet将被曝光的URL路径。
The Jakarta EE web.xml file is usually found in WebContent/WEB-INF.
Jakarta EE的web.xml文件通常在WebContent/WEB-INF中找到。
2.2. Via Annotations
2.2.通过注解
Now let’s register our servlet using the @WebServlet annotation on our custom servlet class. This eliminates the need for servlet mappings in the server.xml and registration of the servlet in web.xml:
现在让我们使用@WebServlet注解来注册我们的servlet类。这样就不需要在server.xml中的servlet映射和在web.xml中注册servlet了。
@WebServlet(
name = "AnnotationExample",
description = "Example Servlet Using Annotations",
urlPatterns = {"/AnnotationExample"}
)
public class Example extends HttpServlet {
@Override
protected void doGet(
HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<p>Hello World!</p>");
}
}
The code above demonstrates how to add that annotation directly to a servlet. The servlet will still be available at the same URL path as before.
上面的代码演示了如何将该注解直接添加到一个servlet中。该servlet仍然可以在与之前相同的URL路径下使用。
3. Registering Servlets in Spring Boot
3.在Spring Boot中注册Servlets
Now that we’ve shown how to register servlets in Jakarta EE, let’s take a look at several ways to register servlets in a Spring Boot application.
现在我们已经展示了如何在Jakarta EE中注册servlet,让我们看看在Spring Boot应用程序中注册servlet的几种方法。
3.1. Programmatic Registration
3.1.程序化注册
Spring Boot supports 100% programmatic configuration of a web application.
Spring Boot支持100%的网络应用程序化配置。
First, we’ll implement the WebApplicationInitializer interface, then implement the WebMvcConfigurer interface,which allows you to override preset defaults instead of having to specify each particular configuration setting, saving you time and allowing you to work with several tried and true settings out-of-the-box.
首先,我们将实现WebApplicationInitializer接口,然后实现WebMvcConfigurer接口,它允许你覆盖预设的默认值,而不是指定每一个特定的配置设置,节省你的时间,并允许你使用几个尝试过的真正的设置开箱即用。
Let’s look at a sample WebApplicationInitializer implementation:
让我们看看一个样本WebApplicationInitializer实现。
public class WebAppInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext ctx
= new AnnotationConfigWebApplicationContext();
ctx.register(WebMvcConfigure.class);
ctx.setServletContext(container);
ServletRegistration.Dynamic servlet = container.addServlet(
"dispatcherExample", new DispatcherServlet(ctx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/");
}
}
Next, let’s implement the WebMvcConfigurer interface:
接下来,让我们实现WebMvcConfigurer接口。
@Configuration
public class WebMvcConfigure implements WebMvcConfigurer {
@Bean
public ViewResolver getViewResolver() {
InternalResourceViewResolver resolver
= new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/");
resolver.setSuffix(".jsp");
return resolver;
}
@Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/").setCachePeriod(3600)
.resourceChain(true).addResolver(new PathResourceResolver());
}
}
Above we specify some of the default settings for JSP servlets explicitly in order to support .jsp views and static resource serving.
上面我们明确指定了JSP servlets的一些默认设置,以支持.jsp视图和静态资源服务。
3.2. XML Configuration
3.2.XML配置
Another way to configure and register servlets within Spring Boot is through web.xml:
在Spring Boot中配置和注册servlets的另一种方式是通过web.xml。
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/dispatcher.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
The web.xml used to specify configuration in Spring is similar to that found in Jakarta EE. Above, you can see how we specify a few more parameters via attributes under the servlet tag.
在Spring中用于指定配置的web.xml与Jakarta EE中的配置相似。在上面,你可以看到我们如何通过servlet标签下的属性指定一些更多的参数。
Here we use another XML to complete the configuration:
这里我们使用另一个XML来完成配置。
<beans ...>
<context:component-scan base-package="com.baeldung"/>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
Remember that your Spring web.xml will usually live in src/main/webapp/WEB-INF.
记住,你的Spring web.xml通常会在src/main/webapp/WEB-INF中。
3.3. Combining XML and Programmatic Registration
3.3.结合XML和程序化注册
Let’s mix an XML configuration approach with Spring’s programmatic configuration:
让我们把XML配置方法和Spring的程序化配置混合起来。
public void onStartup(ServletContext container) throws ServletException {
XmlWebApplicationContext xctx = new XmlWebApplicationContext();
xctx.setConfigLocation('classpath:/context.xml');
xctx.setServletContext(container);
ServletRegistration.Dynamic servlet = container.addServlet(
"dispatcher", new DispatcherServlet(ctx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/");
}
Let’s also configure the dispatcher servlet:
让我们也来配置一下dispatcher servlet。
<beans ...>
<context:component-scan base-package="com.baeldung"/>
<bean class="com.baeldung.configuration.WebAppInitializer"/>
</beans>
3.4. Registration by Bean
3.4.按Bean注册
We can also programmatically configure and register our servlets using a ServletRegistrationBean. Below we’ll do so in order to register an HttpServlet (which implements the javax.servlet.Servlet interface):
我们还可以使用ServletRegistrationBean以编程方式配置和注册我们的Servlet。下面我们将这样做,以注册一个HttpServlet(它实现了javax.servlet.Servlet接口)。
@Bean
public ServletRegistrationBean exampleServletBean() {
ServletRegistrationBean bean = new ServletRegistrationBean(
new CustomServlet(), "/exampleServlet/*");
bean.setLoadOnStartup(1);
return bean;
}
The main advantage of this approach is that it enables you to add both multiple servlets as well as different kinds of servlets to your Spring application.
这种方法的主要优点是,它可以让你在Spring应用程序中同时添加多个Servlet以及不同种类的Servlet。
Instead of merely utilizing a DispatcherServlet, which is a more specific kind of HttpServlet and the most common kind used in the WebApplicationInitializer programmatic approach to configuration we explored in section 3.1, we’ll use a simpler HttpServlet subclass instance which exposes the four basic HttpRequest operations through four functions: doGet(), doPost(), doPut(), and doDelete() just like in Jakarta EE.
我们将使用一个更简单的DispatcherServlet子类实例,它是HttpServlet的一种更具体的类型,也是我们在第3.1节中探讨的WebApplicationInitializer程序化配置方法中最常用的类型,而不是仅仅利用它,它通过四个函数暴露了四个基本HttpRequest操作。doGet(), doPost(), doPut(), 和doDelete()就像在Jakarta EE中一样。
Remember that HttpServlet is an abstract class (so it can’t be instantiated). We can whip up a custom extension easily, though:
记住,HttpServlet是一个抽象类(所以它不能被实例化)。不过,我们可以很容易地编写一个自定义扩展。
public class CustomServlet extends HttpServlet{
...
}
4. Registering Servlets With Properties
4.用属性注册Servlet
Another, though uncommon, way to configure and register your servlets is to use a custom properties file loaded into the app via a PropertyLoader, PropertySource, or PropertySources instance object.
另一种虽然不常见的配置和注册servlets的方法是使用一个自定义的属性文件,通过PropertyLoader, PropertySource, orPropertySources instance object加载到应用程序。
This provides an intermediate kind of configuration and the ability to otherwise customize application.properties which provide little direct configuration for non-embedded servlets.
这提供了一种中间的配置,以及以其他方式定制application.properties的能力,这对非嵌入的servlets来说几乎不提供直接配置。
4.1. System Properties Approach
4.1.系统属性方法
We can add some custom settings to our application.properties file or another properties file. Let’s add a few settings to configure our DispatcherServlet:
我们可以在我们的 application.properties文件或另一个属性文件中添加一些自定义设置。让我们添加一些设置来配置我们的DispatcherServlet。
servlet.name=dispatcherExample
servlet.mapping=/dispatcherExampleURL
Let’s load our custom properties into our application:
让我们把我们的自定义属性加载到我们的应用程序。
System.setProperty("custom.config.location", "classpath:custom.properties");
And now we can access those properties via:
而现在我们可以通过以下方式访问这些属性。
System.getProperty("custom.config.location");
4.2. Custom Properties Approach
4.2.自定义属性方法
Let’s start with a custom.properties file:
让我们从一个custom.properties文件开始。
servlet.name=dispatcherExample
servlet.mapping=/dispatcherExampleURL
We can then use a run-of-the-mill Property Loader:
然后我们可以使用一个普通的属性加载器。
public Properties getProperties(String file) throws IOException {
Properties prop = new Properties();
InputStream input = null;
input = getClass().getResourceAsStream(file);
prop.load(input);
if (input != null) {
input.close();
}
return prop;
}
And now we can add these custom properties as constants to our WebApplicationInitializer implementation:
而现在我们可以将这些自定义属性作为常量添加到我们的WebApplicationInitializer实现中。
private static final PropertyLoader pl = new PropertyLoader();
private static final Properties springProps
= pl.getProperties("custom_spring.properties");
public static final String SERVLET_NAME
= springProps.getProperty("servlet.name");
public static final String SERVLET_MAPPING
= springProps.getProperty("servlet.mapping");
We can then use them to, for example, configure our dispatcher servlet:
然后,我们可以用它们来配置我们的分配器servlet,例如。
ServletRegistration.Dynamic servlet = container.addServlet(
SERVLET_NAME, new DispatcherServlet(ctx));
servlet.setLoadOnStartup(1);
servlet.addMapping(SERVLET_MAPPING);
The advantage of this approach is the absence of .xml maintenance but with easy-to-modify configuration settings that don’t require redeploying the codebase.
这种方法的优点是没有.xml维护,但配置设置容易修改,不需要重新部署代码库。
4.3. The PropertySource Approach
4.3.PropertySource方法
A faster way to accomplish the above is to make use of Spring’s PropertySource which allows a configuration file to be accessed and loaded.
完成上述工作的更快方法是利用Spring的PropertySource,它允许访问和加载一个配置文件。
PropertyResolver is an interface implemented by ConfigurableEnvironment, which makes application properties available at servlet startup and initialization:
PropertyResolver是一个由ConfigurableEnvironment>实现的接口,它使应用程序属性在Servlet启动和初始化时可用。
@Configuration
@PropertySource("classpath:/com/yourapp/custom.properties")
public class ExampleCustomConfig {
@Autowired
ConfigurableEnvironment env;
public String getProperty(String key) {
return env.getProperty(key);
}
}
Above, we autowire a dependency into the class and specify the location of our custom properties file. We can then fetch our salient property by calling the function getProperty() passing in the String value.
以上,我们在类中自动连接了一个依赖关系,并指定了我们自定义属性文件的位置。然后我们可以通过调用函数 getProperty()传入字符串值来获取我们的突出属性。
4.4. The PropertySource Programmatic Approach
4.4.PropertySource的计划性方法
We can combine the above approach (which involves fetching property values) with the approach below (which allows us to programmatically specify those values):
我们可以把上面的方法(涉及获取属性值)和下面的方法(允许我们以编程方式指定这些值)结合起来。
ConfigurableEnvironment env = new StandardEnvironment();
MutablePropertySources props = env.getPropertySources();
Map map = new HashMap(); map.put("key", "value");
props.addFirst(new MapPropertySource("Map", map));
We’ve created a map linking a key to a value then add that map to PropertySources enabling invocation as needed.
我们已经创建了一个地图,将一个键与一个值联系起来,然后将该地图添加到PropertySources中,以便根据需要进行调用。
5. Registering Embedded Servlets
5.注册嵌入式Servlet
Lastly, we’ll also take a look at basic configuration and registration of embedded servlets within Spring Boot.
最后,我们还将看一下Spring Boot中嵌入式servlets的基本配置和注册。
An embedded servlet provides full web container (Tomcat, Jetty, etc.) functionality without having to install or maintain the web-container separately.
嵌入式servlet提供完整的网络容器(Tomcat、Jetty等)功能,而无需单独安装或维护网络容器。
You can add the required dependencies and configuration for simple live server deployment wherever such functionality is supported painlessly, compactly, and quickly.
你可以为简单的实时服务器部署添加所需的依赖性和配置,只要支持这种功能,就可以无痛、紧凑、快速地进行。
We’ll only look at how to do this Tomcat but the same approach can be undertaken for Jetty and alternatives.
我们只看如何做Tomcat,但同样的方法也可以用于Jetty和替代方案。
Let’s specify the dependency for an embedded Tomcat 8 web container in pom.xml:
让我们在pom.xml中指定一个嵌入式Tomcat 8网络容器的依赖性。
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>8.5.11</version>
</dependency>
Now let’s add the tags required to successfully add Tomcat to the .war produced by Maven at build-time:
现在我们来添加必要的标签,以便在构建时将Tomcat成功添加到Maven生成的.war中。
<build>
<finalName>embeddedTomcatExample</finalName>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>2.0.0</version>
<configuration>
<assembleDirectory>target</assembleDirectory>
<programs>
<program>
<mainClass>launch.Main</mainClass>
<name>webapp</name>
</program>
</programs>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>assemble</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
If you are using Spring Boot, you can instead add Spring’s spring-boot-starter-tomcat dependency to your pom.xml:
如果你使用Spring Boot,你可以将Spring的spring-boot-starter-tomcat依赖性添加到你的 pom.xml中。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
5.1. Registration Through Properties
5.1.通过属性注册
Spring Boot supports configuring most possible Spring settings through application.properties. After adding the necessary embedded servlet dependencies to your pom.xml, you can customize and configure your embedded servlet using several such configuration options:
Spring Boot支持通过application.properties来配置大多数可能的Spring设置。在向你的pom.xml添加必要的嵌入式Servlet依赖后,你可以使用几个这样的配置选项来定制和配置你的嵌入式Servlet。
server.jsp-servlet.class-name=org.apache.jasper.servlet.JspServlet
server.jsp-servlet.registered=true
server.port=8080
server.servlet-path=/
Above are some of the application settings that can be used to configure the DispatcherServlet and static resource sharing. Settings for embedded servlets, SSL support, and sessions are also available.
以上是一些可用于配置DispatcherServlet和静态资源共享的应用设置。还可以对嵌入式Servlet、SSL支持和会话进行设置。
There are really too many configuration parameters to list here but you can see the full list in the Spring Boot documentation.
这里真的有太多的配置参数要列出,但你可以在Spring Boot文档中看到完整的列表。
5.2. Configuration Through YAML
5.2.通过YAML进行配置
Similarly, we can configure our embedded servlet container using YAML. This requires the use of a specialized YAML property loader — the YamlPropertySourceLoader — which exposes our YAML and makes the keys and values therein available for use within our app.
同样地,我们可以使用YAML来配置我们的嵌入式Servlet容器。这需要使用一个专门的YAML属性加载器–YamlPropertySourceLoader–它暴露了我们的YAML,并使其中的键和值可在我们的应用程序中使用。
YamlPropertySourceLoader sourceLoader = new YamlPropertySourceLoader();
PropertySource<?> yamlProps = sourceLoader.load("yamlProps", resource, null);
5.3. Programmatic Configuration Through TomcatEmbeddedServletContainerFactory
5.3.通过TomcatEmbeddedServletContainerFactory进行程序化配置
Programmatic configuration of an embedded servlet container is possible through a subclassed instance of EmbeddedServletContainerFactory. For example, you can use the TomcatEmbeddedServletContainerFactory to configure your embedded Tomcat servlet.
通过EmbeddedServletContainerFactory的子类化实例,可以对嵌入式Servlet容器进行程序化配置。例如,你可以使用TomcatEmbeddedServletContainerFactory来配置你的嵌入式Tomcat servlet。
The TomcatEmbeddedServletContainerFactory wraps the org.apache.catalina.startup.Tomcat object providing additional configuration options:
TomcatEmbeddedServletContainerFactory包装org.apache.catalina.startup.Tomcat对象,提供额外的配置选项。
@Bean
public ConfigurableServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcatContainerFactory
= new TomcatServletWebServerFactory();
return tomcatContainerFactory;
}
Then we can configure the returned instance:
然后我们可以配置返回的实例。
tomcatContainerFactory.setPort(9000);
tomcatContainerFactory.setContextPath("/springboottomcatexample");
Each of those particular settings can be made configurable using any of the methods previously described.
这些特定的设置中的每一个都可以使用之前描述的任何方法来进行配置。
We can also directly access and manipulate the org.apache.catalina.startup.Tomcat object:
我们还可以直接访问和操作 org.apache.catalina.startup.Tomcat 对象。
Tomcat tomcat = new Tomcat();
tomcat.setPort(port);
tomcat.setContextPath("/springboottomcatexample");
tomcat.start();
6. Conclusion
6.结论
In this article, we’ve reviewed several ways to register a Servlet in a Jakarta EE and Spring Boot application.
在这篇文章中,我们回顾了在Jakarta EE和Spring Boot应用程序中注册Servlet的几种方法。
The source code used in this tutorial is available in the Github project.
本教程中使用的源代码可在Github项目中找到。