Solon

二、开发知识准备

1、约定

//资源路径约定(不用配置;也不能配置)
resources/app.properties( 或 app.yml ) #为应用配置文件
resources/WEB-INF/static/ #为静态文件根目标
resources/WEB-INF/view/   #为视图模板文件根目标(支持多视图共存)

//调试模式约定:
启动参数添加:--debug=1

2、应用启动过程

请参考: 《想法与架构笔记》,关于应用内在的启动过程的内容。

3、服务端口配置

在应用主配置文件里指定:

server.port: 8081

可以在运行时指定系统属性(优先级高):

java -Dserver.prot=9091 -jar DemoApp.jar

还可以,在运行时通过启动参数指定(优先级更高):

java -jar DemoApp.jar -server.prot=9091

4、静态资源放哪里

Solon 的默认静态资源的路径为:(这个没得改,也不让改;为了简化套路)

resources/WEB-INF/static/

在默放的处理规则下,所有请求,都会先执行静态文件代理。静态文件代理会检测是否存在静态文件,有则输出,没有则跳过处理。输出的静态文件会做304控制。

也可以在启动时,添加别的静态资源目录:

public class DemoApp{
    public void main(String[] args){
        Solon.start(DemoApp.class, args, app->{
            //更多添加方式,可参考 solon.web.staticfiles 插件的能力
            StaticMappings.add("/", new ClassPathStaticRepository("user"));
        });
    }
}

5、路径映射表达式说明

符号说明示例
**任意字符、不限段数**/user/**
*任意字符/user/*
/路径片段开始符和间隔符//user
{name}路径变量申明/user/{name}

路径组合(控制器映射与动作映射)及应用示例:

@Mapping("/user") //或 "user",开头自动会补"/"
@Controller
public void DemoController{

    @Maping("") //=/user
    public void home(){ }
    
    @Maping("/") //=/user/,与上面是有区别的,注意下。
    public void home2(){ }
    
    @Maping("list") //=/user/list ,间隔自动会补"/"
    public void getList(){ }
    
    @Maping("/{id}") //=/user/{id}
    public void getOne(long id){ }
    
    @Maping("/ajax/**") //=/user/ajax/**
    public void ajax(){ }
}

6、路径重定向与转发

路径重定向

public class DemoController{
    @Mapping("/")
    public void home(Context ctx) {
        //通过302方式,通知客户端跳转到 /login (浏览器会发生2次请求,地址会变成/login)
        ctx.redirect("/login");
    }
}    

路径转发

public class DemoController{
    @Mapping("/")
    public void home(Context ctx) {
        //在服务端重新路由到 /login (浏览器发生1次请求,地址不会变)
        ctx.forward("/login");
    }
}    

7、请求参数注入或手动获取

//GET http://localhost:8080/test1?str=a&num=1
public class DemoController{
    @Mapping("/test1")
    public void test1(String str, int num) { //可自动注入 get, post, json body 形式的参数
        
    }
    
    @Mapping("/test2")
    public void test2(Context ctx) {  
        //手动获取 get, post 参数
        String str = ctx.param("str");
        int num = ctx.paramAsInt("num", 0);
        
        //手动获取 body 请求的数据
        String body = ctx.body();
    }
}

8、统一请求异常处理和性能计时

//过滤所有因请求产生的异常(顺带加点别的)
@Slf4j
@Component
public class AppFilter implements Filter {
    @Override
    public void doFilter(Context ctx, FilterChain chain) throws Throwable {
        //1.开始计时(用于计算响应时长)
        long start = System.currentTimeMillis();
        try {
            chain.doFilter(ctx);

            //2.未处理设为404状态
            if(! ctx.getHandled()){
                ctx.status(404);
            }
            
            //3.404状态的定制(也可对别的状态处理)
            if (ctx.status() == 404) { 
                ctx.setHandled(true);
                ctx.output("没有:(");
            }
        } catch (Throwable e) {
            //4.异常捕促与控制
            log.error(e);
        }

        //5.获得接口响应时长
        long times = System.currentTimeMillis() - start;
        System.out.println("用时:"+ times);
    }
}  

9、读取自定义的配置文件

//直接注入
@Configuration
public class Config{
    @Inject("${classpath:user.yml}")
    private UserModel user;
}

public class DemoApp{
    public void main(String[] args){
        Solon.start(DemoApp.class, args, app->{
            app.cfg().loadAdd("user.yml");
        });
    }
}

10、也有jsp的支持(不建议用)

solon 的jsp支持,是基于视图模板的定位去处理的。根据启动器组件的不同,配置略有不同:

<!-- 添加 solon web 开发包 -->
<dependency>
    <groupId>org.noear</groupId>
    <artifactId>solon-web</artifactId>
</dependency>

<!-- 添加 jetty 或 undertow 启动器 -->
<dependency>
    <groupId>org.noear</groupId>
    <artifactId>solon.boot.jetty</artifactId>
</dependency>

<!-- 添加 jetty 或 undertow jsp 扩展支持包 -->
<dependency>
    <groupId>org.noear</groupId>
    <artifactId>solon.boot.jetty.add.jsp</artifactId>
</dependency>

<!-- 添加 jsp 视图引擎 -->
<dependency>
    <groupId>org.noear</groupId>
    <artifactId>solon.view.jsp</artifactId>
</dependency>