【Java代碼生成器】SpringBoot鼓鲁、SSM代碼生成器功能更新蕴轨,源碼全開放

引言

??代碼生成器一直有在斷斷續(xù)續(xù)的更新,只是由于時(shí)間關(guān)系沒能一直堅(jiān)持寫博客骇吭,但每天依然有朋友前去下載關(guān)注橙弱,對(duì)此我感到十分榮幸,源碼已經(jīng)全部開放至碼云绵跷,感興趣的朋友可以去文末鏈接自行提取查看膘螟,同時(shí)今天更新了幾個(gè)小功能,讓我們一起看一下吧碾局。

全局異常處理

??增加了全局異常處理模板:allExceptionHandler.ftl荆残,代碼很簡單,相信熟悉SpringBoot的朋友一眼就能看明白:

package ${packageName}.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

@ControllerAdvice
@ResponseBody
public class AllExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(AllExceptionHandler.class);

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public String handlerUnexcptedServer(Exception ex) {
        logger.error("發(fā)生系統(tǒng)異常净当,錯(cuò)誤信息為:" + ex.getMessage());
        return "系統(tǒng)異常内斯,請去后臺(tái)查看!";
    }
}

??這里直接捕獲了Exception類像啼,如果controller中的方法發(fā)生了異常俘闯,會(huì)統(tǒng)一運(yùn)行到此處進(jìn)行相應(yīng)的處理,原理不必多說:AOP忽冻,只不過Spirng已經(jīng)幫助我們實(shí)現(xiàn)了真朗,直接拿來用即可,這里所做的處理很簡單:打印錯(cuò)誤信息僧诚,返回錯(cuò)誤響應(yīng)遮婶。生成代碼之后大家可以根據(jù)需要自由擴(kuò)展。

日志切面

??日志對(duì)于一個(gè)系統(tǒng)來說是十分重要的湖笨,大多數(shù)情況下旗扑,我們需要在執(zhí)行方法的時(shí)候打印一些必要的日志,比如當(dāng)前執(zhí)行的方法慈省,執(zhí)行方法所需要的時(shí)間臀防,或者在方法運(yùn)行完畢后保存信息等。边败。袱衷。
??對(duì)于日志的處理,當(dāng)然需要抽離出去笑窜,否則代碼將變得十分冗余致燥,這個(gè)時(shí)候同樣需要使用AOP,自定義日志切面類怖侦,實(shí)現(xiàn)個(gè)性化的日志處理操作篡悟,代碼如下:

package ${packageName}.config;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LogAopAspect {

    private static final Logger logger = LoggerFactory.getLogger(LogAopAspect.class);


    @Around("execution(* ${packageName}.controller.*.*(..))")
    public Object process(ProceedingJoinPoint pjp) throws Throwable {

        Class<?> currentClass = pjp.getTarget().getClass();
        MethodSignature signature = (MethodSignature) (pjp.getSignature());
        String ClassName = currentClass.getSimpleName();
        String methodName = currentClass.getMethod(signature.getName(), signature.getParameterTypes()).getName();
        logger.info("======= 開始執(zhí)行:" + ClassName + " — " + methodName + " ========");
        Object obj = pjp.proceed();
        logger.info("======= 執(zhí)行結(jié)束:" + ClassName + " — " + methodName + " ========");
        return obj;

    }


}

??這里使用了Spirng的環(huán)繞通知,根據(jù)切入點(diǎn)表達(dá)式匾寝,Spring會(huì)掃描controller包下的所有類搬葬,生成相應(yīng)的代理類,添加相關(guān)操作艳悔,此處只是在方法執(zhí)行前和執(zhí)行后打印了相關(guān)的類名信息急凰,這樣一來,如果程序出現(xiàn)問題猜年,可以幫我們迅速找到錯(cuò)誤位置抡锈,提高系統(tǒng)的可維護(hù)性。

日志工具類

??增加了日志工具類模板:loggerUtil.ftl乔外,主要用來方便輸出日志和日常調(diào)試床三,代碼如下:

package ${packageName}.utils;

