Como registrar um servlet em Java

Como registrar um servlet em Java

*1. Introdução *

Este artigo fornecerá* uma visão geral de como registrar um servlet no Java EE e Spring Boot. *Especificamente, examinaremos duas maneiras de registrar um Servlet Java no Java EE - um usando um arquivo web.xml e o outro usando anotações. Em seguida, registraremos os servlets no Spring Boot usando a configuração XML, a configuração Java e as propriedades configuráveis.

Um ótimo artigo introdutório sobre servlets pode ser encontrado no link:/introdução aos servlets [aqui].

===* 2. Registrando Servlets no Java EE *

Vamos examinar duas maneiras de registrar um servlet no Java EE. Primeiro, podemos registrar um servlet via web.xml. Como alternativa, podemos usar a anotação Java EE _ @ WebServlet_.

====* 2.1 Via web.xml *

A maneira mais comum de registrar um servlet no seu aplicativo Java EE é adicioná-lo ao seu arquivo 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..Example</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>Example</servlet-name>
    <url-pattern>/Example</url-pattern>
</servlet-mapping>

Como você pode ver, isso envolve duas etapas: (1) adicionar nosso servlet à tag servlet, certificando-se de especificar também o caminho de origem para a classe em que o servlet reside e (2) especificar o caminho da URL em que o servlet será exposto na tag url-pattern.

O arquivo Java EE web.xml geralmente é encontrado em WebContent/WEB-INF.

====* 2.2 Via Anotações *

Agora vamos registrar nosso servlet usando a anotação _ @ WebServlet_ em nossa classe de servlet customizada. Isso elimina a necessidade de mapeamentos de servlet no server.xml e o registro do servlet em web.xml:

@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>");
    }
}

O código acima demonstra como adicionar essa anotação diretamente a um servlet. O servlet ainda estará disponível no mesmo caminho de URL que antes.

===* 3. Registrando Servlets no Spring Boot *

Agora que mostramos como registrar servlets no Java EE, vamos dar uma olhada em várias maneiras de registrar servlets em um aplicativo Spring Boot.

====* 3.1 Registro programático *

O Spring Boot suporta 100% de configuração programática de um aplicativo da web.

Primeiro, implementaremos a interface WebApplicationInitializer e, em seguida, implementaremos a interface WebMvcConfigurer, que permite substituir os padrões predefinidos em vez de especificar cada configuração específica, economizando tempo e permitindo que você trabalhe com várias configurações reais e experimentadas. -a Caixa.

Vejamos uma implementação de exemplo 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("/");
     }
}

Em seguida, vamos implementar a 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());
    }
}

Acima, especificamos algumas das configurações padrão para servlets JSP explicitamente, a fim de suportar visualizações .jsp e veiculação de recursos estáticos.

3.2 Configuração XML

Outra maneira de configurar e registrar servlets no Spring Boot é através de 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>

O web.xml usado para especificar a configuração no Spring é semelhante ao encontrado no Java EE. Acima, você pode ver como especificamos mais alguns parâmetros por meio de atributos na tag servlet.

Aqui usamos outro XML para concluir a configuração:

<beans ...>

    <context:component-scan base-package="com."/>

    <bean
      class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

Lembre-se de que o seu web.xml do Spring geralmente fica em src/main/webapp/WEB-INF.

3.3 Combinando XML e registro programático

Vamos misturar uma abordagem de configuração XML com a configuração programática do 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("/");
}

Vamos também configurar o servlet do expedidor:

<beans ...>

    <context:component-scan base-package="com."/>
    <bean class="com..configuration.WebAppInitializer"/>
</beans>

3.4 Registro pelo Bean

Também podemos configurar e registrar programaticamente nossos servlets usando um ServletRegistrationBean. Abaixo, faremos isso para registrar um HttpServlet (que implementa a interface javax.servlet.Servlet):

@Bean
public ServletRegistrationBean exampleServletBean() {
    ServletRegistrationBean bean = new ServletRegistrationBean(
      new CustomServlet(), "/exampleServlet/*");
    bean.setLoadOnStartup(1);
    return bean;
}

