DARTVM Server Development (6⃣️ days)--processing requests with annotations

Source: Internet
Author: User
    • DARTVM Server Development (️ days)--hello world!
    • DARTVM Server Development (️ days)--processing requests
    • DARTVM Server Development (️ days)--pub Manager, return HTML page
    • DARTVM Server Development (️ days)--code optimization
    • DARTVM Server Development (️ days)--Log tool

In the previous article, we learned how to build a DARTVM server, in my flutter group sharing, some friends will be questioned, learning this is not as good as learning Golang,dart server What is the use of .... Wait, let me explain here, for the time being really useless, the DART server is running a language VM, and as the Java server is running the JVM, let's simply say what is language VM and JVM, language VM is specifically for a language to develop, and the JVM is a bytecode VM, This bytecode VM is a rule, as long as it is in accordance with its rules, no matter what language you can develop, but the premise is to convert to bytecode according to this rule, so that: the JVM relative performance without language VMs is better, but a wide range of language VMs because of the language design, so, It is possible to fully manipulate the VM through the language, can be compared with two similar, JVM and language VM is like auniversal driver and the original driver, of course, this is a similar comparison, not too serious! Well, Balabala, said a lot, summed up: at present flutter based on dart language, learning DARTVM development helps to play the Dart Foundation, the foundation played well, the development of Flutter SAO operation is more! Also suitable for walking dart Web development

Below, if you follow the instructions carefully, you will learn how to use annotations, get annotations using reflection, and invoke methods through reflection.


Image

1. Defining annotations (Dart called metadata)

In Java, if you customize an annotation, you need to add @Target scope annotations,@Retention annotation type annotations, add @interface, and then define the annotation parameters, and now tell you, Not in Dart, we just need to define the entity class as well, the code is as follows

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

Note that the constructor method needs to add a const modifier, which is defined as the compile-time constant, and the following is the use of the

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

Then we have the controller identified as the first path of the controller, if not ignored,
Next we'll define a @request annotation

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

The above defines a second path, followed by a request method, and we then get the comment on the get and post based on this request.

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';}

You can see that the get and post annotations inherit the request, passing a specific requested method
Now that we are ready with these annotations, we now use these annotations to write the 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();  }}

Well, ask to write play, then, how do we associate these annotations, the following will be used to reflect!

2. Resolving annotation classes with reflection

Dart contains a mirror bag, which can be passed through the class to parse the metadata (i.e. annotations), and can be passed through the mirror parameters to invoke the method, in order to manage these controllers, we define a basecontroller, Let the controller that handles the request inherit this class

//抽象类abstract class BaseController{}

The above method is an empty method, we do not add anything, and then let Usercontroller inherit this class

@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();  }}

Below, we import the mirror bag and create a new Controllermanager to manage the controller

Import ' dart:mirrors '; import ' Dart:io '; class controllermanager{static Controllermanager manager=new Controllermanager ();//The List is used to determine if the controller has been added list<basecontroller> controllers=[];//This is a map, corresponding to the request link,  With the corresponding controller information map<string,controllerinfo> urltomirror=new Map (); Add controller void Addcontroller (Basecontroller Controller) {//Determine if the controller is currently added if (!controllers.contains (Controller)) {con    Trollers.add (Controller);//Add Map Urltomirror.addall (Getrequestinfo (Controller)); }}//the Controllermanager process request method void Requestserver (HttpRequest request) {//path of the current request String path=request.uri.tostring    ();     Method of the current request String Method=request.method;      Determine if the map contains the request address if (Urltomirror.containskey (path)) {Controllerinfo info=urltomirror[path];//gets to the request, the delivery path, the request method, and the request    Info.invoke (path, method, request); }else{//No this address returns a 404 request.response. Statuscode=httpstatus.notfound. Write (' {' {' Code ': 404, ' msg ': ' The link does not exist! "}''')     ..    Close (); } }} 

The idea is that, at initialization, all controllers are added to the map to request the path to key to find, when requested, the request address in the map to find, for it processing the request, if not found, give it a 404 of information, Here's 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();    }  }}

The main is the Symbol, instancemirror these two classes, through the Instancemirror.invoke (parameters passed by symbol,[]), you can call the corresponding method
We also have a method for adding a controller to map in Controllermanager getrequestinfo (Controller) is not described, This is the key to getting instancemirror and symbol, and the following describes getting instancemirror and symbol

Pass a controller in. map<string,controllerinfo> Getrequestinfo (Basecontroller Controller) {//actual returned MAP map< string,controllerinfo> info=new Map ()///Request address corresponding method map<string,symbol> urltomethod=new map ();// Get the Mirror of the controller instance Instancemirror im = reflect (Controller);//Get the Controller runtime type mirror classmirror Classmirror = im.type;// The root path of the request list<string> path = [];//all received request address of the Controller list<string> urllist=[];//get metadata, is to get @controller (  PATH:XXX) in the xxx ClassMirror.metadata.forEach ((medate) {path.add (Medate.reflectee.path);  }); Get all the methods of the class ClassMirror.declarations.forEach ((symbol, declarationmirror) {//) to remove its own construction method if (symbol.tostring ()! = CL        AssMirror.simpleName.toString ()) {//Gets the metadata of the method, which is @get (Path:path) DeclarationMirror.metadata.forEach ((medate) {        The requested address is String Requestpath = path.join () + Medate.reflectee.path;    Type of request String method = medate.reflectee.method;//Print (' request address: $requestPath, request method: $method '); Add to request addressSet Urllist.add (Requestpath);//Add to the collection of request address corresponding method Urltomethod.putifabsent (' $requestPath # $method ', () =>symbol);    }      ); }});//Instantiate a controller information controllerinfo controllerinfo=new controllerinfo (IM, urltomethod);//loop add to the map you actually need,  The corresponding request address root controllerinfo information Urllist.foreach ((URL) {info.putifabsent (URL, () =>controllerinfo); });//return the required map return info;}

The above note has been written very detailed, if not clear, I will explain again:

    • Reflect (Controller) >>>> Instancemirror (with instance of controller, callable method)
    • Instancemirror.type >>>> Classmirror (to get annotations for a class)
    • Classmirror. Metadata >>>>> get metadata for a class
    • Classmirror.declarations >>>> (symbol, declarationmirror) gets all the method names of the class (used to invoke the method), mirrors (for retrieving metadata)
    • Declarationmirror.metadata >>>> Get the metadata for a method
      Well, basically finished, and then we're going to use that Controllermanager

3. Using Controllermanager

First we need to add the controller we need to the Controllermanager before running the server (this is a stupid method, if a big guy knows how to automatically scan the controller and add it to Controllermanager, Please tell the younger brother, thank you!)

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

Then replace our previous handlemessage (Request) method with the

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

When all is done, let's take a break and then click the Green button to start our server and enter Http://localhost:8080/user/login
Witness the Miracle!

Success. png
As you can see, we successfully use annotations to process requests!
Today's content is basically these, if you study the article carefully, for flutter development can also use annotations to log in, to request data, well, thank you! We'll see you tomorrow!

If you want to continue to learn DARTVM server development, please pay attention to me, learn more SAO operation!

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.