import org.slf4j.LoggerFactory;

/**
 * 日志工具類,使用靜態(tài)方法打印日志  無需每個(gè)類中定義日志對(duì)象
 * Logback對(duì)每個(gè)Logger對(duì)象做了緩存杨幼,每次調(diào)用LoggerFactory.getLogger(String name)時(shí)如果已存在則從緩存中獲取不會(huì)生成新的對(duì)象;
 * 同時(shí)也不會(huì)有對(duì)象的創(chuàng)建與銷毀造成的性能損失
 */
public class LoggerUtil {

    public static void error(String msg) {
        LoggerFactory.getLogger(getClassName()).error(msg);
    }

    public static void error(String msg, Object... obj) {
        LoggerFactory.getLogger(getClassName()).error(msg, obj);
    }

    public static void warn(String msg) {
        LoggerFactory.getLogger(getClassName()).error(msg);
    }

    public static void warn(String msg, Object... obj) {
        LoggerFactory.getLogger(getClassName()).error(msg, obj);
    }

    public static void info(String msg) {
        LoggerFactory.getLogger(getClassName()).info(msg);
    }

    public static void info(String msg, Object... obj) {
        LoggerFactory.getLogger(getClassName()).info(msg, obj);
    }

    public static void debug(String msg) {
        LoggerFactory.getLogger(getClassName()).debug(msg);
    }

    public static void debug(String msg, Object... obj) {
        LoggerFactory.getLogger(getClassName()).debug(msg, obj);
    }

    // 獲取調(diào)用 error,info,debug靜態(tài)類的類名
    private static String getClassName() {
        return new SecurityManager() {
            public String getClassName() {
                return getClassContext()[3].getName();
            }
        }.getClassName();
    }
}

??這個(gè)沒有什么可講的撇簿,其中getClassName方法通過返回當(dāng)前執(zhí)行堆棧的數(shù)組來獲取當(dāng)前調(diào)用此方法的類名,索引3處為我們需要獲取的類名差购。

excelUtil擴(kuò)展

??對(duì)excelUtil.ftl模板做了進(jìn)一步擴(kuò)展四瘫,增加了一些較為實(shí)用的方法,使用簡單欲逃,代碼如下:

private static final String XLS = "xls";
    private static final String XLSX = "xlsx";

    public static CellStyle creatCellStyle(SXSSFWorkbook workbook, boolean head) {
        CellStyle style = workbook.createCellStyle();
        //對(duì)齊方式設(shè)置
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBottomBorderColor(IndexedColors.BLACK.getIndex()); // 下邊框
        style.setBorderLeft(BorderStyle.THIN);
        style.setLeftBorderColor(IndexedColors.BLACK.getIndex()); // 左邊框
        style.setBorderRight(BorderStyle.THIN);
        style.setRightBorderColor(IndexedColors.BLACK.getIndex()); // 右邊框
        style.setBorderTop(BorderStyle.THIN);
        style.setTopBorderColor(IndexedColors.BLACK.getIndex()); // 上邊框
        style.setWrapText(true);// 設(shè)置自動(dòng)換行
        if (head) {
            //設(shè)置背景顏色
            style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
            style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            //粗體字設(shè)置
            Font font = workbook.createFont();
            font.setBold(true);
            style.setFont(font);
        }
        return style;
    }

