前言
在单页面应用(SPA,Single Page Application)开发中,点击不同的菜单,通常需要动态获取其对应的Html页面代码,返回给前端,再将这一整块append到主框架页面的某个指定div中。所以,Java如何获取Html代码呢?
开发环境中
如在Eclipse中开发一个基于SpringBoot的SPA,每次右键-Run As/Debug As主类来运行项目,那如何找到某指定页面的html文件呢?如下(字节流):
/**
* 获取对应pageName的html内容(本地eclipse里直接run)<br>
* 字节流方式读取文件,可能读断一个中文字符,导致乱码
*/
@Deprecated
private String getHtmlByPageName(String pageName) {
URL url = this.getClass().getClassLoader().getResource("templates/" + pageName + ".html");
LOGGER.info("pageName : {} - {}", pageName, url);
// File f = new
// File("E:\\code_svn\\srp_trunk\\target\\classes\\templates\\404.html");
StringBuffer sb = new StringBuffer();
BufferedInputStream bis = null;
try {
File f = new File(url.toURI());
FileInputStream fis = new FileInputStream(f);
bis = new BufferedInputStream(fis);
int len = 0;
byte[] temp = new byte[1024];
while ((len = bis.read(temp)) != -1) {
sb.append(new String(temp, 0, len));
}
LOGGER.debug("page content:\n{}...", sb.toString().substring(0, 200));
} catch (Exception e) {
LOGGER.error("Error occurred, cause by: ", e);
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
LOGGER.error("Error occurred, cause by: ", e);
}
}
}
return sb.toString();
}
注意事项
采用字节流读取文本,容易读断一个完整的汉字,从而造成页面部分汉字乱码,如��。
所以,以字符流方式读取更佳,如下(字符流):
/**
* 获取对应pageName的html内容(本地eclipse里直接run)<br>
* 字符流方式读取文件
*/
private String getHtmlByPageName1(String pageName) {
URL url = this.getClass().getClassLoader().getResource("templates/" + pageName + ".html");
LOGGER.info("pageName : {} - {}", pageName, url);
// File f = new
// File("E:\\code_svn\\srp_trunk\\target\\classes\\templates\\404.html");
StringBuffer sb = new StringBuffer();
BufferedInputStream bis = null;
try {
File f = new File(url.toURI());
FileInputStream fis = new FileInputStream(f);
bis = new BufferedInputStream(fis);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
String s = "";
while ((s = br.readLine()) != null) {
sb.append(s).append("\n");
}
LOGGER.debug("page content:\n{}...", sb.toString().substring(0, 200));
} catch (Exception e) {
LOGGER.error("Error occurred, cause by: ", e);
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
LOGGER.error("Error occurred, cause by: ", e);
}
}
}
return sb.toString();
}
生产环境中
在生产环境中,不同于开发环境,我们经常需要java -jar来运行目标jar包,那在SpringBoot打出来的jar包中,如何找到某指定页面的html文件呢?如下(字符流):
/**
* 获取对应pageName的html内容(生产环境java -jar直接run)
*/
private String getHtmlByPageName2(String pageName) throws IOException {
// /BOOT-INF/classes/templates/dashboard.html
String path = "/BOOT-INF/classes/templates/" + pageName + ".html";
// 返回读取指定资源的输入流
InputStream is = this.getClass().getResourceAsStream(path);
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String s = "";
StringBuffer sb = new StringBuffer();
while ((s = br.readLine()) != null) {
sb.append(s).append("\n");
}
return sb.toString();
}
注意每次readLine后都别忘了append换行符,否则会导致html中的<script>元素里的JavaScript,将从第一处双斜杠注释的地方往后,都作为注释内容的一部分(因为整个html都是长长一整行),最终很神奇地发现为何某些JavaScript代码没运行。
所以,我们需要在代码中,判断当前程序所处的环境是开发环境还是生产环境,以进入不同的获取页面代码的逻辑。
SpringBoot多环境配置
一般可放置多个application-{profile}.properties文件,并在application.properties中设置一默认环境,如下:
spring.profiles.active=test
要想改变运行环境,可修改上述配置为dev或其他,亦可通过命令行参数的方式设置,如下:
java -jar xxx.jar --spring.profiles.active=dev
判断SpringBoot运行环境
Java如何判断SpringBoot的运行环境呢?如下:
import java.util.Locale;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext context = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
// 传入线程中
public static <T> T getBean(String beanName) {
return (T) context.getBean(beanName);
}
// 国际化使用
public static String getMessage(String key) {
return context.getMessage(key, null, Locale.getDefault());
}
/// 获取当前环境
public static String getActiveProfile() {
return context.getEnvironment().getActiveProfiles()[0];
}
}
因此, 对于Java根据SpringBoot运行环境的不同,而走不同的getHtmlByPageName逻辑,如下:
String profile = SpringContextUtil.getActiveProfile();
if ("dev".equals(profile)) {
return getHtmlByPageName1(pageName);
} else {
return getHtmlByPageName2(pageName);
}
以上。