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

xyz.erupt.tpl.service.EruptTplService Maven / Gradle / Ivy

The newest version!
package xyz.erupt.tpl.service;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.stereotype.Service;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.Assert;
import org.springframework.util.LinkedCaseInsensitiveMap;
import org.springframework.util.PathMatcher;
import xyz.erupt.annotation.sub_erupt.Tpl;
import xyz.erupt.core.service.EruptApplication;
import xyz.erupt.core.util.EruptSpringUtil;
import xyz.erupt.tpl.annotation.EruptTpl;
import xyz.erupt.tpl.annotation.TplAction;
import xyz.erupt.tpl.engine.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Writer;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * @author YuePeng
 * date 2020-02-24
 */
@Order
@Service
@Slf4j
public class EruptTplService {

    public static String TPL = "tpl";

    private static final Map> tplEngines = new HashMap<>();

    private static final Class[] engineTemplates = {
            NativeEngine.class,
            FreemarkerEngine.class,
            ThymeleafEngine.class,
            VelocityTplEngine.class,
            BeetlEngine.class,
            EnjoyEngine.class
    };

    static {
        for (Class tpl : engineTemplates) {
            try {
                EngineTemplate engineTemplate = (EngineTemplate) tpl.newInstance();
                engineTemplate.setEngine(engineTemplate.init());
                tplEngines.put(engineTemplate.engine(), engineTemplate);
            } catch (NoClassDefFoundError ignored) {
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

    private final Map tplActions = new LinkedCaseInsensitiveMap<>();

    private final Map tplMatcherActions = new LinkedCaseInsensitiveMap<>();

    private final PathMatcher pathMatcher = new AntPathMatcher();

    @Resource
    private HttpServletRequest request;

    @Resource
    private HttpServletResponse response;

    public void run() {
        EruptSpringUtil.scannerPackage(EruptApplication.getScanPackage(),
                new TypeFilter[]{new AnnotationTypeFilter(EruptTpl.class)},
                this::registerTpl);
    }

    //注册模板
    public void registerTpl(Class tplClass) {
        Arrays.stream(tplClass.getDeclaredMethods()).forEach(method -> Optional.ofNullable(method.getAnnotation(TplAction.class))
                .ifPresent(it -> {
                            if (pathMatcher.isPattern(it.value())) {
                                tplMatcherActions.put(it.value(), method);
                            } else {
                                tplActions.put(it.value(), method);
                            }
                        }
                ));
    }

    //移除模板
    public void unregisterTpl(Class tplClass) {
        Arrays.stream(tplClass.getDeclaredMethods()).forEach(
                method -> Optional.ofNullable(method.getAnnotation(TplAction.class)).ifPresent(
                        it -> {
                            tplActions.remove(it.value());
                            tplMatcherActions.remove(it.value());
                        }
                )
        );
    }

    public Method getAction(String path) {
        if (tplActions.containsKey(path)) {
            return tplActions.get(path);
        } else {
            // 从模糊匹配中查询资源路径
            for (Map.Entry entry : tplMatcherActions.entrySet()) {
                if (pathMatcher.match(entry.getKey(), path)) {
                    return entry.getValue();
                }
            }
        }
        return null;
    }

    public Object getEngine(Tpl.Engine engine) {
        return tplEngines.get(engine).getEngine();
    }

    @SneakyThrows
    public void tplRender(Tpl tpl, Map map, HttpServletResponse response) {
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        this.tplRender(tpl, map, response.getWriter());
    }

    public void tplRender(Tpl tpl, Map map, Writer writer) {
        if (!tpl.tplHandler().isInterface()) {
            Tpl.TplHandler tplHandler = EruptSpringUtil.getBean(tpl.tplHandler());
            map = Optional.ofNullable(map).orElse(new HashMap<>());
            tplHandler.bindTplData(map, tpl.params());
        }
        this.tplRender(tpl.engine(), tpl.path(), map, writer);
    }

    @SneakyThrows
    public void tplRender(Tpl.Engine engine, String path, Map map, Writer writer) {
        map = Optional.ofNullable(map).orElse(new HashMap<>());
        map.put(EngineConst.INJECT_REQUEST, request);
        map.put(EngineConst.INJECT_RESPONSE, response);
        map.put(EngineConst.INJECT_BASE, request.getContextPath());
        EngineTemplate engineAbstractTemplate = tplEngines.get(engine);
        Assert.notNull(engineAbstractTemplate, engine.name() + " jar not found");
        engineAbstractTemplate.render(engineAbstractTemplate.getEngine(), path, map, writer);
    }

}