All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hxl.miniapi.core.MiniContext.kt Maven / Gradle / Ivy

There is a newer version: 1.3.3
Show newest version
package com.hxl.miniapi.core

import com.hxl.miniapi.core.auth.MiniAuthentication
import com.hxl.miniapi.core.convert.GsonConvert
import com.hxl.miniapi.core.convert.HttpParameteLocalDateTimeTypeConverter
import com.hxl.miniapi.core.convert.HttpParameterDateTypeConverter
import com.hxl.miniapi.core.convert.HttpParameterLocalDateTypeConverter
import com.hxl.miniapi.core.io.FileResourceLoader
import com.hxl.miniapi.core.io.JarResourceLoader
import com.hxl.miniapi.core.resolver.request.*
import com.hxl.miniapi.core.resolver.response.*
import com.hxl.miniapi.http.anno.RestController
import com.hxl.miniapi.http.HttpIntercept
import com.hxl.miniapi.http.server.CoolMiniWebServerImpl
import com.hxl.miniapi.http.server.WebServer
import com.hxl.miniapi.orm.AutowriteCrud
import com.hxl.miniapi.orm.BaseCrudRepository
import com.hxl.miniapi.orm.Mybatis
import com.hxl.miniapi.orm.MybatisCrudRepository
import com.hxl.miniapi.utils.*
import org.objectweb.asm.ClassReader
import java.lang.reflect.Method
import java.lang.reflect.Modifier
import java.net.URL
import javax.sql.DataSource

open class MiniContext : Context {
    companion object {
        const val URL_PROTOCOL_FILE = "file"
        const val URL_PROTOCOL_JAR = "jar"
        private var REST_CONTROLLER_CODE = "L${RestController::class.java.name.replace(".", "/")};"
        private var COMPONENT_CLASS = arrayOf(REST_CONTROLLER_CODE)
    }

    private val httpParameterTypeConverter: MutableList> = mutableListOf()

    /**
     * 请求映射
     */
    private val requestMappingHandlerMapping: RequestMappingHandlerMapping = RequestMappingHandlerMapping(this)

    /**
     * 参数解析器
     */
    private val argumentResolvers: MutableList = mutableListOf()

    /**
     * 结果转换器
     */
    private val resultResolver: MutableList = mutableListOf()

    /**
     * @description: 拦截器
     */

    private val httpIntercepts: MutableList = mutableListOf()


    /**
     * json转换器
     */
    private var jsonConvert: JsonConvert = GsonConvert()

    /**
     * 认证器
     */
    private var authentication: MiniAuthentication? = null

    /**
     * 数据源
     */
    private var dataSource: DataSource? = null

    /**
     * 所有component类
     */
    private val componentClass: MutableList> = mutableListOf()

    /**
     * 所有bean实例
     */
    private val beans = mutableMapOf, Any>()

    private val fileResourceLoader =FileResourceLoader()
    private val jarResourceLoader =JarResourceLoader()
    init {
        addArgumentResolvers(
            SessionArgumentResolver(),
            RequestUriArgumentResolver(),
            FilePartArgumentResolver(),
            PathVariableArgumentResolver(),
            RequestBodyArgumentResolver(this),
            RequestParamSimpleTypeArgumentResolver(this),
            ReferenceArgumentResolver(this),
        )

        //用于将String到T类型
        addHttpParameterTypeConverter(
            HttpParameteLocalDateTimeTypeConverter(),
            HttpParameterDateTypeConverter(),
            HttpParameterLocalDateTypeConverter(),
            HttpParameterLocalDateTypeConverter()
        )

        addResultResolvers(
            HttpStatusResponseResolver(this.jsonConvert),
            StringResultResolver(),
            InputStreamResulResolver(),
            SimpleTypeResultResolver(),
            JsonResultResolver(this.jsonConvert)
        )

    }

    override fun getArgumentResolvers(): List {
        return this.argumentResolvers
    }

    override fun getRequestMappingHandlerMapping(): RequestMappingHandlerMapping {
        return this.requestMappingHandlerMapping
    }

    override fun addHttpIntercept(httpIntercept: HttpIntercept) {
        this.httpIntercepts.add(httpIntercept)
    }

    override fun getHttpIntercept(): List {
        return this.httpIntercepts
    }

    override fun createWebServer(): WebServer {
        return CoolMiniWebServerImpl(this)
    }