A principal vantagem dessa abordagem é que ela permite adicionar vários servlets, bem como diferentes tipos de servlets, ao seu aplicativo Spring.

Em vez de simplesmente utilizar um DispatcherServlet, _ que é um tipo mais específico de _HttpServlet e o tipo mais comum usado na abordagem programática WebApplicationInitializer à configuração que exploramos na seção 3.1, usaremos uma instância mais simples da subclasse HttpServlet que expõe as quatro HttpRequest operações através de quatro funções: _doGet () _, _doPost () _, _doPut () _ e _doDelete () _ assim como no Java EE.

Lembre-se de que HttpServlet é uma classe abstrata (portanto, não pode ser instanciada). Podemos criar uma extensão personalizada facilmente, no entanto:

public class CustomServlet extends HttpServlet{
    ...
}

*4. Registrando Servlets com Propriedades *

Outra maneira, embora incomum, de configurar e registrar seus servlets é usar um arquivo de propriedades customizado carregado no aplicativo por meio de um objeto de instância PropertyLoader, PropertySource, _ ou _PropertySources .

Isso fornece um tipo intermediário de configuração e a capacidade de personalizar application.properties, que fornece pouca configuração direta para servlets não incorporados.

====* 4.1 Abordagem de propriedades do sistema *

Podemos adicionar algumas configurações personalizadas ao nosso arquivo application.properties ou outro arquivo de propriedades. Vamos adicionar algumas configurações para configurar nosso DispatcherServlet:

servlet.name=dispatcherExample
servlet.mapping=/dispatcherExampleURL

Vamos carregar nossas propriedades personalizadas em nosso aplicativo:

System.setProperty("custom.config.location", "classpath:custom.properties");

E agora podemos acessar essas propriedades via:

System.getProperty("custom.config.location");

====* 4.2 Abordagem de propriedades personalizadas *

Vamos começar com um arquivo custom.properties:

servlet.name=dispatcherExample
servlet.mapping=/dispatcherExampleURL

Em seguida, podemos usar um Carregador de propriedades comum:

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;
}

E agora podemos adicionar essas propriedades personalizadas como constantes à nossa implementação 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");

Em seguida, podemos usá-los para, por exemplo, configurar nosso servlet de expedidor:

ServletRegistration.Dynamic servlet = container.addServlet(
  SERVLET_NAME, new DispatcherServlet(ctx));
servlet.setLoadOnStartup(1);
servlet.addMapping(SERVLET_MAPPING);

A vantagem dessa abordagem é a ausência de manutenção .xml, mas com definições de configuração fáceis de modificar que não exigem a reimplantação da base de código.

====* 4.3 A abordagem PropertySource *

Uma maneira mais rápida de fazer isso é usar o PropertySource do Spring, que permite que um arquivo de configuração seja acessado e carregado.

PropertyResolver é uma interface implementada por _ConfigurableEnvironment, _ que disponibiliza as propriedades do aplicativo na inicialização e inicialização do servlet:

@Configuration
@PropertySource("classpath:/com/yourapp/custom.properties")
public class ExampleCustomConfig {
    @Autowired
    ConfigurableEnvironment env;

    public String getProperty(String key) {
        return env.getProperty(key);
    }
}

Acima, atribuímos automaticamente uma dependência à classe e especificamos o local do nosso arquivo de propriedades personalizadas. Podemos então buscar nossa propriedade saliente chamando a função _getProperty () _ que passa no valor String.

====* 4.4 A abordagem programática PropertySource *

Podemos combinar a abordagem acima (que envolve buscar valores de propriedade) com a abordagem abaixo (que nos permite especificar programaticamente esses valores):

ConfigurableEnvironment env = new StandardEnvironment();
MutablePropertySources props = env.getPropertySources();
Map map = new HashMap(); map.put("key", "value");
props.addFirst(new MapPropertySource("Map", map));

Criamos um mapa vinculando uma chave a um valor e, em seguida, adicionamos esse mapa a PropertySources, permitindo a chamada conforme necessário.

===* 5. Registrando Servlets Incorporados *

Por fim, também veremos a configuração básica e o registro de servlets incorporados no Spring Boot.

*Um servlet incorporado fornece a funcionalidade completa de contêiner da Web (Tomcat, Jetty etc.) sem precisar instalar ou manter o contêiner da Web separadamente* .

Você pode adicionar as dependências e a configuração necessárias para a implantação simples do servidor ativo, sempre que essa funcionalidade for suportada sem problemas, de forma compacta e rápida.

Vamos ver apenas como fazer isso Tomcat, mas a mesma abordagem pode ser adotada para o Jetty e alternativas.

Vamos especificar a dependência para um contêiner da Web Tomcat 8 incorporado em pom.xml:

<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
     <artifactId>tomcat-embed-core</artifactId>
     <version>8.5.11</version>
</dependency>

Agora vamos adicionar as tags necessárias para adicionar com êxito o Tomcat ao .war produzido pelo Maven no momento da construção:

<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>

Se você estiver usando o Spring Boot, poderá adicionar a dependência spring-boot-starter-tomcat do Spring ao seu pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
</dependency>

5.1. Registro através de propriedades

O Spring Boot suporta a configuração da maioria das configurações possíveis do Spring através de application.properties. Após adicionar as dependências necessárias do servlet incorporado ao seu pom.xml, você pode personalizar e configurar o servlet incorporado usando várias dessas opções de configuração:

server.jsp-servlet.class-name=org.apache.jasper.servlet.JspServlet
server.jsp-servlet.registered=true
server.port=8080
server.servlet-path=/

A seguir, estão algumas configurações do aplicativo que podem ser usadas para configurar o DispatcherServlet e o compartilhamento estático de recursos. Configurações para servlets incorporados, suporte SSL e sessões também estão disponíveis.

Existem realmente muitos parâmetros de configuração para listar aqui, mas você pode ver a lista completa em Spring Documentação de inicialização.

5.2 Configuração através do YAML

Da mesma forma, podemos configurar nosso contêiner de servlet incorporado usando o YAML. Isso requer o uso de um carregador de propriedades YAML especializado - o YamlPropertySourceLoader - que expõe nossa YAML e disponibiliza as chaves e valores disponíveis para uso em nosso aplicativo.

YamlPropertySourceLoader sourceLoader = new YamlPropertySourceLoader();
PropertySource<?> yamlProps = sourceLoader.load("yamlProps", resource, null);

5.3. Configuração programática através do TomcatEmbeddedServletContainerFactory

A configuração programática de um contêiner de servlet incorporado é possível por meio de uma instância subclassificada de EmbeddedServletContainerFactory. Por exemplo, você pode usar o TomcatEmbeddedServletContainerFactory para configurar seu servlet Tomcat incorporado.

O TomcatEmbeddedServletContainerFactory envolve o objeto org.apache.catalina.startup.Tomcat, fornecendo opções de configuração adicionais:

@Bean
public ConfigurableServletWebServerFactory servletContainer() {
    TomcatServletWebServerFactory tomcatContainerFactory
      = new TomcatServletWebServerFactory();
    return tomcatContainerFactory;
}

Em seguida, podemos configurar a instância retornada:

tomcatContainerFactory.setPort(9000);
tomcatContainerFactory.setContextPath("/springboottomcatexample");

Cada uma dessas configurações específicas pode ser configurada usando qualquer um dos métodos descritos anteriormente.

Também podemos acessar e manipular diretamente o objeto org.apache.catalina.startup.Tomcat:

Tomcat tomcat = new Tomcat();
tomcat.setPort(port);
tomcat.setContextPath("/springboottomcatexample");
tomcat.start();

*6. Conclusão *

Neste artigo, analisamos várias maneiras de* registrar um Servlet em um aplicativo Java EE e Spring Boot. *

O código fonte usado neste tutorial está disponível no Projeto Github.