9.全局异常拦截器
全局异常拦截器可以拦截程序中出现的已知异常(主动声明的异常)和未知异常。关于异常拦截,建立一个全局异常拦截器,对程序中所有异常进行分类拦截,并友好的返回异常信息,有利于提高程序的健壮性。
构建全局异常拦截器:Throwable异常的顶级父类
1. 添加@ControllerAdvice注解,拦截所有的含有@RequestMapping注解的方法。
2. @ExceptionHandler(XxxException.class) 声明拦截的异常类型。
3. @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) 声明遇到此异常时响应的状态码。
例:拦截业务异常
@ExceptionHandler(BussinessException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ErrorTip notFount(BussinessException e) {
LogManager.me().executeLog(LogTaskFactory.exceptionLog(ShiroKit.getUser().getId(), e));
getRequest().setAttribute("tip", e.getMessage());
log.error("业务异常:", e);
//这里的ErrorTip类为 code + message 形式的自定义响应体结构。
return new ErrorTip(e.getCode(), e.getMessage());
}
当拦截未知异常的时候,可以将@ExceptionHandler(Throwable.class)中的异常类型设置为Throwable。
10.代码生成器
业务场景:开发新业务的时候,减少重复代码的编写,利用代码生成器构建业务框架模板。
Guns框架中的代码生成器是如何实现的?
原理:模板 + 变量 = 代码
设计方面分三块:config + engine + template
config:配置方面,定义全局配置,针对不同模板类型进行相关配置。
ContextConfig:全局基础配置
ControllerConfig:Controller模板配置
ServiceConfig:Service模板配置
DaoConfig:DAO模板配置
PageConfig:页面模板配置
engine:模板引擎,初始化config的相关配置,结合template进行代码生成。
AbstractTemplateEngine:抽象模板引擎父类
GunsTemplateEngine:Guns模板引擎
SimpleTemplateEngine:模板引擎具体实现类 -- 通用
template:采用beetl模板引擎进行模板页面的构造。
XxxController.java.btl
标记一点:模板设计模式,在GunsTemplateEngine中定义逻辑骨架,将实现步骤推迟到子类SimpleTemplateEngine中去完成。
骨架实现:这里只说明GunsTemplateEngine模板引擎中的重要方法。
protected GroupTemplate groupTemplate; //引入Beetl的组模板生成对象
//config的配置加入模板引擎 binding表明将config绑定模板页面中的变量,类比model.addAttribute()。
public void configTemplate(Template template){
template.binding("controller", super.getControllerConfig());
template.binding("context", super.getContextConfig());
template.binding("dao", super.getDaoConfig());
template.binding("service", super.getServiceConfig());
}
//重点:生成文件方法 template是模板页面路径,filePath是生成文件路径 -- 自定义
public void generateFile(String template,String filePath){
Template pageTemplate = groupTemplate.getTemplate(template);
configTemplate(pageTemplate);
//路径分隔符配置 基于不同平台系统
if(PlatformUtil.isWindows()){
filePath = filePath.replaceAll("/+|\\\\+","\\\\");
}else{
filePath = filePath.replaceAll("/+|\\\\+","/");
}
//生成文件目录
File file = new File(filePath);
File parentFile = file.getParentFile();
if(!parentFile.exists()){
parentFile.mkdirs();
}
try {
//渲染出生成文件
pageTemplate.renderTo(new FileOutputStream(file));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
//上述提到的模板设计模式,在此处得以应用,实现交给子类SimpleTemplateEngine去完成。
protected abstract void generatePageEditHtml();
protected abstract void generatePageAddHtml();
protected abstract void generatePageInfoJs();
protected abstract void generatePageJs();
protected abstract void generatePageHtml();
protected abstract void generateController();
protected abstract void generateDao();
protected abstract void generateService();
具体实现:SimpleTemplateEngine具体模板引擎实现类。
public class SimpleTemplateEngine extends GunsTemplateEngine {
@Override
protected void generatePageEditHtml() {
String path = ToolUtil.format(super.getContextConfig().getProjectPath() + getPageConfig().getPageEditPathTemplate(),
super.getContextConfig().getBizEnName(),super.getContextConfig().getBizEnName());
//核心代码:template为模板页面路径,path为自定义文件生成路径。
generateFile("gunsTemplate/page_edit.html.btl", path);
System.out.println("生成编辑页面成功!");
}
}
这里需要说明path的处理方式:
1. ToolUtil.format 格式化文本
public static String format(String template, Object... values) {
return StrKit.format(template, values);
}
调用了StrKit.format的静态方法,template为预设路径,values为需要替换预设路径中占位符的字符串集合。
例:StrKit.format("aaa {} ccc","bbb") 格式化后为:"aaa bbb ccc"
进入super.getContextConfig().getProjectPath() + getPageConfig().getPageEditPathTemplate()模板预设路径中:
pageEditPathTemplate = "\\src\\main\\webapp\\WEB-INF\\view\\" + contextConfig.getModuleName() + "\\{}\\{}_edit.html";
可以看到模板预设路径中含有{}占位符,因此,方法的第二个参数就是自定义的填充占位符的字符集。
经过填充占位符之后,拼接成自定义的文件生成路径作为generateFile的path。
2. ContextConfig 设置自定义的填充占位符字符集,即对全局配置ContextConfig成员变量进行赋值。
这部分可以自定义,字符集中主要包括:模块名 + 业务名 + ...
开启模板引擎,进行代码生成:
GunsTemplateEngine gunsTemplateEngine = new SimpleTemplateEngine();
//导入全局配置信息
gunsTemplateEngine.setContextConfig(contextConfig);
//代码生成器启动
gunsTemplateEngine.start();
start()方法:开启生成器进行代码生成。
//生成器开始方法
public void start() {
//配置之间的相互依赖
super.initConfig();
//生成模板 -- 判断各项配置开关是否开启,开启后进行生成 -- 实现交给子类去完成
if(super.contextConfig.getControllerSwitch()){
generateController();
}
if(super.contextConfig.getIndexPageSwitch()){
generatePageHtml();
}
if(super.contextConfig.getAddPageSwitch()){
generatePageAddHtml();
}
if(super.contextConfig.getEditPageSwitch()){
generatePageEditHtml();
}
if(super.contextConfig.getJsSwitch()){
generatePageJs();
}
if(super.contextConfig.getInfoJsSwitch()){
generatePageInfoJs();
}
if(super.contextConfig.getDaoSwitch()){
generateDao();
}
if(super.contextConfig.getServiceSwitch()){
generateService();
}
}