/**
     * 根據(jù)文件后綴名類型獲取對(duì)應(yīng)的工作簿對(duì)象
     *
     * @param inputStream 讀取文件的輸入流
     * @param fileType    文件后綴名類型(xls或xlsx)
     * @return 包含文件數(shù)據(jù)的工作簿對(duì)象
     * @throws IOException
     */
    public static Workbook getWorkbook(InputStream inputStream, String fileType) throws IOException {
        Workbook workbook = null;
        if (fileType.equalsIgnoreCase(XLS)) {
            workbook = new HSSFWorkbook(inputStream);
        } else if (fileType.equalsIgnoreCase(XLSX)) {
            workbook = new XSSFWorkbook(inputStream);
        }
        return workbook;
    }


    /**
     * 讀取Excel文件內(nèi)容 每一行內(nèi)容使用Map封裝
     *
     * @param fileName 要讀取的Excel文件所在路徑
     * @return 讀取結(jié)果列表找蜜,讀取失敗時(shí)返回null
     */
    public static List<Map<String, String>> readExcelToRowMap(String fileName) {

        // 讀取excel中的數(shù)據(jù)
        Map<String, String> map = new LinkedHashMap<>();
        List<Map<String, String>> resultDataList = parseExcel(readExcel(fileName), map);

        return resultDataList;

    }

    public static List<Map<String, String>> readExcelToRowMap(File file) {

        // 讀取excel中的數(shù)據(jù)
        Map<String, String> map = new LinkedHashMap<>();
        List<Map<String, String>> resultDataList = parseExcel(readExcel(file), map);

        return resultDataList;

    }

    /**
     * 讀取Excel文件內(nèi)容 每一行內(nèi)容使用List封裝
     *
     * @param fileName 要讀取的Excel文件所在路徑
     * @return 讀取結(jié)果列表,讀取失敗時(shí)返回null
     */
    public static List<List<String>> readExcelToRowList(String fileName) {

        // 讀取excel中的數(shù)據(jù)
        List<String> list = new ArrayList<>();
        List<List<String>> resultDataList = parseExcel(readExcel(fileName), list);

        return resultDataList;

    }

    public static List<List<String>> readExcelToRowList(File file) {

        // 讀取excel中的數(shù)據(jù)
        List<String> list = new ArrayList<>();
        List<List<String>> resultDataList = parseExcel(readExcel(file), list);

        return resultDataList;

    }

    /**
     * 讀取excel獲得workbook
     *
     * @param e
     * @return
     */
    private static <E> Workbook readExcel(E e) {

        Workbook workbook = null;
        FileInputStream inputStream = null;

        try {

            String fileName = "";
            String fileType = "";
            File excelFile = null;
            if (e instanceof String) {
                // 獲取Excel后綴名
                fileName = (String) e;
                fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
                // 獲取Excel文件
                excelFile = new File(fileName);
                if (!excelFile.exists()) {
                    return null;
                }
                inputStream = new FileInputStream(excelFile);
                workbook = getWorkbook(inputStream, fileType);
            } else if (e instanceof File) {
                fileName = ((File) e).getName();
                fileType = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
                // 獲取Excel工作簿
                inputStream = new FileInputStream((File) e);
                workbook = getWorkbook(inputStream, fileType);
            }
            return workbook;
        } catch (Exception e1) {
            e1.printStackTrace();
            return null;
        } finally {
            try {
                if (null != workbook) {
                    workbook.close();
                }
                if (null != inputStream) {
                    inputStream.close();
                }
            } catch (Exception e2) {
                return null;
            }
        }
    }


    /**
     * 解析Excel數(shù)據(jù)
     *
     * @param workbook Excel工作簿對(duì)象
     * @return 解析結(jié)果
     */
    private static <E> List<E> parseExcel(Workbook workbook, E e) {

        if (workbook == null) {
            return null;
        }

        List<E> resultDataList = new ArrayList<>();
        // 解析sheet
        for (int sheetNum = 0; sheetNum < workbook.getNumberOfSheets(); sheetNum++) {
            Sheet sheet = workbook.getSheetAt(sheetNum);
            // 校驗(yàn)sheet是否合法
            if (sheet == null) {
                continue;
            }
            // 獲取第一行數(shù)據(jù)
            int firstRowNum = sheet.getFirstRowNum();
            Row firstRow = sheet.getRow(firstRowNum);
            if (null == firstRow) {
                System.out.println(sheet.getSheetName() + "無數(shù)據(jù)");
                continue;
            }

            //獲取head頭部
            Row headRow = sheet.getRow(firstRowNum);
            //獲取列數(shù)
            int numberOfCells = headRow.getPhysicalNumberOfCells();

            List<String> headList = new ArrayList<>();
            for (int i = 0; i < numberOfCells; i++) {
                Cell cell = headRow.getCell(i);
                String head = convertCellValueToString(cell);
                headList.add(head);
            }
            // 解析每一行的數(shù)據(jù)稳析,構(gòu)造數(shù)據(jù)對(duì)象
            int rowStart = firstRowNum + 1;

            int rowEnd = sheet.getPhysicalNumberOfRows();
            for (int rowNum = rowStart; rowNum < rowEnd; rowNum++) {
                Row row = sheet.getRow(rowNum);

                if (null == row) {
                    continue;
                }

                E resultData = null;
                if (e instanceof Map) {
                    resultData = (E) convertRowToDataMap(row, headList);
                } else {
                    resultData = (E) convertRowToDataList(row, headList);
                }

                if (null == resultData) {
                    continue;
                }
                resultDataList.add(resultData);
            }

        }

        return resultDataList;
    }


    /**
     * 將單元格內(nèi)容轉(zhuǎn)換為字符串
     *
     * @param cell
     * @return
     */

    private static String convertCellValueToString(Cell cell) {
        if (cell == null) {
            return "";
        }
        String returnValue = "";
        switch (cell.getCellType()) {
            case NUMERIC:   //數(shù)字
                if (DateUtil.isCellDateFormatted(cell)) {
                    Date date = cell.getDateCellValue();
                    DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// HH:mm:ss cellValue = df2.format(d);
                    returnValue = format.format(date);
                } else {
                    Double doubleValue = cell.getNumericCellValue();
                    // 格式化科學(xué)計(jì)數(shù)法洗做,取一位整數(shù)
                    DecimalFormat df = new DecimalFormat("0");
                    returnValue = df.format(doubleValue);
                }
                break;
            case STRING:    //字符串
                returnValue = cell.getStringCellValue();
                break;
            case BOOLEAN:   //布爾
                Boolean booleanValue = cell.getBooleanCellValue();
                returnValue = booleanValue.toString();
                break;
            case BLANK:     // 空值
                break;
            case FORMULA:   // 公式
                returnValue = cell.getCellFormula();
                break;
            case ERROR:     // 故障
                break;
            default:
                break;
        }
        return returnValue;
    }

    /**
     * 提取每一行中需要的數(shù)據(jù)到map中
     *
     * @param row 行數(shù)據(jù)
     * @return 解析后的行數(shù)據(jù)對(duì)象
     */
    private static Map<String, String> convertRowToDataMap(Row row, List<String> headList) {

        Map<String, String> resultData = new LinkedHashMap<>();

        for (int i = 0; i < headList.size(); i++) {
            Cell cell = row.getCell(i);
            String data = convertCellValueToString(cell);
            resultData.put(headList.get(i), data);
        }

        return resultData;

    }

    /**
     * 提取每一行中需要的數(shù)據(jù)到List中
     *
     * @param row 行數(shù)據(jù)
     * @return 解析后的行數(shù)據(jù)對(duì)象
     */
    private static List<String> convertRowToDataList(Row row, List<String> headList) {

        List<String> resultData = new ArrayList<>();


        for (int i = 0; i < headList.size(); i++) {
            Cell cell = row.getCell(i);
            String data = convertCellValueToString(cell);
            resultData.add(data);
        }

        return resultData;

    }

