java使用内嵌Tomcat開發javaWeb項目
- 寫在前面
- 內建Swagger,提供優雅api文檔
-
- 在pom.xml添加swagger依賴
- 建立swagger配置類
- 在spring-config.xml中配置掃描
- 在controller下面建立ApiController,用于測試接口描述
- 在spring-mvc.xml和spring-shiro.xml中開啟swagger資源映射和關閉權限攔截
- 啟動項目
- 使用HandlerInterceptor記錄通路controller的日志
-
- 編寫LoggingHandlerInterceptor
- 在spring-mvc.xml中配置
- 啟動項目
- 項目部署環境修改
-
- 修改啟動類
- 修改配置檔案加載路徑
- 修改靜态資源映射路徑
- 建立與項目同級webapp目錄,遷移檔案到webapp目錄
- 啟動項目
- 在pom.xml添加打包插件,将項目打包成可運作的jar包
- 打包項目
- 部署項目
寫在前面
這一篇部落格,主要講解項目開發中,接口文檔編寫,日志記錄,項目部署,
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", "[email protected]"))
.description("embed tomcat")
.title("embed tomcat")
.version("0.0.1").build();
}
}
在spring-config.xml中配置掃描
在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資源映射和關閉權限攔截
<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>
修改靜态資源映射路徑
建立與項目同級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開發項目到部署的過程,同時實作頁面和配置與項目的解耦,保證項目可以随意移植到不同的系統上面運作