造一个方形的轮子2--添加配置

造一个方形轮子文章目录:造一个方形的轮子

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");
            //.....下略

启动后查看:


2-1.png

ok,问题解决了,解决的相当粗暴,这块下边会再统一改,就不多费话了。

02、解析配置准备

常用的配置文件有两种yamlproperties图省事我就只用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 国际许可协议 进行许可。转载请注明出处!

推荐阅读更多精彩内容