返回值日期格式化處理

??對(duì)于響應(yīng)返回值的日期類型做了格式化的處理,在SpringBoot中增加了如下配置:

spring:
    jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8

SSM中增加如下配置:

<mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                <property name="objectMapper">
                    <bean class="com.fasterxml.jackson.databind.ObjectMapper">
                        <property name="dateFormat">
                            <bean class="java.text.SimpleDateFormat">
                                <constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss" />
                            </bean>
                        </property>
                    </bean>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

??現(xiàn)在生成器會(huì)自動(dòng)加入此配置迈着。

源碼全開放

??代碼生成器的源碼已經(jīng)全部開放竭望,感興趣的朋友可以去碼云查看,readme中有具體的源碼解讀裕菠,地址為:https://gitee.com/zrxjava/codeMan咬清,感謝您的閱讀,下次再見奴潘!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末旧烧,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子画髓,更是在濱河造成了極大的恐慌掘剪,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,110評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奈虾,死亡現(xiàn)場離奇詭異夺谁,居然都是意外死亡廉赔,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門匾鸥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蜡塌,“玉大人,你說我怎么就攤上這事勿负×蟀” “怎么了?”我有些...
    開封第一講書人閱讀 165,474評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵奴愉,是天一觀的道長琅摩。 經(jīng)常有香客問我,道長锭硼,這世上最難降的妖魔是什么房资? 我笑而不...
    開封第一講書人閱讀 58,881評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮檀头,結(jié)果婚禮上志膀,老公的妹妹穿的比我還像新娘。我一直安慰自己鳖擒,他們只是感情好溉浙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蒋荚,像睡著了一般戳稽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上期升,一...
    開封第一講書人閱讀 51,698評(píng)論 1 305
  • 那天惊奇,我揣著相機(jī)與錄音,去河邊找鬼播赁。 笑死颂郎,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的容为。 我是一名探鬼主播乓序,決...
    沈念sama閱讀 40,418評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼坎背!你這毒婦竟也來了替劈?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,332評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤得滤,失蹤者是張志新(化名)和其女友劉穎陨献,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體懂更,經(jīng)...
    沈念sama閱讀 45,796評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡眨业,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評(píng)論 3 337
  • 正文 我和宋清朗相戀三年急膀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片龄捡。...
    茶點(diǎn)故事閱讀 40,110評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡脖阵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出墅茉,到底是詐尸還是另有隱情,我是刑警寧澤呜呐,帶...
    沈念sama閱讀 35,792評(píng)論 5 346
  • 正文 年R本政府宣布就斤,位于F島的核電站,受9級(jí)特大地震影響蘑辑,放射性物質(zhì)發(fā)生泄漏洋机。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評(píng)論 3 331
  • 文/蒙蒙 一洋魂、第九天 我趴在偏房一處隱蔽的房頂上張望绷旗。 院中可真熱鬧,春花似錦副砍、人聲如沸衔肢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽角骤。三九已至,卻和暖如春心剥,著一層夾襖步出監(jiān)牢的瞬間邦尊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評(píng)論 1 272
  • 我被黑心中介騙來泰國打工优烧, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蝉揍,地道東北人殖蚕。 一個(gè)月前我還...
    沈念sama閱讀 48,348評(píng)論 3 373
  • 正文 我出身青樓泰偿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親归露。 傳聞我的和親對(duì)象是個(gè)殘疾皇子熙卡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 開心一笑 【1.你以為我會(huì)眼睜睜的看著你去送死再膳?我會(huì)閉著眼睛挺勿。2.給你講個(gè)故事,從前有個(gè)笨蛋喂柒,他非常笨不瓶,別人問他問...
    架構(gòu)師啟示錄閱讀 9,599評(píng)論 1 45
  • 生成器(Generator)可以說是在 ES2015 中最為強(qiáng)悍的一個(gè)新特性禾嫉,因?yàn)樯善魇巧婕暗?ECMAScri...
    Will_Wen_Gunn閱讀 4,737評(píng)論 0 9
  • PPT:結(jié)構(gòu)化表達(dá)的方法與藝術(shù) 隨著MS Office及WPS等辦公軟件的普及,有著集文字蚊丐、圖像熙参、聲音、章節(jié)等一體...
    丁肇之閱讀 232評(píng)論 0 0
  • 所有愛喝酒的妹紙都是我的愛人 所有喝不醉的漢紙都是我的天敵 每一個(gè)姑娘都有一種酒的香氣 所以我才學(xué)會(huì)聞香識(shí)酒 為了...
    葡萄周末閱讀 5,320評(píng)論 18 30
  • 這城市聽得見的聲音 來自偶爾路過的花斑雀 和散步的波斯貓 匆匆而過的汽車不會(huì)呼喊 只在每個(gè)紅綠燈處 發(fā)出刺耳的呻吟...
    王二痞子閱讀 660評(píng)論 4 24