第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定

DartVM服務(wù)器開發(fā)(第六天)--利用注解處理請求

標簽:
Java

在之前的文章中,我们学习了如何建立一个DartVM服务器,在我对Flutter群分享时,有些群友会疑问,学习这个还不如学习golang,Dart服务器有什么用....等等,我这里先说明一下,就目前来说确实没什么用,dart服务器运行的是语言VM,而像java服务器运行的是jvm,我们简单来讲一下什么是语言VM跟JVM,语言VM是专门针对某种语言去开发,而JVM是一个字节码VM,这个字节码VM是规定了一个规则,只要是遵守它的规则,无论你是什么语言都可以开发,但前提是根据这个规则转换为字节码,所以说:JVM相对性能没有语言VM要好,但适用范围广泛,语言VM因为根据该语言设计的,所以,是可以通过该语言完全的操控VM,可以两个类似的相比较,JVM跟语言VM就好比万能驱动与原配驱动,当然这是类似的比较,不用太较真!好了,巴拉巴拉,说了一大堆,总结:目前Flutter基于dart语言,学习DartVM开发有助于打好Dart基础,基础打好了,开发Flutter的骚操作也就更多!同样也适合走Dart web开发的同学

下面,如果你跟着仔细操作,你将学会如何使用注解,使用反射获取注解、通过反射调用方法。


webp

image

1. 定义注解(dart叫元数据)

在java中,如果自定义一个注解,需要添加@Target作用域注解,@Retention注解类型注解,添加@interface,然后定义注解参数,那么现在告诉你,在dart都不用,我们只需要定义实体类一样就可以了,代码如下

class Controller{  final String path;//构造方法定义为编译时常量
  const Controller({this.path});  @override
  String toString() =>'Controller';//这里是区别其它注解}

要注意的是构造方法需要添加一个const修饰,定义为编译时常量,然后下面就是使用

@Controller(path: '/user')class UserController {
  
}

然后我们以Controller标识过的作为该Controller的第一段请求路径,如果没有path,就不定义path,
接下来我们再定义一个@Request注解

class Request{  final String path;  final String method;  const Request({this.path,this.method});  @override
  String toString() =>'Request';
}

上面定义了一个第二段请求路径,跟一个请求方法,然后我们根据这个Request再弄Get跟Post的注解

class Get extends Request{  final String path;  const Get({this.path}) : super(path : path,method: 'GET');  @override
  String toString() =>'Get';
}class Post extends Request{  final String path;  const Post({this.path}) : super(path : path, method: 'POST');  @override
  String toString() =>'Get';

}

可以看到Get跟Post注解都继承了Request,传递了特定的请求方法
现在我们都准备好了这些注解,我们用这些注解写一下请求

@Controller(path: '/user')class UserController{  @Get(path: '/login')  void login(HttpRequest request) {
    request.response
      ..statusCode = HttpStatus.ok
      ..writeln('LoginSuccess')
      ..close();
  }  @Post(path: '/logout')  void logout(HttpRequest request){
    request.response
      ..statusCode = HttpStatus.ok
      ..writeln('logoutSuccess')
      ..close();
  }  @Request(path: '/delete', method: 'DELETE')  void editUser(HttpRequest request){
    request.response
      ..statusCode = HttpStatus.ok
      ..writeln('DeleteSuccess')
      ..close();
  }
}

好了请求写完了,那么,我们怎么去关联这些注解呢,下面就要用到反射了!

2.使用反射解析注解类

dart里面含有一个镜子包dart:mirrors,这个包可以通过传入的类,去解析元数据(即注解),并可以通过镜子传递参数去调用方法,为了统一管理这些Controller,我们定义一个BaseController,让处理请求的Controller都继承这个类

//抽象类abstract class BaseController{
}

上面这个方法是一个空方法,我们不添加任何东西,然后让UserController继承这个类

@Controller(path: '/user')class UserController extends BaseController{  @Get(path: '/login')  void login(HttpRequest request) {
    request.response
      ..statusCode = HttpStatus.ok
      ..writeln('LoginSuccess')
      ..close();
  }  @Post(path: '/logout')  void logout(HttpRequest request){
    request.response
      ..statusCode = HttpStatus.ok
      ..writeln('logoutSuccess')
      ..close();
  }  @Request(path: '/delete', method: 'DELETE')  void editUser(HttpRequest request){
    request.response
      ..statusCode = HttpStatus.ok
      ..writeln('DeleteSuccess')
      ..close();
  }
}

下面,我们导入镜子包dart:mirrors,新建一个ControllerManager,用来去管理Controller

import 'dart:mirrors';import 'dart:io';class ControllerManager{  static ControllerManager manager=new ControllerManager();//该list用于判断Controller是否已经被添加
  List<BaseController> controllers=[];//这是一个map,对应的是请求链接,跟对应的controller信息
  Map<String,ControllerInfo> urlToMirror=new Map();  //添加控制器
  void addController(BaseController controller){//判断当前是否已经添加过控制器
    if(!controllers.contains(controller)){
      controllers.add(controller);//添加map
      urlToMirror.addAll(getRequestInfo(controller));
    }
  }//该controllerManager处理请求的方法
  void requestServer(HttpRequest request){    //当前请求的路径
    String path=request.uri.toString();    //当前请求的方法
    String method=request.method;   
  //判断map中是否包含该请求地址
    if(urlToMirror.containsKey(path)){
      ControllerInfo info=urlToMirror[path];//获取到该请求,传递路径、请求方法跟请求
      info.invoke(path, method, request);
    }else{//没有该地址返回一个404
     request.response
       ..statusCode=HttpStatus.notFound
       ..write('''{
    "code": 404,
    "msg": "链接不存在!"
}''')
     ..close();
    }
  }
}

