@@ -1,20 +1,29 @@
 | 
			
		||||
import { decorate, injectable } from "@ccms/container"
 | 
			
		||||
import { plugin } from '@ccms/api'
 | 
			
		||||
import { decorate, injectable, getContainer } from "@ccms/container"
 | 
			
		||||
 | 
			
		||||
import { METADATA_KEY, PARAM_TYPE } from '../constants'
 | 
			
		||||
import { interfaces } from "../interfaces"
 | 
			
		||||
import { addControllerMetadata, addControllerAction, addActionParam } from "./utils"
 | 
			
		||||
import { addControllerMetadata, addControllerAction, addActionParam, getControllerMetadata } from "./utils"
 | 
			
		||||
 | 
			
		||||
export const Controllers = (...controllers: any[]) => {
 | 
			
		||||
    return (target: any, propertyKey: string) => {
 | 
			
		||||
        for (const controller of controllers) {
 | 
			
		||||
            addControllerMetadata(getControllerMetadata(controller), target)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const Controller = (metadata?: string | interfaces.ControllerMetadata) => {
 | 
			
		||||
    return (target: any) => {
 | 
			
		||||
        if (!metadata) { metadata = target.name.toLowerCase().replace('controller', '') }
 | 
			
		||||
        if (typeof metadata === "string") { metadata = { path: metadata } }
 | 
			
		||||
        metadata.target = target
 | 
			
		||||
        metadata.name = metadata.name || target.name
 | 
			
		||||
        metadata.path = metadata.path ?? `/${metadata}`
 | 
			
		||||
        metadata.path = metadata.path.startsWith('/') ? metadata.path : `/${metadata.path}`
 | 
			
		||||
        decorate(injectable(), target)
 | 
			
		||||
        Reflect.defineMetadata(METADATA_KEY.Controller, metadata, target)
 | 
			
		||||
        addControllerMetadata(metadata)
 | 
			
		||||
        return
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -29,7 +38,6 @@ function action(method: interfaces.Method) {
 | 
			
		||||
            metadata.executor = propertyKey
 | 
			
		||||
            Reflect.defineMetadata(METADATA_KEY.Action, metadata, target[propertyKey])
 | 
			
		||||
            addControllerAction(target, propertyKey)
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -50,7 +58,6 @@ function param(type: PARAM_TYPE) {
 | 
			
		||||
            metadata.index = index
 | 
			
		||||
            metadata.paramtype = Reflect.getMetadata("design:paramtypes", target, propertyKey)[index]
 | 
			
		||||
            addActionParam(target, propertyKey, metadata)
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -72,7 +79,6 @@ function Middleware() {
 | 
			
		||||
            metadata.executor = propertyKey
 | 
			
		||||
            Reflect.defineMetadata(METADATA_KEY.Action, metadata, target[propertyKey])
 | 
			
		||||
            addControllerAction(target, propertyKey)
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,13 @@
 | 
			
		||||
import { interfaces } from '../interfaces'
 | 
			
		||||
import { METADATA_KEY } from '../constants'
 | 
			
		||||
 | 
			
		||||
export function getControllerMetadatas(): interfaces.ControllerMetadata[] {
 | 
			
		||||
    return Reflect.getMetadata(METADATA_KEY.Controller, Reflect) || []
 | 
			
		||||
export function getControllerMetadatas(target: any = Reflect): Map<string, interfaces.ControllerMetadata> {
 | 
			
		||||
    return Reflect.getMetadata(METADATA_KEY.Controller, target) || new Map<string, interfaces.ControllerMetadata>()
 | 
			
		||||
}
 | 
			
		||||
export function addControllerMetadata(metadata: interfaces.ControllerMetadata) {
 | 
			
		||||
    Reflect.defineMetadata(METADATA_KEY.Controller, [metadata, ...getControllerMetadatas()], Reflect)
 | 
			
		||||
export function addControllerMetadata(metadata: interfaces.ControllerMetadata, target: any = Reflect) {
 | 
			
		||||
    let metadatas = getControllerMetadatas(target)
 | 
			
		||||
    metadatas.set(metadata.name, metadata)
 | 
			
		||||
    Reflect.defineMetadata(METADATA_KEY.Controller, metadatas, target)
 | 
			
		||||
}
 | 
			
		||||
export function getControllerActions(target: any): string[] {
 | 
			
		||||
    return Reflect.getMetadata(METADATA_KEY.Action, target.constructor) || []
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@ export namespace interfaces {
 | 
			
		||||
        /**
 | 
			
		||||
         * 对象
 | 
			
		||||
         */
 | 
			
		||||
        target?: string
 | 
			
		||||
        target?: any
 | 
			
		||||
    }
 | 
			
		||||
    export interface ControllerMetadata extends WebMetadata {
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,11 @@
 | 
			
		||||
import * as querystring from 'querystring'
 | 
			
		||||
 | 
			
		||||
import { web } from '@ccms/api'
 | 
			
		||||
import { web, plugin } from '@ccms/api'
 | 
			
		||||
import { provideSingleton, JSClass, postConstruct, Container, ContainerInstance, inject } from '@ccms/container'
 | 
			
		||||
 | 
			
		||||
import { WebProxyBeanName, FilterProxyBeanName, METADATA_KEY, PARAM_TYPE } from './constants'
 | 
			
		||||
import { Context, InterceptorAdapter, RequestHandler, interfaces } from './interfaces'
 | 
			
		||||
import { getControllerActions, getActionMetadata, getControllerMetadata, getActionParams } from './decorators'
 | 
			
		||||
import { getControllerActions, getActionMetadata, getControllerMetadata, getActionParams, getControllerMetadatas } from './decorators'
 | 
			
		||||
 | 
			
		||||
const HttpServletRequestWrapper = Java.type('javax.servlet.http.HttpServletRequestWrapper')
 | 
			
		||||
const HttpServletResponseWrapper = Java.type('javax.servlet.http.HttpServletResponseWrapper')
 | 
			
		||||
@@ -25,6 +25,7 @@ export class Server {
 | 
			
		||||
    private StreamUtils = org.springframework.util.StreamUtils
 | 
			
		||||
    private ResponseEntity = org.springframework.http.ResponseEntity
 | 
			
		||||
 | 
			
		||||
    private pluginControllers: Map<string, any>
 | 
			
		||||
    private interceptors: Map<string, InterceptorAdapter>
 | 
			
		||||
    private methodMappings: Map<string, Map<string, RequestHandler>>
 | 
			
		||||
 | 
			
		||||
@@ -36,6 +37,8 @@ export class Server {
 | 
			
		||||
        this.interceptors = new Map()
 | 
			
		||||
        this.methodMappings = new Map()
 | 
			
		||||
        this.start()
 | 
			
		||||
        process.on('plugin.after.enable', (plugin: plugin.Plugin) => this.registryPlugin(plugin))
 | 
			
		||||
        process.on('plugin.after.disable', (plugin: plugin.Plugin) => this.unregistryPlugin(plugin))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    start() {
 | 
			
		||||
@@ -52,23 +55,34 @@ export class Server {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    registryPlugin(plugin: plugin.Plugin) {
 | 
			
		||||
        let controllers = getControllerMetadatas(plugin).values()
 | 
			
		||||
        for (const controller of controllers) {
 | 
			
		||||
            console.debug(`Plugin ${plugin.description.name} Registry Controller ${controller.name}.`)
 | 
			
		||||
            this.registryController(controller.target)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unregistryPlugin(plugin: plugin.Plugin) {
 | 
			
		||||
        let controllers = getControllerMetadatas(plugin).values()
 | 
			
		||||
        for (const controller of controllers) {
 | 
			
		||||
            console.debug(`Plugin ${plugin.description.name} Unregistry Controller ${controller.name}.`)
 | 
			
		||||
            this.unregistryController(controller.target)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    registryController(target: any) {
 | 
			
		||||
        if (!target) { throw new Error('Controller can\'t be undefiend!') }
 | 
			
		||||
        let controllerMetadata = getControllerMetadata(target)
 | 
			
		||||
        if (!controllerMetadata) { throw new Error(`Controller ${target.name} must have @Controller decorator!`) }
 | 
			
		||||
        try {
 | 
			
		||||
            this.container.rebind(METADATA_KEY.Controller).to(target).inSingletonScope().whenTargetNamed(target.name)
 | 
			
		||||
        } catch{
 | 
			
		||||
            this.container.bind(METADATA_KEY.Controller).to(target).inSingletonScope().whenTargetNamed(target.name)
 | 
			
		||||
        }
 | 
			
		||||
        target = this.container.getNamed(METADATA_KEY.Controller, target.name)
 | 
			
		||||
        target = this.bindController(target)
 | 
			
		||||
        let actions = getControllerActions(target)
 | 
			
		||||
        for (const action of actions) {
 | 
			
		||||
            let actionMetadata = getActionMetadata(target, action)
 | 
			
		||||
            let path = `${controllerMetadata.path || ''}${actionMetadata.path || ''}`
 | 
			
		||||
            if (!path) throw new Error(`Controller ${controllerMetadata.name} Action ${actionMetadata.name} path is empty!`)
 | 
			
		||||
            if (!this.methodMappings.has(path)) { this.methodMappings.set(path, new Map()) }
 | 
			
		||||
            console.debug(`Controller ${controllerMetadata.name} Registry ${path} to ${actionMetadata.executor || '<anonymous>'} Action function.`)
 | 
			
		||||
            console.debug(`Controller ${controllerMetadata.name} Registry ${path} Action to ${actionMetadata.executor || '<anonymous>'} function.`)
 | 
			
		||||
            this.methodMappings.get(path).set(actionMetadata.method || 'ALL', (ctx: Context) => {
 | 
			
		||||
                let args = []
 | 
			
		||||
                let params = getActionParams(target, action)
 | 
			
		||||
@@ -97,6 +111,15 @@ export class Server {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private bindController(target: any) {
 | 
			
		||||
        try {
 | 
			
		||||
            this.container.rebind(METADATA_KEY.Controller).to(target).inSingletonScope().whenTargetNamed(target.name)
 | 
			
		||||
        } catch{
 | 
			
		||||
            this.container.bind(METADATA_KEY.Controller).to(target).inSingletonScope().whenTargetNamed(target.name)
 | 
			
		||||
        }
 | 
			
		||||
        return this.container.getNamed(METADATA_KEY.Controller, target.name)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unregistryController(target: any) {
 | 
			
		||||
        if (!target) { throw new Error('Controller can\'t be undefiend!') }
 | 
			
		||||
        let controllerMetadata = getControllerMetadata(target)
 | 
			
		||||
@@ -112,6 +135,7 @@ export class Server {
 | 
			
		||||
            let path = `${controllerMetadata.path || ''}${actionMetadata.path || ''}`
 | 
			
		||||
            if (!this.methodMappings.has(path)) { continue }
 | 
			
		||||
            this.methodMappings.get(path).delete(actionMetadata.method)
 | 
			
		||||
            console.debug(`Controller ${controllerMetadata.name} Unregistry ${path} Action.`)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -130,7 +154,9 @@ export class Server {
 | 
			
		||||
        this.interceptors.set(interceptor.name, interceptor)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unregistryInterceptor(interceptor: InterceptorAdapter) {
 | 
			
		||||
    unregistryInterceptor(interceptor: string | InterceptorAdapter) {
 | 
			
		||||
        if (typeof interceptor === "string") { interceptor = { name: interceptor } }
 | 
			
		||||
        console.debug(`Unregistry ${interceptor.name} Interceptor.`)
 | 
			
		||||
        this.interceptors.delete(interceptor.name)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -170,12 +196,12 @@ export class Server {
 | 
			
		||||
    //     return wrapper
 | 
			
		||||
    // }
 | 
			
		||||
 | 
			
		||||
    private notFound(method: string, path: string) {
 | 
			
		||||
    private notFound(ctx: Context) {
 | 
			
		||||
        return {
 | 
			
		||||
            status: 404,
 | 
			
		||||
            msg: "handlerMapping Not Found!",
 | 
			
		||||
            method,
 | 
			
		||||
            path,
 | 
			
		||||
            method: ctx.request.getMethod(),
 | 
			
		||||
            path: ctx.request.getRequestURI(),
 | 
			
		||||
            timestamp: Date.now()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -184,12 +210,7 @@ export class Server {
 | 
			
		||||
        try { this.beanFactory.destroySingleton(WebProxyBeanName) } catch (ex) { }
 | 
			
		||||
        var WebServerProxyNashorn = Java.extend(this.WebServerProxy, {
 | 
			
		||||
            process: (req: javax.servlet.http.HttpServletRequest, resp: javax.servlet.http.HttpServletResponse) => {
 | 
			
		||||
                let path = req.getRequestURI()
 | 
			
		||||
                if (!this.methodMappings.has(path)) return this.notFound(req.getMethod(), path)
 | 
			
		||||
                let mappings = this.methodMappings.get(req.getRequestURI())
 | 
			
		||||
                let handler = mappings.get(req.getMethod()) || mappings.get("ALL")
 | 
			
		||||
                if (!handler) return this.notFound(req.getMethod(), path)
 | 
			
		||||
                let ctx: Context = { request: req, response: resp, params: {}, body: {}, handler }
 | 
			
		||||
                let ctx: Context = { request: req, response: resp, params: {}, body: {} }
 | 
			
		||||
                ctx.url = req.getRequestURI()
 | 
			
		||||
                // @ts-ignore
 | 
			
		||||
                ctx.headers = { __noSuchProperty__: (name: string) => req.getHeader(name) }
 | 
			
		||||
@@ -250,6 +271,10 @@ export class Server {
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        let path = ctx.request.getRequestURI()
 | 
			
		||||
        if (!this.methodMappings.has(path)) return this.notFound(ctx)
 | 
			
		||||
        let mappings = this.methodMappings.get(ctx.request.getRequestURI())
 | 
			
		||||
        ctx.handler = mappings.get(ctx.request.getMethod()) || mappings.get("ALL")
 | 
			
		||||
        ctx.result = this.execRequestHandle(ctx)
 | 
			
		||||
        for (const [_, interceptor] of this.interceptors) {
 | 
			
		||||
            if (interceptor.postHandle) {
 | 
			
		||||
@@ -283,6 +308,7 @@ Handle   Time   : ${Date.now() - startTime}ms
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private execRequestHandle(ctx: Context) {
 | 
			
		||||
        if (!ctx.handler) return this.notFound(ctx)
 | 
			
		||||
        try {
 | 
			
		||||
            return ctx.handler(ctx)
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user