Solon MVC 的 @Mapping 用法說明

带刺的坐椅發表於2024-11-16

在 Solon Mvc 裡,@Mapping 註解一般是配合 @Controller 和 @Remoting,作請求路徑對映用的。且,只支援加在 public 函式 或 類上

1、註解屬性

屬性 說明 備註
value 路徑 與 path 互為別名
path 路徑 與 value 互為別名
method 請求方式限定(def=all) 可用 @Post@Get 等註解替代此屬性
consumes 指定處理請求的提交內容型別 可用 @Consumes 註解替代此屬性
produces 指定返回的內容型別 可用 @Produces 註解替代此屬性
multipart 申明支援多分片請求(def=false) 如果為false,則自動識別

當 method=all,即不限定請求方式

2、支援的路徑對映表示式

符號 說明 示例
** 任意字元、不限段數 **/user/**
* 任意字元 /user/*
? 可有可無 /user/?
/ 路徑片段開始符和間隔符 //user
{name} 路徑變數申明 /user/{name}

路徑組合(控制器對映與動作對映)及應用示例:

import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Mapping;

@Mapping("/user") //或 "user",開頭自動會補"/"
@Controller
public void DemoController{

    @Mapping("") //=/user
    public void home(){ }
    
    @Mapping("/") //=/user/,與上面是有區別的,注意下。
    public void home2(){ }
    
    @Mapping("/?") //=/user/ 或者 /user,與上面是有區別的,注意下。
    public void home3(){ }
    
    @Mapping("list") //=/user/list ,間隔自動會補"/"
    public void getList(){ }
    
    @Mapping("/{id}") //=/user/{id}
    public void getOne(long id){ }
    
    @Mapping("/ajax/**") //=/user/ajax/**
    public void ajax(){ }
}

提醒:一個 @Mapping 函式不支援多個路徑的對映

3、引數注入

非請求引數的可注入物件:

型別 說明
Context 請求上下文(org.noear.solon.core.handle.Context)
Locale 請求的地域資訊,國際化時需要
ModelAndView 模型與檢視物件(org.noear.solon.core.handle.ModelAndView)

支援請求引數自動轉換注入:

  • 當變數名有對應的請求引數時(即有名字可對上的請求引數)
    • 會直接嘗試對請求引數值進行型別轉換
  • 當變數名沒有對應的請求引數時
    • 當變數為實體時:會嘗試所有請求引數做為屬性注入
    • 否則注入 null

支援多種形式的請求引數直接注入:

  • queryString
  • form-data
  • x-www-form-urlencoded
  • path
  • json body

其中 queryString, form-data, x-www-form-urlencoded, path 引數,支援 ctx.param() 介面統一獲取。

import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.ModelAndView;
import org.noear.solon.core.handle.UploadedFile;
import java.util.Locale;

@Mapping("/user") 
@Controller
public void DemoController{
    //非請求引數的可注入物件
    @Mapping("case1")
    public void case1(Context ctx, Locale locale , ModelAndView mv){ }
    
    //請求引數(可以是散裝的;支援 queryString, form;json,或支援的其它序列化格式)
    @Mapping("case2")
    public void case2(String userName, String nickName, long[] ids, List<String> names){ }
    
    //請求引數(可以是整裝的結構體;支援 queryString, form;json,或支援的其它序列化格式Mapping
    @Mapping("case3")
    public void case3(UserModel user){ }
    
    //也可以是混搭的
    @Mapping("case4")
    public void case4(Context ctx, UserModel user, String userName){  }
    
    //檔案上傳    //注意與 <input type='file' name="file1" /> 名字對上
    @Mapping("case5")
    public void case5(UploadedFile file1, UploadedFile file2){ } 
    
    //同名多檔案上傳
    @Mapping("case6")
    public void case6(UploadedFile[] file){ }  
}

提醒: ?user[name]=1&ip[0]=a&ip[1]=b&order.id=1 風格的引數注入,需要引入外掛:solon-serialization-properties

4、帶註解的引數注入

註解:

註解 說明
@Param 注入請求引數(包括:query-string、form)。起到指定名字、預設值等作用
@Header 注入請求 header
@Cookie 注入請求 cookie
@Path 注入請求 path 變數(因為框架會自動處理,所以這個只是標識下方便文件生成用)
@Body 注入請求體(一般會自動處理。僅在主體的 String, InputSteam, Map 時才需要)

註解相關屬性:

屬性 說明 適用註解
value 引數名字 @Param, @Header, @Cookie, @Path
name 引數名字(與 value 互為別名) @Param, @Header, @Cookie, @Path
required 必須的 @Param, @Header, @Cookie, @Body
defaultValue 預設值 @Param, @Header, @Cookie, @Body
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Mapping;
import org.noear.solon.annotation.Header;
import org.noear.solon.annotation.Body;
import org.noear.solon.annotation.Path;

@Mapping("/user") 
@Controller
public void DemoController{
    @Mapping("case1")
    public void case1(@Body String bodyStr){   }
    
    @Mapping("case2")
    public void case2(@Body Map<String,String> paramMap, @Header("Token") String token){ }
    
    @Mapping("case3")
    public void case3(@Body InputStream stream, @Cookie("Token") token){  }
    
    //這個用例加不加 @Body 效果一樣
    @Mapping("case4")
    public void case4(@Body UserModel user){  } 
    
    @Mapping("case5/{id}")
    public void case5(String id){  }
    
    //如果名字不同,才有必要用 @Path //否則是自動處理(如上)
    @Mapping("case5_2/{id}")
    public void case5_2(@Path("id") String name){  } 
    
    @Mapping("case6")
    public void case6(String name){ }
    
    //如果名字不同,才有必要用 @Param //否則是自動處理(如上)
    @Mapping("case6_2")
    public void case6_2(@Param("id") String name){ } 
    
    //如果要預設值,才有必要用 @Param
    @Mapping("case6_3")
    public void case6_3(@Param(defaultValue="world") String name){ }
    
    @Mapping("case7")
    public void case7(@Header String token){ }
    
    @Mapping("case7_2")
    public void case7_2(@Header String[] user){ } //v2.4.0 後支援
}

5、請求方式限定

可以1個或多個加個 @Mppaing 註解上,用於限定請求方式(不限,則支援全部請求方式

請求方式限定註解 說明
@Get 限定為 Http Get 請求方式
@Post 限定為 Http Post 請求方式
@Put 限定為 Http Put 請求方式
@Delete 限定為 Http Delete 請求方式
@Patch 限定為 Http Patch 請求方式
@Head 限定為 Http Head 請求方式
@Options 限定為 Http Options 請求方式
@Trace 限定為 Http Trace 請求方式
@Http 限定為 Http 所有請求方式
@Message 限定為 Message 請求方式
@To 標註轉發目標
@WebSokcet 限定為 WebSokcet 請求方式
@Sokcet 限定為 Sokcet 請求方式
@All 允許所有請求方式(預設)
其它限定註解 說明
@Produces 申明輸出內容型別
@Consumes 申明輸入內容型別(當輸出內容型別未包函 @Consumes,則響應為 415 狀態碼)
@Multipart 顯式申明支援 Multipart 輸入

例:

import org.noear.solon.boot.web.MimeType;

@Mapping("/user") 
@Controller
public void DemoController{
    @Get
    @Mapping("case1")
    public void case1(Context ctx, Locale locale , ModelAndView mv){ }
   
    //也可以直接使用 Mapping 的屬性進行限定。。。但是沒使用註解的好看
    @Mapping(path = "case1_2", method = MethodType.GET)
    public void case1_2(Context ctx, Locale locale , ModelAndView mv){ }
    
    @Put
    @Message
    @Mapping("case2")
    public void case2(String userName, String nickName){ }
    
    //如果沒有輸出申明,側 string 輸出預設為 "text/plain"
    @Produces(MimeType.APPLICATION_JSON_VALUE)
    @Mapping("case3")
    public String case3(){
        return "{code:1}";
    }
    
    ////也可以直接使用 Mapping 的屬性進行限定。。。但是沒使用註解的好看
    @Mapping(path= "case3_2", produces=MimeType.APPLICATION_JSON_VALUE))
    public String case3_2(){
        return "{code:1}";
    }
    
    //如果沒有輸出申明,側 object 輸出預設為 "application/json"
    @Mapping("case3_3")
    public User case3_3(){
        return new User();
    }
    
}

6、輸出型別

@Mapping("/user") 
@Controller
public void DemoController{

    //輸出檢視與模型,經後端渲染後輸出最終格式
    @Maping("case1")
    public ModelAndView case1(){
        ModelAndView mv = new ModelAndView();
        mv.put("name", "world");
        mv.view("hello.ftl");
        
        return mv;
    }
    
    //輸出結構體,預設會採用josn格式渲染後輸出
    @Maping("case2")
    public UserModel case2(){
        return new UserModel();
    }
    
    //輸出下載檔案
    @Maping("case3")
    public Object case3(){
        return new File(...); //或者 return new DownloadedFile(...);
    }
}

7、父類繼承支援

@Mapping("user")
public void UserController extends CrudControllerBase<User>{
           
}

public class CrudControllerBase<T>{
    @Post
    @Mapping("add")
    public void add(T t){
        ...
    }

    @Delete
    @Mapping("remove")
    public void remove(T t){
        ...
    }
}

相關文章