001/** 002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package io.jboot.web.render; 017 018import com.jfinal.render.Render; 019import com.jfinal.render.RenderException; 020import com.jfinal.render.RenderManager; 021import com.jfinal.template.Engine; 022import io.jboot.Jboot; 023import io.jboot.utils.StrUtil; 024import io.jboot.web.render.cdn.JbootWebCdnConfig; 025import io.jboot.ext.MixedByteArrayOutputStream; 026import io.jboot.web.render.cdn.CdnUtil; 027 028import java.io.IOException; 029import java.io.PrintWriter; 030import java.util.Enumeration; 031import java.util.HashMap; 032import java.util.Map; 033 034public class JbootRender extends Render { 035 036 private static Engine engine; 037 private static String contentType = "text/html; charset=" + getEncoding(); 038 private static JbootWebCdnConfig cdnConfig = Jboot.config(JbootWebCdnConfig.class); 039 040 private Engine getEngine() { 041 if (engine == null) { 042 engine = RenderManager.me().getEngine(); 043 } 044 return engine; 045 } 046 047 public JbootRender(String view) { 048 if (StrUtil.isBlank(view)){ 049 throw new IllegalArgumentException("view cannot be null or empty."); 050 } 051 this.view = view; 052 } 053 054 public String getContentType() { 055 return contentType; 056 } 057 058 @Override 059 public void render() { 060 response.setContentType(getContentType()); 061 062 Map<Object, Object> data = new HashMap<Object, Object>(); 063 for (Enumeration<String> attrs = request.getAttributeNames(); attrs.hasMoreElements(); ) { 064 String attrName = attrs.nextElement(); 065 data.put(attrName, request.getAttribute(attrName)); 066 } 067 068 try { 069 if (cdnConfig.isEnable()) { 070 renderWithCdn(data); 071 } else { 072 getEngine().getTemplate(view).render(data, response.getWriter()); 073 } 074 } catch (RuntimeException e) { // 捕获 ByteWriter.close() 抛出的 RuntimeException 075 Throwable cause = e.getCause(); 076 if (cause instanceof IOException) { // ClientAbortException、EofException 直接或间接继承自 IOException 077 String name = cause.getClass().getSimpleName(); 078 if ("ClientAbortException".equals(name) || "EofException".equals(name)) { 079 return; 080 } 081 } 082 throw e; 083 } catch (IOException e) { 084 throw new RenderException(e); 085 } 086 } 087 088 private void renderWithCdn(Map<Object, Object> data) throws IOException { 089 MixedByteArrayOutputStream baos = new MixedByteArrayOutputStream(); 090 getEngine().getTemplate(view).render(data, baos); 091 092 PrintWriter responseWriter = response.getWriter(); 093 responseWriter.write(CdnUtil.toHtml(baos.getInputStream(), cdnConfig.getDomain())); 094 } 095 096 097 @Override 098 public String toString() { 099 return view; 100 } 101 102 103}