java篇-(java使用内嵌Tomcat开发javaWeb项目-进阶篇)

  • Post author:
  • Post category:java




写在前面


这一篇博客,主要讲解项目开发中,接口文档编写,日志记录,项目部署,



java使用内嵌Tomcat开发javaWeb项目-高级篇2这篇博客,主要讲解在开发中,如何集成其他功能,博客地址:


java篇-(java使用内嵌Tomcat开发javaWeb项目-高级篇2

,

java使用内嵌Tomcat开发javaWeb项目源代码下载地址:


embed-tomcat-example.zip



集成Swagger,提供优雅api文档



在pom.xml添加swagger依赖

在这里插入图片描述

        ...
        <springfox.swagger.version>3.0.0</springfox.swagger.version>
        <swagger.version>1.6.2</swagger.version>
        <jackson.version>2.11.4</jackson.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson.version}</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.swagger/swagger-annotations -->
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
            <version>${swagger.version}</version>
        </dependency>

        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-models</artifactId>
            <version>${swagger.version}</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>${springfox.swagger.version}</version>
        </dependency>
       <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-oas</artifactId>
            <version>${springfox.swagger.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>${springfox.swagger.version}</version>
        </dependency>
		...



创建swagger配置类

在这里插入图片描述

package com.lhstack.embed.config;

import io.swagger.annotations.Api;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ui.Model;
import org.springframework.web.servlet.ModelAndView;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * @author lhstack
 */
@Configuration
@EnableOpenApi
public class SwaggerConfiguration {

    @Bean
    public Docket docket() {
        return new Docket(DocumentationType.OAS_30)
                .apiInfo(apiInfo())
                .ignoredParameterTypes(HttpServletRequest.class,
                        HttpServletResponse.class,
                        HttpSession.class,
                        ServletContext.class,
                        Model.class,
                        ModelAndView.class)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.lhstack.embed.controller")
                        .and(RequestHandlerSelectors.withClassAnnotation(Api.class)))
                .paths(PathSelectors.any())
                .build();
    }

    public ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .contact(new Contact("lhstack", "https://www.lhstack.com", "lhstack@foxmail.com"))
                .description("embed tomcat")
                .title("embed tomcat")
                .version("0.0.1").build();
    }

}



在spring-config.xml中配置扫描

在这里插入图片描述

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



在controller下面创建ApiController,用于测试接口描述

在这里插入图片描述

package com.lhstack.embed.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author lhstack
 */
@RestController
@RequestMapping("api")
@Api(tags = "api接口")
public class ApiController {

    @GetMapping("hello")
    @ApiOperation("打印hello")
    public String hello(){
        return "hello";
    }

    @GetMapping("hello/{param}")
    @ApiOperation("带参数")
    public String hello(@ApiParam(value = "打印的值") @PathVariable("param") String hello){
        return hello;
    }
}



在spring-mvc.xml和spring-shiro.xml中开启swagger资源映射和关闭权限拦截

在这里插入图片描述

     <mvc:resources mapping="/swagger-ui/**" location="classpath:/META-INF/resources/webjars/springfox-swagger-ui/" />

在这里插入图片描述

<entry key="/swagger-ui/**" value="anon"/>
<entry key="/swagger-resources/**" value="anon" />
<entry key="/v3/**" value="anon" />
<entry key="/api/**" value="anon" />



启动项目

通过浏览器输入

http://localhost:8080/swagger-ui/index.html

,访问swagger稳定,进行接口调试

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述



使用HandlerInterceptor记录访问controller的日志



编写LoggingHandlerInterceptor

在这里插入图片描述

package com.lhstack.embed.handler.log;

import com.alibaba.fastjson.JSONObject;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

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

/** `
 * @author lhstack
 */
public class LoggingHandlerInterceptor implements HandlerInterceptor {

    private static final Logger LOGGER = LoggerFactory.getLogger(LoggingHandlerInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if(handler instanceof HandlerMethod){
            HandlerMethod handlerMethod = (HandlerMethod) handler;

            LOGGER.info("\n" +
                            "--------------\n" +
                            "Method: {}\n" +
                            "Url: {}\n" +
                            "Param: {}\n" +
                            "Handler: {}\n" +
                            "Principal: {}\n" +
                            "--------------",
                    request.getMethod(),
                    request.getRequestURI(),
                    JSONObject.toJSONString(request.getParameterMap()),
                    handlerMethod.getMethod(),
                    SecurityUtils.getSubject().getPrincipal()
            );
        }
        return true;
    }

}




在spring-mvc.xml中配置

在这里插入图片描述

    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.lhstack.embed.handler.log.LoggingHandlerInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>



启动项目


访问swagger接口,并请求接口


在这里插入图片描述

在这里插入图片描述



项目部署环境修改


j将配置和静态资源移动到外部目录,这是方便项目的配置修改,静态页面的修改,如数据库配置,或者页面替换等等,提高项目的灵活性,同时也减少了jar包的大小,实现配置,页面,与后台完全解耦



修改启动类


修改context path,设置路径为jar包所在同级目录下webapp


在这里插入图片描述


修改spring配置文件加载路径,修改为加载contextPath目录下的WEB-INFO/spring目录里面的配置文件


在这里插入图片描述

package com.lhstack.embed;