上面的思路是,在初始化时,将所有的Controller都添加到map中以请求路径为key去查找,当请求时,请求地址在map中查找到,就为它处理请求,如果查找不到,就给它丢一个404的信息,下面是ControllerInfo

class ControllerInfo{//请求地址对应Controller中的方法,Symbol包含方法标识
  final Map<String,Symbol> urlToMethod;//该参数包含通过类初始化得到的实例镜子,可以通过该参数调用方法
  final InstanceMirror instanceMirror;  
//构造方法
  ControllerInfo(this.instanceMirror,this.urlToMethod);  //调用请求方法
  void invoke(String url,String method,HttpRequest request){  //判断是否该请求地址是对应的请求方法
    if(urlToMethod.containsKey('$url#$method')){//调用方法
      instanceMirror.invoke(urlToMethod['$url#$method'], [request]);
    }else {//请求方法不对,返回一个错误
      request.response
        ..statusCode=HttpStatus.methodNotAllowed
        ..write('''{
    "code": 405,
    "msg": "请求出错!"
}''')
        ..close();
    }
  }
}

主要的是Symbol、InstanceMirror这两个类,通过instanceMirror.invoke(Symbol,[传递的参数]),就能调用对应的方法了
我们在ControllerManager中还有一个添加Controller到map的方法getRequestInfo(controller)没有介绍,这个就是获取InstanceMirror跟Symbol的关键,下面介绍获取InstanceMirror跟Symbol

//传递一个Controller进去Map<String,ControllerInfo> getRequestInfo(BaseController controller) {// 实际返回的Map
  Map<String,ControllerInfo> info=new Map();//请求地址对应的方法
  Map<String,Symbol> urlToMethod=new Map();// 获取Controller实例的镜子
  InstanceMirror im = reflect(controller);//获取Controller运行时类型的镜子
  ClassMirror classMirror = im.type;//请求的根路径
  List<String> path = [];//该Controller的所有接收的请求地址
  List<String> urlList=[];//获取元数据,就是获取@Controller(path: xxx)中的xxx
  classMirror.metadata.forEach((medate) {
    path.add(medate.reflectee.path);
  });  //获取该类的所有方法
  classMirror.declarations.forEach((symbol, declarationMirror) {    //将自身的构造方法剔除
    if (symbol.toString() != classMirror.simpleName.toString()) {    //获取方法的元数据,就是@Get(path: path)
      declarationMirror.metadata.forEach((medate) {        //请求的地址
        String requestPath = path.join() + medate.reflectee.path;        //请求的类型
        String method = medate.reflectee.method;//        print('请求地址为:$requestPath,请求方法为:$method');
    //添加到请求地址集合
        urlList.add(requestPath);//添加到请求地址对应方法的集合
        urlToMethod.putIfAbsent('$requestPath#$method', ()=>symbol);
      }
      );
    }
  });//实例化一个Controller信息
  ControllerInfo controllerInfo=new ControllerInfo(im, urlToMethod);//循环添加到实际需要的Map,对应请求地址根ControllerInfo信息
  urlList.forEach((url){
    info.putIfAbsent(url, ()=>controllerInfo);
  });//返回需要的map
  return info;
}

上面的注释已经写的很明细了,如果不清楚,我再讲解下:

  • reflect(controller)  >>>>  InstanceMirror(含有Controller的实例,可调用方法)

  • InstanceMirror.type >>>> ClassMirror(为了获取类的注解)

  • classMirror. metadata  >>>>> 获取类的元数据

  • classMirror.declarations >>>> (symbol, declarationMirror) 获取该类的所有方法名(用于调用方法),镜子(用于获取元数据)

  • declarationMirror.metadata >>>> 获取方法的元数据
    好了,基本上讲完,然后我们去使用该ControllerManager

3. 使用ControllerManager

首先我们需要在运行服务器之前,将我们需要的Controller添加到ControllerManager中(这个比较笨的方法,如果有大佬知道怎么自动去扫描Controller添加到ControllerManager,请告知小弟,谢谢!)

  //添加控制器
  ControllerManager.manager.addController(new UserController());

然后将我们之前的 handleMessage(request)方法替换为

//....
          ControllerManager.manager.requestServer(request);//....

当所有操作完成之后,我们休息一会,然后点击绿色按钮,启动我们的服务器,并输入http://localhost:8080/user/login
见证奇迹!

webp




作者:rhyme_lph
链接:https://www.jianshu.com/p/59f6c00b9f4e


點擊查看更多內(nèi)容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優(yōu)質(zhì)文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續(xù)努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優(yōu)惠券免費領(lǐng)

立即參與 放棄機會
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號

舉報

0/150
提交
取消