造一个方形轮子文章目录:造一个方形的轮子
01、先把车正过来
在上一篇《造一个方形的轮子1--嵌入容器》的最后成功的翻车了,现在先把发现的这个问题解决,想一下如果不想源码暴露出去那么就得改变一下tomcat的web服务项目根目录 ,改成什么好呢?还好有现成的springboot可以借(抄)鉴(袭)。
在springboot里如果我们要添加静态资源有好几个目录可选,可以在resources目录下添加
-resources
-META-INF.resources
-public
-resources
-static
上边4个目录下的文件在打包的时候都会当作静态资源处理的,省点事,就用一个public吧。在square项目的resource目录下添加一下public文件夹,添加一个默认页面。
index.html
<!DOCTYPE html>
<html lang="en">
<body>
<h1>Whitelabel Error Page</h1><p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p><div>There was an unexpected error (type=Not Found, status=404).</div><div>No message available</div>
</body>
</html>
然后将SquareApplication.run()方法里的启动目录改一下:
public static void run(Class clzz, String[] args) {
//.....上略,可以翻看上篇代码
tomcat = new Tomcat();
// 设置Tomcat的工作目录:工程根目录/Tomcat
tomcat.setBaseDir(project_path + "/Tomcat");
tomcat.setPort(TOMCAT_PORT);
// 在这里添加上public目录
tomcat.addWebapp(CONTEXT_PATH, project_path+"/classes/public");
//.....下略
启动后查看:
ok,问题解决了,解决的相当粗暴,这块下边会再统一改,就不多费话了。
02、解析配置准备
常用的配置文件有两种yaml
和properties
图省事我就只用yaml
了
yaml
本身就不多说了,java里面支持yaml
的工具包挺多的,看了一下Springboot使用的是snakeyaml,妥了,就用这个吧,添加一下yaml
解析使用的依赖:
pom.xml
<properties>
...
<snakeyaml.version>1.9</snakeyaml.version>
</properties>
<dependencies>
...
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>${snakeyaml.version}</version>
</dependency>
</dependencies>
在resources文件夹下添加application.yml文件
application.yml
server:
port: 8888
servlet:
context-path: /abc
03、添加资源加载工具类
这个工具类是利用snakeyaml包将application.yml配置的内容转换为Map类型key为配置的参数key比如server.port
LoadApplicationYmlUtil.java
/**
* 加载application.yml文件
* @author ixx
* @date 2019-06-15
*/
public class LoadApplicationYmlUtil {
private static final Logger log = LoggerFactory.getLogger(LoadApplicationYmlUtil.class);
public static Map<String, Object> load(String projectPath){
Map<String, Object> retMap = new HashMap<>();
Yaml yaml = new Yaml();
try {
Map<String, Object> map = (Map<String, Object>)yaml.load(new FileInputStream(projectPath+"/classes/application.yml"));
if(map != null && map.size()>0){
for(Map.Entry e : map.entrySet()) {
convert("", retMap, e);
}
}
} catch (FileNotFoundException e) {
log.error("load application.yml file error.", e);
}
return retMap;
}
/**
* 递归组装配置参数
* @param key 父级key路径(类似server.servlet)
* @param retMap 要返回的map
* @param entry
*/
private static void convert(String key, Map<String, Object> retMap, Map.Entry entry){
if(entry.getValue() instanceof Map){
key = key+entry.getKey()+".";
for(Map.Entry e : ((Map<String, Object>)entry.getValue()).entrySet()){
convert(key, retMap, e);
}
} else {
key = key+entry.getKey();
retMap.put(key, entry.getValue());
}
}
}
实现主要就是将读出来的内容利用convert
递归转换一下
04、初始化配置
在SquareApplication.java里添加loadYaml
方法,放个完整代码吧,重点看loadYaml
方法:
/**
* 项目启动类
* @author ixx
* @date 2019-6-13
*/
public class SquareApplication {
private static final Logger log = LoggerFactory.getLogger(SquareApplication.class);
private static Map<String, Object> CONF_MAP = new HashMap<>();
private static Tomcat tomcat = null;
private static String CONTEXT_PATH = "/";
private static String ENCODING = "UTF-8";
private static int TOMCAT_PORT = 8080;
public static void run(Class clzz, String[] args) {
try {
long startTime = System.currentTimeMillis();
String project_path = clzz.getResource("").getPath();
project_path = project_path.substring(0, project_path.indexOf("classes"));
// 加载配置
loadYaml(project_path);
// 初始化参数
setArgs(args);
// 输出banner
printBanner(project_path);
tomcat = new Tomcat();
// 设置Tomcat的工作目录:工程根目录/Tomcat
tomcat.setBaseDir(project_path + "/Tomcat");
tomcat.setPort(TOMCAT_PORT);
tomcat.addWebapp(CONTEXT_PATH, project_path+"/classes/public");
// 执行这句才能支持JDNI查找
tomcat.enableNaming();
tomcat.getConnector().setURIEncoding(ENCODING);
tomcat.start();
log.info("Tomcat started on port(s): {} with context path '{}'", TOMCAT_PORT, CONTEXT_PATH);
log.info("Started Application in {} ms." , (System.currentTimeMillis() - startTime));
// 保持服务器进程
tomcat.getServer().await();
} catch (Exception e) {
log.error("Application startup failed...", e);
}
}
/**
* 初始化参数
* @param args
*/
private static void setArgs(String[] args){
Map<String, String> map = ArgsToKVUtil.convert(args);
if(map.get("--server.port") != null){
TOMCAT_PORT = Integer.parseInt(map.get("--server.port"));
}
}
/**
* 加载配置文件
* @param projectPath
*/
private static void loadYaml(String projectPath){
CONF_MAP = LoadApplicationYmlUtil.load(projectPath);
if(CONF_MAP.get("server.port") != null){
TOMCAT_PORT = (Integer)CONF_MAP.get("server.port");
}
if(CONF_MAP.get("server.servlet.context-path") != null){
CONTEXT_PATH = (String)CONF_MAP.get("server.servlet.context-path");
}
}
/**
* 输出banner图
*/
private static void printBanner(String projectPath){
BufferedReader br = null;
try{
File f = new File(projectPath + "/classes/default-banner.txt");
br = new BufferedReader(new FileReader(f));
StringBuilder stringBuilder = new StringBuilder("\n");
String line;
while ((line = br.readLine()) != null){
stringBuilder.append(line).append("\n");
}
log.info(stringBuilder.toString());
} catch (Exception e){
log.info("load banner file error!!", e);
if(br != null){
try {
br.close();
} catch (IOException e1) {
}
}
}
}
}
启动T.main()方法测试,启动日志输出:
13:05:38.676 [main] INFO com.jisuye.core.SquareApplication -
__________ ____
| ____ |/ ___| __ _ _ _ __ _ _ __ ___
| | | |\___ \ / _` | | | |/ _` | '__/ _ \
| |____| | ___) | (_| | |_| | (_| | | | __/
|__________||____/ \__, |\__,_|\__,_|_| \___|
======================|_|====================
:: Square :: (v0.1)
.....
信息: Starting ProtocolHandler ["http-nio-8888"]
13:05:40.912 [main] INFO com.jisuye.core.SquareApplication - Tomcat started on port(s): 8888 with context path '/abc'
13:05:40.914 [main] INFO com.jisuye.core.SquareApplication - Started Application in 2318 ms.
可以看到端口号及context-path
已经使用的是application.yml
配置文件中的了
05、翻车现场
又到了翻车时间了,到目前为止已经实现的代码好像都还ok,但不要忘记我的目的,我要造的是轮子,一个方形的轮子,轮子怎么能光自己跑呢,轮子是给别人用的,不然别人怎么翻车。
好的,把轮子打个包出来,找个”车“试试吧。
项目根目录下执行mvn clean install
编译完成并推到本地仓库里了,然后我们新建一个maven项目 car
在car项目的pom.xml里添加引用:
<groupId>com.jisuye</groupId>
<artifactId>car</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.jisuye</groupId>
<artifactId>square</artifactId>
<version>0.1-SNAPSHOT</version>
</dependency>
</dependencies>
添加resources/application.yml配置文件
server:
port: 8989
servlet:
context-path: /car
添加main/java/com/jisuye/Application.java文件
package com.jisuye;
import com.jisuye.core.SquareApplication;
public class Application {
public static void main(String args[]){
SquareApplication.run(Application.class, args);
}
}
启动main
方法,查看日志输出:
13:29:51.529 [main] INFO com.jisuye.core.SquareApplication - load banner file error!!
java.io.FileNotFoundException: C:\Users\admin\ixx\car\target\classes\default-banner.txt (系统找不到指定的文件。)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileReader.<init>(FileReader.java:72)
at com.jisuye.core.SquareApplication.printBanner(SquareApplication.java:88)
at com.jisuye.core.SquareApplication.run(SquareApplication.java:36)
at com.jisuye.Application.main(Application.java:7)
...
java.io.FileNotFoundException: C:\Users\admin\ixx\car\target\classes\public (系统找不到指定的文件。)
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.<init>(ZipFile.java:225)
at java.util.zip.ZipFile.<init>(ZipFile.java:155)
at java.util.jar.JarFile.<init>(JarFile.java:166)
at java.util.jar.JarFile.<init>(JarFile.java:130)
at org.apache.catalina.startup.Tomcat.getWebappConfigFileFromWar(Tomcat.java:1375)
at org.apache.catalina.startup.Tomcat.getWebappConfigFile(Tomcat.java:1355)
at org.apache.catalina.startup.Tomcat.addWebapp(Tomcat.java:718)
at org.apache.catalina.startup.Tomcat.addWebapp(Tomcat.java:694)
at org.apache.catalina.startup.Tomcat.addWebapp(Tomcat.java:236)
at com.jisuye.core.SquareApplication.run(SquareApplication.java:41)
at com.jisuye.Application.main(Application.java:7)
....
Process finished with exit code 0
这车翻的妥妥的....
下一篇再解决吧....
本篇代码地址: https://github.com/iuv/square
本文作者: ixx
本文链接: http://jianpage.com/2019/06/24/square2/
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!