    override fun refresh(start: Class<*>) {
        componentClass.clear()
        val resources = ClassLoader.getSystemClassLoader().getResources(start.`package`.name.replace(".", "/"))
        val classResources = mutableListOf()
        for (resource in resources) {
            println("resource= ${resource} +protocol=${resource.protocol}")
            if (URL_PROTOCOL_FILE == resource.protocol) {
                classResources.addAll(fileResourceLoader.getResources(resource.file))
            }
            if (URL_PROTOCOL_JAR == resource.protocol) {
                classResources.addAll(jarResourceLoader.getResources(resource.file))
            }
        }
        findComponentClass(classResources)
        registerIfRequestMapping()
        //如果存在数据源配置,则自动注入依赖
        this.beans.values.forEach(this::autowriteInjection)

    }


    /**
     * @description: 依赖注入
     * @date: 2022/10/6 上午6:36
     */

    private fun autowriteInjection(bean: Any) {
        if (dataSource == null)  return
        val mybatis = MybatisCrudRepository(Mybatis(dataSource!!))

        val beanFields = bean::class.java.declaredFields
        beanFields.forEach {
            if (it.getDeclaredAnnotation(AutowriteCrud::class.java) != null &&
                !Modifier.isFinal(it.modifiers) &&
                BaseCrudRepository::class.java.isAssignableFrom(it.type)) {
                it.isAccessible = true
                it.set(bean, mybatis)
            }
        }

    }


    /**
     * @description: 封装MappingInfo
     * @date: 2022/10/1 下午12:57
     */

    private fun registerIfRequestMapping() {
        this.componentClass.forEach { clazz ->
            //如果是标有@RestController的类
            if (isRestControllerClass(clazz)) clazz.declaredMethods.forEach(this::extractMappingMethod)
        }
    }


    /**
     * @description: 提取并注册Mapping方法
     * @date: 2022/10/6 上午6:34
     */

    private fun extractMappingMethod(method: Method) {
        if (method.declaringClass != Any::class.java) {
            method.getRequestMappingInfo()?.run {
                this.method = method
                this.urlPatterns = method.getRequestMappingAnnotation().getDefaultValue().addPrefixIfMiss("/")
                this.instance = beans.getOrPut(method.declaringClass) { method.declaringClass.instance() }
                //注册mapping映射
                requestMappingHandlerMapping.registerMapping(this)
            }
        }
    }

    /**
     * @description: 是否是RestController类
     * @date: 2022/10/1 下午1:04
     */

    private fun isRestControllerClass(clazz: Class<*>): Boolean {
        return clazz.getDeclaredAnnotation(RestController::class.java) != null
    }

    /**
     * @description: 找到所有component类
     * @date: 2022/10/1 下午12:56
     */

    private fun findComponentClass(classResources: List) {
        for (classResource in classResources) {
            val classNode = org.objectweb.asm.tree.ClassNode()
            ClassReader(classResource.openConnection().getInputStream()).accept(classNode, ClassReader.EXPAND_FRAMES)
            if ( classNode.visibleAnnotations==null) continue
            classNode.visibleAnnotations.forEach {
                if (COMPONENT_CLASS.contains(it.desc)) {
                    componentClass.add(classNode.name.toClass())
                }
            }
        }
    }

    override fun addArgumentResolvers(vararg argumentResolvers: ArgumentResolver) {
        argumentResolvers.forEach { this.argumentResolvers.add(it) }
    }

    override fun addResultResolvers(vararg resultResolver: ResultResolver) {
        resultResolver.forEach { this.resultResolver.add(it) }
    }

    override fun getResultResolvers(): List {
        return this.resultResolver
    }

    override fun setJsonConvert(jsonConvert: JsonConvert) {
        this.jsonConvert = jsonConvert
    }

    override fun getJsonConvert(): JsonConvert {
        return this.jsonConvert
    }

    override fun addHttpParameterTypeConverter(vararg httpParameterTypeConverter: HttpParameterTypeConverter<*>) {
        httpParameterTypeConverter.forEach { this.httpParameterTypeConverter.add(it) }
    }

    override fun getHttpParameterTypeConverter(): List> {
        return this.httpParameterTypeConverter
    }

    override fun setAuthorization(authentication: MiniAuthentication) {
        if (authentication.authUrl.isEmpty()) throw IllegalArgumentException("url参数不能为空")
        val newUrl = if (authentication.authUrl == "/") "/" else {
            if (!authentication.authUrl.startsWith("/")) {
                "/${authentication.authUrl}"
            } else {
                authentication.authUrl
            }
        }
        this.authentication = MiniAuthentication(newUrl.removeSuffix("/"), authentication.authentication)
    }

    override fun setDataSource(dataSource: DataSource) {
        this.dataSource = dataSource
    }

    override fun getAuthorization(): MiniAuthentication? {
        return this.authentication
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy