Solon v3.0.2

四、认识请求上下文(Context)

</> markdown

Handler + Context 架构,是Solon Web 的基础。在 Context (org.noear.solon.core.handle.Context)里可以获取:

  • 请求相关的对象与接口
  • 会话状态相关的对象与接口
  • 响应相关的对象与接口

或者理解所有请求与响应相关的,都在它身上。关于架构方面,可以再看看《想法与架构笔记》

1、几种获取(或控制) Context 的方式

a) 通过 Controller 获取

@Controller
public class HelloController{
    @Mapping("/hello")
    public String hello(Context ctx){
        //可以注入 ctx:Context
        return "Hello " + ctx.paramOrDefault("name", "world");
    }
}

b) 通过 Handler 或 Filter 或 RouterInterceptor 接口方式获取

Solon.start(DemoApp.class, args, app->{
   app.get("/hello", ctx-> ctx.output("Hello " + ctx.paramOrDefault("name", "world"))); 
});

//或者,用以组件方式编写
@Mapping("/hello")
@Component
public class HelloHandler implements Handler{
    public void handle(Context ctx) throws Throwable{
        ctx.output("Hello " + ctx.paramOrDefault("name", "world"));
    }
}

c) 直接获取当前上下文(基于 ThreadLocal 实现)

Context ctx = Context.current();

d) 获取当前线程的上下文,进行跨线程传递(一般在异步场景才用到)

public class Demo {
    public void asyncDemo() {
        //获取当前线程的请求上下文
        Context ctx = Context.current();

        //跨线程传递当前请求上下文
        RunUtil.async(()->{
            try {
                ContextUtil.currentSet(ctx);

                //... Context.current() 有值...
            } finally {
                ContextUtil.currentRemove();
            }
        });
    }
}

2、关于 context-path 的配置(基于 pathNew 实现)

添加配置即可:(v1.11.2 后支持)

server.contextPath: "/test-service/" #原路径仍能访问

或者:('!' 开头。v2.6.3 后支持)

server.contextPath: "!/test-service/" #原路径不能访问

3、几个特殊属性

属性说明备注
ctx.mainHandler()获取主请求处理路由器没有登记时,则为 null(基本属于 404 了)
ctx.controller()获取当前控制器实例如果不是 MVC 处理,则为 null
ctx.action()获取当前动作对象如果不是 MVC 处理,则为 null
ctx.action().method()获取当前动作的执行函数包装
ctx.errors获取MVC处理异常action 执行完成后才会有值
ctx.result获取MVC处理结果action 执行完成后才会有值
ctx.attr("output")获取 string 输出内容只要通过 ctx.output(str) 输出的都会有这个记录

提示:控制器里的 @Mapping 函数,即为 Action

4、请求相关的接口

请求相关接口说明
-request()->Object原始请求对象
-remoteIp()获取远程ip(也可能是代理的ip)
-remotePort()获取远程端口(也可能是代理的port)
-realIp()->String获取客户端真实IP
-isMultipart()-bool是否为分段内容
-isMultipartFormData()->bool是否为分段表单数据
-method()->String获取请求方式
-protocol()->String获取请求协议
-protocolAsUpper()->String获取请求协议并大写
-url()->String获取请求的URL字符串
-uri()->URI获取请求的URI
-path()->String获取请求的URI路径
-pathNew(String)设置新路径
-pathNew()->String获取新路径,不存在则返回原路径
-pathMap(String)->Map<String,String>获取请求的URI路径变量,根据路径表达式
-pathAsUpper()->String获取请求的URI路径并大写
-pathAsLower()->String获取请求的URI路径并小写
-userAgent()>String获取请求的UA
-contentLength()->long获取内容长度
-contentType()->String获取内容类型
-queryString()->String获取查询字符串
-accept()->String获取 Accept 头信息
-body()->String获取body内容
-body(String)->String获取body内容,并按指定字符串解码
-bodyNew()->String获取新的body
-bodyNew(String)设置新的body
-bodyAsBytes()->byte[]获取body内容为byte[]
-bodyAsStream()->InputStream获取body内容为Stream
-paramValues(String)->String[]获取参数数组
-param(String)->String获取参数
-paramOrDefault(String, String)->String获取参数,并给定默认值
-paramAsInt(String)->int获取参数并转为int
-paramAsInt(String, int)->int获取参数并转为int, 并给定默认值
-paramAsLong(String)->long获取参数并转为long
-paramAsLong(String, long)->long获取参数并转为long,并给定默认值
-paramAsDouble(String)->double获取参数并转为double
-paramAsDouble(String, double)->double获取参数并转为double,并给定默认值
-paramAsDecimal(String)->BigDecimal获取参数并转为BigDecimal
-paramAsDecimal(String, BigDecimal)->BigDecimal获取参数并转为BigDecimal,并给定默认值
-paramAsBean(Class<T>)->T获取参数并转为Bean
-paramMap()->MultiMap<String>获取所有参数集合
-paramNames()->Set<String>获取所有参数名字集合
-file(String)->UploadedFile获取上传文件,第一个
-fileMap()->MultiMap<UploadedFile>获取所有上传文件集合
-fileValues(String)->UploadedFile[]获取上传文件,可能有多个
-fileNames()->Set<String>获取所有上传文件名字集合
-filesDelete()删除所有上传的临时缓冲文件(如果有)
-cookie(String)->String获取 cookie
-cookieOrDefaul(String, String)->String获取 cookie, 并给定默认值
-cookieValues(String)->String[]获取 cookie 数组
-cookieMap()->MultiMap<String>获取所有 cookie 集合
-cookieNames()->Set<String>获取所有 cookie 名字集合
-header(String)->String获取 header
-headerOrDefault(String, String)->String获取 header,并给定默认值
-headerValues(String)->String[]获取 header 数组
-headerMap()->MultiMap<String>获取所有 header 集合
-headerNames()->Set<String>获取所有 header 名字集合

关于 MultiMap 接口的使用示例:

//for(遍历)
for(KeyValues<String> kv: ctx.paramMap()){ //headerMap(), cookieMap()
    String       val  = kv.getValue();  //单值
    List<String> val2 = ky.getValues(); //多值
}

//add(添加)
ctx.paramMap().add("list", "a1")
ctx.paramMap().add("list", "a2")

ctx.paramValues("list") -> String[] //获取多值

//put(替换)
ctx.paramMap().put("item", "a1")

ctx.param("item") -> String //获取单值

5、响应相关的接口

响应相关接口说明
-response()->Object原始响应对象
-charset(String)设置字符集
-contentType(String)设置内容类型
-contentTypeNew()获取设置的新内容类型
-contentLength(long)设置内容长度
-render(Object)渲染数据(比如将对象渲染为 Json 并输出)
-render(String, Map)渲染视图
-renderAndReturn(Object)->String渲染数据并返回
-output(byte[])输出 字节数组
-output(InputStream)输出 流对象
-output(String)输出 字符串
-output(Throwable)输出 异常对象
-outputAsJson(String)输出为json文本
-outputAsHtml(String)输出为html文本
-outputAsFile(DownloadedFile)输出为文件
-outputAsFile(File)输出为文件
-outputStream()->OutputStream获取输出流
-outputStreamAsGzip()->GZIPOutputStream获取压缩输出流
-flush()冲刷
-headerSet(String, String)设置响应 header
-headerAdd(String, String)添加响应 header
-headerOfResponse(String)获取响应 header
-headerValuesOfResponse(String)获取响应 header 数组
-headerNamesOfResponse()获取响应 header 所有名字
-cookieSet(String, String)设置响应 cookie
-cookieSet(String, String, int)设置响应 cookie
-cookieSet(String, String, String, int)设置响应 cookie
-cookieSet(String, String, String, String, int)设置响应 cookie
-cookieRemove(String)移徐响应 cookie
-redirect(String)302跳转地址
-redirect(String, int)跳转地址
-forward(String)服务端转换地址
-status()获取输出状态
-status(int)设置输出状态

6、会话相关的接口

会话相关接口说明
-sessionState()->SessionState获取 sessionState
-sessionId()->String获取 sessionId
-session(String)->Object获取 session 状态
-sessionOrDefault(String, T)->T获取 session 状态(类型转换,存在风险)
-sessionAsInt(String)->int获取 session 状态以 int 型输出
-sessionAsInt(String, int)->int获取 session 状态以 int 型输出, 并给定默认值
-sessionAsLong(String)->long获取 session 状态以 long 型输出
-sessionAsLong(String, long)->long获取 session 状态以 long 型输出, 并给定默认值
-sessionAsDouble(String)->double获取 session 状态以 double 型输出
-sessionAsDouble(String, double)->double获取 session 状态以 double 型输出, 并给定默认值
-sessionSet(String, Object)设置 session 状态
-sessionRemove(String)移除 session 状态
-sessionClear()清空 session 状态

7、其它查询

其它相关接口说明
+current()->Context获取当前线程的上下文
-getLocale()->Locale获取地区
-setLocale(Locale)设置地区
-setHandled(bool)设置处理状态
-getHandled()获取处理状态
-setRendered(bool)设置渲染状态
-getRendered()获取渲染状态
-attrMap()->Map获取自定义特性并转为Map
-attr(String)->Object获取上下文特性
-attrOrDefault(String, T)->T获取上下文特性,并设定默认值
-attrSet(String, Object)设置上下文特性
-attrSet(Map)设置上下文特性
-attrClear()清除上下文特性
-remoting()->bool是否为远程调用
-remotingSet(bool)设置是否为远程调用
-result:Object用于在处理链中透传处理结果
-errors:Throwable用于在处理链中透传处理错误
-controller()->Object获取当前控制器
-action()->Action获取当前动作