import org.apache.catalina.Context;
import org.apache.catalina.Wrapper;
import org.apache.catalina.startup.Tomcat;
import org.apache.tomcat.util.descriptor.web.FilterDef;
import org.apache.tomcat.util.descriptor.web.FilterMap;
import org.apache.tomcat.websocket.server.WsContextListener;
import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.servlet.DispatcherServlet;

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

/**
 * @author lhstack
 */
public class EmbedTomcatApplication {
    public static void main(String[] args) throws Exception {
        int port = 8080;
        Tomcat tomcat = new Tomcat();
        tomcat.setPort(port);
        tomcat.getConnector().setPort(port);
        String webapp = System.getProperty("user.dir") + "/webapp";
        Context context = tomcat.addContext("/", webapp);
        addCharacterFilter(context, "UTF-8");
        addWsContextListener(context);
        addShiroFilter(context);
        addDispatcherServlet(context);
        //启动tomcat
        tomcat.start();

    }

    private static void addWsContextListener(Context context) {
        context.addApplicationListener(WsContextListener.class.getName());
    }

    private static void addShiroFilter(Context context) {
        DelegatingFilterProxy filterProxy = new DelegatingFilterProxy();
        filterProxy.setTargetFilterLifecycle(true);
        FilterDef filterDef = new FilterDef();
        //这里与shiroFilterFactoryBean的id必须一致
        filterDef.setFilterName("shiroFilterFactoryBean");

        filterDef.setFilter(filterProxy);

        //定义filter映射
        FilterMap filterMap = new FilterMap();
        filterMap.setFilterName("shiroFilterFactoryBean");
        filterMap.addURLPattern("/*");
        //添加filter
        context.addFilterDef(filterDef);
        context.addFilterMap(filterMap);
    }

    private static void addDispatcherServlet(Context context) {
        DispatcherServlet dispatcherServlet = new DispatcherServlet();
        dispatcherServlet.setContextConfigLocation("WEB-INF/spring/spring-*.xml");
        Wrapper servlet = Tomcat.addServlet(context, "DispatcherServlet", dispatcherServlet);
        //跟着tomcat一起启动
        servlet.setLoadOnStartup(1);
        servlet.addMapping("/");
    }

    private static void addCharacterFilter(Context context, String encoding) {
        //定义filter
        FilterDef filterDef = new FilterDef();
        filterDef.setFilterName("CharacterEncodingFilter");
        filterDef.setFilter((req, res, chain) -> {

            if (req instanceof HttpServletRequest) {
                req.setCharacterEncoding(encoding);
            }
            if (res instanceof HttpServletResponse) {
                res.setCharacterEncoding(encoding);
            }
            chain.doFilter(req, res);
        });

        //定义filter映射
        FilterMap filterMap = new FilterMap();
        filterMap.setFilterName("CharacterEncodingFilter");
        filterMap.addURLPattern("/*");

        //添加filter
        context.addFilterDef(filterDef);
        context.addFilterMap(filterMap);
    }
}



修改配置文件加载路径

在这里插入图片描述

spring-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <context:property-placeholder location="WEB-INF/config/db.properties,WEB-INF/config/redis.properties" />
    <context:component-scan base-package="com.lhstack.embed.config" />
</beans>



修改静态资源映射路径

在这里插入图片描述

    <mvc:resources mapping="/static/**" location="/static/"/>



创建与项目同级webapp目录,迁移文件到webapp目录

在这里插入图片描述

在这里插入图片描述



启动项目

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述



在pom.xml添加打包插件,将项目打包成可运行的jar包

在这里插入图片描述

<plugins>
   <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-shade-plugin</artifactId>
      <version>3.1.0</version>
      <executions>
         <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
               <filters>
                  <filter>
                     <artifact>*:*</artifact>
                     <excludes>
                        <exclude>META-INF/*.SF</exclude>
                        <exclude>META-INF/*.DSA</exclude>
                        <exclude>META-INF/*.RSA</exclude>
                     </excludes>
                  </filter>
               </filters>
               <transformers>
                                <!--               启动类                 -->
                  <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
				 	 <mainClass>com.lhstack.embed.EmbedTomcatApplication</mainClass>
                  </transformer>
                                <!--                 合并spring jar包下面的META-INF/spring.handlers文件里面的内容               -->
    			  <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                     <resource>META-INF/spring.handlers</resource>
                  </transformer>
                                <!--               合并spring jar包下面的META-INF/spring.schemas文件里面的内容                 -->
			 	  <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                     <resource>META-INF/spring.schemas</resource>
                  </transformer>
               </transformers>
            </configuration>
          </execution>
        </executions>
  </plugin>
</plugins>



打包项目

在这里插入图片描述

在target目录下面得到可运行jar包

在这里插入图片描述



部署项目


将embed-tomcat-example-0.0.1.jar和webapp目录放在同一个目录下面,如下


在这里插入图片描述

jar包里面也没有静态文件和配置文件

在这里插入图片描述


编写启动脚本,并放在与jar包同级目录


在这里插入图片描述

在这里插入图片描述


双击启动


在这里插入图片描述


浏览器访问


在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

修改静态资源目录里面的内容

在这里插入图片描述


第一次访问可能有缓存,多试几次,或者ctrl+f5强制刷新


在这里插入图片描述


这样就实现了使用内嵌tomcat开发项目到部署的过程,同时实现页面和配置与项目的解耦,保证项目可以随意移植到不同的系统上面运行



版权声明:本文为qq_42413011原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。