From 9aaa9082928b1b6f67e3c24308229cf5548fa90f Mon Sep 17 00:00:00 2001 From: wangbing <1919101440@qq.com> Date: Wed, 23 Oct 2019 00:16:54 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../manger/callable/SpringBootCallable.java | 23 +- .../manger/callable/SpringMVCCallable.java | 4 +- ...AjaxController.ftl => AjaxController.java} | 0 ...ignController.ftl => FeignController.java} | 0 .../java/action/GlobalController.ftl | 186 - .../java/action/GlobalController.java | 339 + .../SpringBoot/java/config/ActionConfig.java | 24 + .../java/config/FreeMarkerConfig.java | 118 + .../java/config/SecurityConfig.java | 4 +- .../SpringBoot/java/config/TaskConfig.java | 10 +- .../SpringBoot/java/config/WebMvcConfig.java | 21 - .../SpringBoot/java/frame/auth/LocalData.java | 10 +- .../SpringBoot/resources/application-dev.ftl | 18 +- .../SpringBoot/resources/application-prod.ftl | 18 +- .../SpringBoot/resources/static/js/ajax.js | 44 +- .../SpringBoot/resources/templates/403.ftl | 2 +- .../resources/templates/control/header.ftl | 12 +- .../resources/templates/layout/app.ftl | 14 +- .../resources/templates/layout/default.ftl | 20 +- .../resources/templates/layout/index.ftl | 11 +- .../resources/templates/screen/home.ftl | 2 +- .../resources/templates/screen/login.ftl | 15 +- src/main/resources/templates/403.ftl | 249 - src/main/resources/templates/404.ftl | 78 - src/main/resources/templates/500.ftl | 80 - .../resources/templates/control/footer.ftl | 5 - .../resources/templates/control/header.ftl | 50 - .../resources/templates/control/macro.ftl | 6 - .../resources/templates/layout/default.ftl | 19 - src/main/resources/templates/layout/wap.ftl | 44 - src/main/resources/templates/screen/index.ftl | 6578 ----------------- 31 files changed, 596 insertions(+), 7408 deletions(-) rename src/main/resources/modules/SpringBoot/java/action/{AjaxController.ftl => AjaxController.java} (100%) rename src/main/resources/modules/SpringBoot/java/action/{FeignController.ftl => FeignController.java} (100%) delete mode 100644 src/main/resources/modules/SpringBoot/java/action/GlobalController.ftl create mode 100644 src/main/resources/modules/SpringBoot/java/action/GlobalController.java create mode 100644 src/main/resources/modules/SpringBoot/java/config/FreeMarkerConfig.java delete mode 100644 src/main/resources/templates/403.ftl delete mode 100644 src/main/resources/templates/404.ftl delete mode 100644 src/main/resources/templates/500.ftl delete mode 100644 src/main/resources/templates/control/footer.ftl delete mode 100644 src/main/resources/templates/control/header.ftl delete mode 100644 src/main/resources/templates/control/macro.ftl delete mode 100644 src/main/resources/templates/layout/default.ftl delete mode 100644 src/main/resources/templates/layout/wap.ftl delete mode 100644 src/main/resources/templates/screen/index.ftl diff --git a/src/main/java/xyz/wbsite/dbtool/javafx/manger/callable/SpringBootCallable.java b/src/main/java/xyz/wbsite/dbtool/javafx/manger/callable/SpringBootCallable.java index 9960a94a..db048745 100644 --- a/src/main/java/xyz/wbsite/dbtool/javafx/manger/callable/SpringBootCallable.java +++ b/src/main/java/xyz/wbsite/dbtool/javafx/manger/callable/SpringBootCallable.java @@ -211,16 +211,24 @@ public class SpringBootCallable implements Callable { File control = new File(root.getAbsolutePath(), "control"); control.mkdirs(); + File ajax = new File(root.getAbsolutePath(), "ajax"); + ajax.mkdirs(); + File auth = new File(root.getAbsolutePath(), "auth"); + auth.mkdirs(); + File screen = new File(root.getAbsolutePath(), "screen"); + screen.mkdirs(); + freeMarkerManager.outputTemp(new File(control.getAbsolutePath(), "Footer.java"), option + "/java/action/control/Footer.java", ctx); freeMarkerManager.outputTemp(new File(control.getAbsolutePath(), "Header.java"), option + "/java/action/control/Header.java", ctx); - File screen = new File(root.getAbsolutePath(), "screen"); - screen.mkdirs(); + freeMarkerManager.outputTemp(new File(ajax.getAbsolutePath(), "AuthAjax.java"), option + "/java/action/ajax/system/AuthAjax.java", ctx); + + freeMarkerManager.outputTemp(new File(screen.getAbsolutePath(), "Index.java"), option + "/java/action/screen/Index.java", ctx); - freeMarkerManager.outputTemp(new File(root.getAbsolutePath(), "GlobalController.java"), option + "/java/action/GlobalController.ftl", ctx); + freeMarkerManager.outputTemp(new File(root.getAbsolutePath(), "GlobalController.java"), option + "/java/action/GlobalController.java", ctx); - freeMarkerManager.outputTemp(new File(root.getAbsolutePath(), "AjaxController.java"), option + "/java/action/AjaxController.ftl", ctx); +// freeMarkerManager.outputTemp(new File(root.getAbsolutePath(), "AjaxController.java"), option + "/java/action/AjaxController.java", ctx); } public void generateConfig(File root, Project project, DataBase dataBase, String option) { @@ -236,6 +244,7 @@ public class SpringBootCallable implements Callable { //config freeMarkerManager.outputTemp(new File(root.getAbsolutePath(), "ActionConfig.java"), option + "/java/config/ActionConfig.java", ctx); + freeMarkerManager.outputTemp(new File(root.getAbsolutePath(), "FreeMarkerConfig.java"), option + "/java/config/FreeMarkerConfig.java", ctx); freeMarkerManager.outputTemp(new File(root.getAbsolutePath(), "SecurityConfig.java"), option + "/java/config/SecurityConfig.java", ctx); freeMarkerManager.outputTemp(new File(root.getAbsolutePath(), "TaskConfig.java"), option + "/java/config/TaskConfig.java", ctx); freeMarkerManager.outputTemp(new File(root.getAbsolutePath(), "ThreadPoolConfig.java"), option + "/java/config/ThreadPoolConfig.java", ctx); @@ -495,9 +504,9 @@ public class SpringBootCallable implements Callable { freeMarkerManager.outputTemp(new File(base.getAbsolutePath(), "Token.java"), option + "/java/frame/base/Token.java", ctx); //freemarker - freeMarkerManager.outputTemp(new File(freemarker.getAbsolutePath(), "ViewNameTranslator.java"), option + "/java/frame/freemarker/ViewNameTranslator.java", ctx); - freeMarkerManager.outputTemp(new File(freemarker.getAbsolutePath(), "Layout.java"), option + "/java/frame/freemarker/Layout.java", ctx); - freeMarkerManager.outputTemp(new File(freemarker.getAbsolutePath(), "Uri.java"), option + "/java/frame/freemarker/Uri.java", ctx); +// freeMarkerManager.outputTemp(new File(freemarker.getAbsolutePath(), "ViewNameTranslator.java"), option + "/java/frame/freemarker/ViewNameTranslator.java", ctx); +// freeMarkerManager.outputTemp(new File(freemarker.getAbsolutePath(), "Layout.java"), option + "/java/frame/freemarker/Layout.java", ctx); +// freeMarkerManager.outputTemp(new File(freemarker.getAbsolutePath(), "Uri.java"), option + "/java/frame/freemarker/Uri.java", ctx); //uitls freeMarkerManager.outputTemp(new File(utils.getAbsolutePath(), "Base64Util.java"), option + "/java/frame/utils/Base64Util.java", ctx); diff --git a/src/main/java/xyz/wbsite/dbtool/javafx/manger/callable/SpringMVCCallable.java b/src/main/java/xyz/wbsite/dbtool/javafx/manger/callable/SpringMVCCallable.java index 48887253..b2cc3362 100644 --- a/src/main/java/xyz/wbsite/dbtool/javafx/manger/callable/SpringMVCCallable.java +++ b/src/main/java/xyz/wbsite/dbtool/javafx/manger/callable/SpringMVCCallable.java @@ -480,8 +480,8 @@ public class SpringMVCCallable implements Callable { ctx.put("author", project.getProjectAuthor()); ctx.put("date", new Date()); - freeMarkerManager.outputTemp(new File(root.getAbsolutePath() + File.separator + "AjaxController.java"), option + "/java/controller/AjaxController.ftl", ctx); - freeMarkerManager.outputTemp(new File(root.getAbsolutePath() + File.separator + "GlobalController.java"), option + "/java/controller/GlobalController.ftl", ctx); + freeMarkerManager.outputTemp(new File(root.getAbsolutePath() + File.separator + "AjaxController.java"), option + "/java/controller/AjaxController.java", ctx); + freeMarkerManager.outputTemp(new File(root.getAbsolutePath() + File.separator + "GlobalController.java"), option + "/java/controller/GlobalController.java", ctx); } catch (Exception e) { e.printStackTrace(); diff --git a/src/main/resources/modules/SpringBoot/java/action/AjaxController.ftl b/src/main/resources/modules/SpringBoot/java/action/AjaxController.java similarity index 100% rename from src/main/resources/modules/SpringBoot/java/action/AjaxController.ftl rename to src/main/resources/modules/SpringBoot/java/action/AjaxController.java diff --git a/src/main/resources/modules/SpringBoot/java/action/FeignController.ftl b/src/main/resources/modules/SpringBoot/java/action/FeignController.java similarity index 100% rename from src/main/resources/modules/SpringBoot/java/action/FeignController.ftl rename to src/main/resources/modules/SpringBoot/java/action/FeignController.java diff --git a/src/main/resources/modules/SpringBoot/java/action/GlobalController.ftl b/src/main/resources/modules/SpringBoot/java/action/GlobalController.ftl deleted file mode 100644 index 491f7077..00000000 --- a/src/main/resources/modules/SpringBoot/java/action/GlobalController.ftl +++ /dev/null @@ -1,186 +0,0 @@ -package ${basePackage}.action; - -import ${basePackage}.frame.base.FileUploadResponse; -import ${basePackage}.frame.base.BaseResponse; -import ${basePackage}.frame.base.ErrorType; -import ${basePackage}.frame.base.Screen; -import ${basePackage}.frame.auth.LocalData; -import ${basePackage}.config.ActionConfig; -import org.springframework.beans.BeansException; -import org.apache.commons.io.FileUtils; -import org.springframework.boot.web.servlet.error.ErrorController; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.*; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; -import org.springframework.web.multipart.MultipartFile; -import org.springframework.web.multipart.MultipartHttpServletRequest; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.File; -import java.io.IOException; -import org.springframework.beans.factory.annotation.Value; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * 全局请求Controller,如果无特殊请求,则不需再增加其他Controller - * 全局htm后缀入口{@link GlobalController#hold} - * 全局异常捕捉{@link GlobalController#excepitonHandler} - * 全局上传接口{@link GlobalController#upload} - * 全局下载接口{@link GlobalController#download} - *

- * 说明Request命名规则,驼峰式命名 - * Api#Example#Request ==> 目标#动作#Request - * - * @author author - * @version 0.0.1 - * @since 2019-06-16 - */ -@Controller -@ControllerAdvice -public class GlobalController implements ErrorController { - - @Value("${r'${web.welcome.page}'}") - private String homePage; - - /** - * 全局异常捕捉 - * - * @param request - * @param response - * @param exception 要捕获的异常 - * @return - */ - @ExceptionHandler(Exception.class) - public String excepitonHandler(HttpServletRequest request, HttpServletResponse response, Model model, Exception exception) { - StringBuffer msg = new StringBuffer(""); - if (exception != null) { - msg = new StringBuffer(""); - String message = exception.toString(); - int length = exception.getStackTrace().length; - if (length > 0) { - msg.append("").append(message).append("
"); - for (int i = 0; i < length; i++) { - msg.append("").append(exception.getStackTrace()[i]).append("
"); - } - } else { - msg.append(message); - } - } - response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - model.addAttribute("msg", msg.toString()); - return "500"; - } - - private final static String ERROR_PATH = "/error"; - - @Override - public String getErrorPath() { - return ERROR_PATH; - } - - @RequestMapping(value = ERROR_PATH) - public String error(HttpServletRequest request) { - Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code"); - - switch (statusCode) { - case 404: - return "404"; - case 403: - try { - LocalData.getResponse().sendRedirect("/login.htm"); - } catch (IOException e) { - e.printStackTrace(); - } - return "403"; - case 500: - return "500"; - default: - return "403"; - } - } - - @RequestMapping("/") - public String home() { - return "forward:" + homePage; - } - - /** - * 当未明确指定控制器时,走该请求,默认返回对应的layout布局和screen视图 - * 当需要使用layout时,不需要返回值,ViewNameTranslator会处理对应关系 - * @param model - * @param request - */ - @RequestMapping({"/**/*.htm"}) - public void hold(HttpServletRequest request, Model model) { - HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse(); - - // 尝试执行Target Screen执行器(服务器渲染),不存在则直接返回视图模板(Ajax渲染) - Screen screenExec = null; - try { - String target = LocalData.getTarget(); - target = target.replaceAll("/", ".").toLowerCase(); - screenExec = LocalData.getApplicationContext().getBean(ActionConfig.SCREEN_PREFIX + target, Screen.class); - screenExec.exec(model, request, response); - } catch (BeansException e) { - - } - - //todo 可在此获取共性数据(也可以在全局拦截器GlobalHandlerInterceptor、拦截器作用域比此更高), - //todo 例如用户信息等。其他业务数据在页面渲染后通过Ajax请求 - } - - @RequestMapping("/upload") - @ResponseBody - public BaseResponse upload(HttpServletRequest request) { - FileUploadResponse fileUploadResponse = new FileUploadResponse(); - MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request; - MultipartFile target = multipartHttpServletRequest.getFile("file"); - - String fileName = target.getOriginalFilename(); - - //======== - //处理文件 - //======== - fileUploadResponse.setId(1L); - fileUploadResponse.setUrl("example.com\\img\\1.jpg"); - fileUploadResponse.setDownloadUrl("example.com\\img\\1.jpg"); - - - if (target != null) { - fileUploadResponse.addError(ErrorType.BUSINESS_ERROR, "文件上传成功,但未处理文件[" + fileName + "]!"); - } else { - fileUploadResponse.addError(ErrorType.BUSINESS_ERROR, "文件上传失败!"); - } - - return fileUploadResponse; - } - - @RequestMapping("/download") - @ResponseBody - public ResponseEntity download(@RequestParam(value = "file", required = false) String file) throws IOException { - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); - - //======== - //下载DEMO - //======== - if (file == null) { - file = "test.txt"; - headers.setContentDispositionFormData("attachment", new String(file.getBytes("UTF-8"), "iso-8859-1")); - return new ResponseEntity("test".getBytes(), - headers, HttpStatus.CREATED); - } - - return new ResponseEntity(FileUtils.readFileToByteArray(new File(file)), - headers, HttpStatus.CREATED); - } -} diff --git a/src/main/resources/modules/SpringBoot/java/action/GlobalController.java b/src/main/resources/modules/SpringBoot/java/action/GlobalController.java new file mode 100644 index 00000000..35d5e3ae --- /dev/null +++ b/src/main/resources/modules/SpringBoot/java/action/GlobalController.java @@ -0,0 +1,339 @@ +package ${basePackage}.action; + +import ${basePackage}.frame.base.*; +import ${basePackage}.frame.auth.LocalData; +import ${basePackage}.config.ActionConfig; +import ${basePackage}.frame.utils.MapperUtil; +import org.springframework.beans.BeansException; +import org.apache.commons.io.FileUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.web.servlet.error.ErrorController; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.IOException; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.servlet.DispatcherServlet; +import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.View; +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; +import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Locale; +import java.util.concurrent.ConcurrentHashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 全局请求Controller,如果无特殊请求,则不需再增加其他Controller + * 全局htm后缀入口{@link GlobalController#action(HttpServletRequest, Model)} + * 全局异常捕捉{@link GlobalController#exceptionHandler(HttpServletRequest, HttpServletResponse, Model, Exception)} + * 全局上传接口{@link GlobalController#upload(HttpServletRequest)} + * 全局下载接口{@link GlobalController#download(String)} + * 全局消息订阅{@link GlobalController#sse(String)} + *

+ * 说明Request命名规则,驼峰式命名 + * Api#Example#Request ==> 目标#动作#Request + * + * @author author + * @version 0.0.1 + * @since 2019-06-16 + */ +@Controller +@ControllerAdvice +public class GlobalController implements ErrorController { + + @Value("${r'${web.welcome.page}'}") + private String homePage; + @Value("${r'${web.login.page}'}") + private String loginPage; + @Autowired + private FreeMarkerViewResolver viewResolver; + + /** + * 全局异常捕捉 + * + * @param request + * @param response + * @param exception 要捕获的异常 + * @return + */ + @ExceptionHandler(Exception.class) + public String exceptionHandler(HttpServletRequest request, HttpServletResponse response, Model model, Exception exception) { + StringBuffer msg = new StringBuffer(""); + if (exception != null) { + msg = new StringBuffer(""); + String message = exception.toString(); + int length = exception.getStackTrace().length; + if (length > 0) { + msg.append("").append(message).append("
"); + for (int i = 0; i < length; i++) { + msg.append("").append(exception.getStackTrace()[i]).append("
"); + } + } else { + msg.append(message); + } + } + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + model.addAttribute("msg", msg.toString()); + return "500"; + } + + private final static String ERROR_PATH = "/error"; + + @Override + public String getErrorPath() { + return ERROR_PATH; + } + + @RequestMapping(value = ERROR_PATH) + public String error(HttpServletRequest request) { + Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code"); + + switch (statusCode) { + case 404: + return "404"; + case 403: + try { + LocalData.getResponse().sendRedirect("/login.htm"); + } catch (IOException e) { + e.printStackTrace(); + } + return "403"; + case 500: + return "500"; + default: + return "403"; + } + } + + @RequestMapping("/") + public String home() { + Token token = LocalData.getToken(); + if (token == null) { + return "redirect:" + loginPage; + } else { + return "redirect:" + homePage; + } + } + + /** + * 当未明确指定控制器时,走该请求,默认返回对应的layout布局和screen视图 + * 当需要使用layout时,不需要返回值,ViewNameTranslator会处理对应关系 + * + * @param model + * @param request + */ + @RequestMapping({"/**/*.htm"}) + public String action(HttpServletRequest request, Model model) { + HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse(); + + String servletPath = request.getServletPath();// /**/*.htm + String layout = "/layout/default"; + String action = "";// **/* + + Pattern compile = Pattern.compile("^/(.+)\\.htm"); + Matcher matcher = compile.matcher(servletPath); + if (matcher.find()) { + action = matcher.group(1); + LocalData.setAction(action); + } + + try { + LocaleResolver localeResolver = (LocaleResolver) request.getAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE); + Locale locale = localeResolver.resolveLocale(request); + + {//查询screen + String[] split = action.split("/"); + StringBuilder sb = new StringBuilder(""); + sb.append("screen"); + for (int i = 0; i < split.length; i++) { + sb.append(File.separator); + sb.append(split[i]); + } + layout = sb.toString(); + View view = viewResolver.resolveViewName(layout, locale); + if (view == null) { + response.setStatus(HttpStatus.NOT_FOUND.value()); + return null; + } + + // 尝试执行Screen执行器(服务器渲染),并返回视图模板 + try { + Screen screenExec = LocalData.getApplicationContext().getBean(ActionConfig.SCREEN_PREFIX + action, Screen.class); + screenExec.exec(model, request, response); + } catch (BeansException e) { + + } + } + + {//查找layout + String[] split = action.split("/"); + + int lt = split.length; + while (lt > 0) { + + StringBuilder sb = new StringBuilder(""); + sb.append("layout"); + for (int i = 0; i < lt - 1; i++) { + sb.append(File.separator); + sb.append(split[i]); + } + + layout = sb.toString() + File.separator + split[split.length - 1]; + + View view = viewResolver.resolveViewName(layout, locale); + //无法找到对应layout,使用默认layout + if (view == null) { + layout = sb.toString() + File.separator + "default"; + View defaultView = viewResolver.resolveViewName(layout, locale); + if (null == defaultView && lt == 1) { + System.err.println("can not find layout/default.ftl"); + } else if (null == defaultView) { + lt--; + } else { + break; + } + } else { + break; + } + } + } + } catch (Exception e) { + return exceptionHandler(request, response, model, e); + } + + //todo 可在此获取共性数据(也可以在全局拦截器GlobalHandlerInterceptor、拦截器作用域比此更高), + //todo 例如用户信息等。其他业务数据在页面渲染后通过Ajax请求 + return layout; + } + + @RequestMapping("/upload") + @ResponseBody + public BaseResponse upload(HttpServletRequest request) { + FileUploadResponse fileUploadResponse = new FileUploadResponse(); + MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request; + MultipartFile target = multipartHttpServletRequest.getFile("file"); + + String fileName = target.getOriginalFilename(); + + //======== + //处理文件 + //======== + fileUploadResponse.setId(1L); + fileUploadResponse.setUrl("example.com\\img\\1.jpg"); + fileUploadResponse.setDownloadUrl("example.com\\img\\1.jpg"); + + + if (target != null) { + fileUploadResponse.addError(ErrorType.BUSINESS_ERROR, "文件上传成功,但未处理文件[" + fileName + "]!"); + } else { + fileUploadResponse.addError(ErrorType.BUSINESS_ERROR, "文件上传失败!"); + } + + return fileUploadResponse; + } + + + @RequestMapping("/ajax/{module}/{target}/{method}") + @ResponseBody + public BaseResponse ajax(@PathVariable String module, @PathVariable String target, @PathVariable String method, @RequestBody String param) { + BaseResponse baseResponse = null; + + try { + Object ajax = LocalData.getApplicationContext().getBean(ActionConfig.AJAX_PREFIX + "." + module + "." + target); + + Class ajaxClass = ajax.getClass(); + Method methodC = ajaxClass.getMethod(method, String.class); + Object invoke = methodC.invoke(ajax, param); + if (invoke instanceof BaseResponse) { + baseResponse = (BaseResponse) invoke; + } else { + baseResponse = new BaseResponse(); + baseResponse.addError(ErrorType.BUSINESS_ERROR, "方法返回值错误!"); + } + } catch (BeansException e) { + baseResponse = new BaseResponse(); + baseResponse.addError(ErrorType.BUSINESS_ERROR, "未找到对应的目标!"); + } catch (NoSuchMethodException e) { + baseResponse = new BaseResponse(); + baseResponse.addError(ErrorType.BUSINESS_ERROR, "未找到对应的方法!"); + } catch (IllegalAccessException e) { + baseResponse = new BaseResponse(); + baseResponse.addError(ErrorType.BUSINESS_ERROR, "方法执必须公开!"); + } catch (InvocationTargetException e) { + baseResponse = new BaseResponse(); + baseResponse.addError(ErrorType.BUSINESS_ERROR, "方法执行错误!"); + } + return baseResponse; + } + + @RequestMapping("/download") + @ResponseBody + public ResponseEntity download(@RequestParam(value = "file", required = false) String file) throws IOException { + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); + + //======== + //下载DEMO + //======== + if (file == null) { + file = "test.txt"; + headers.setContentDispositionFormData("attachment", new String(file.getBytes("UTF-8"), "iso-8859-1")); + return new ResponseEntity("test".getBytes(), + headers, HttpStatus.CREATED); + } + + return new ResponseEntity(FileUtils.readFileToByteArray(new File(file)), + headers, HttpStatus.CREATED); + } + + + private static ConcurrentHashMap sseMap = new ConcurrentHashMap(); + + /** + * Sse推送服务,服务器向js推送自定义消息 + * Sse容器{@link GlobalController#sseMap} + * Sse批量推送{@link GlobalController#pushAll} + */ + @RequestMapping(value = "/sse/{userId}", produces = "text/event-stream;charset=UTF-8") + public SseEmitter sse(@PathVariable String userId) { + SseEmitter sseEmitter = new SseEmitter(10000000L); + if (sseMap.get(userId) != null) { + sseMap.remove(userId); + } + sseMap.put(userId, sseEmitter); + return sseEmitter; + } + + /** + * Sse批量推送 + * + * @param data 推送对象 + */ + public static void pushAll(Object data) { + for (String s : sseMap.keySet()) { + try { + sseMap.get(s).send(MapperUtil.toJson(data), MediaType.APPLICATION_JSON); + } catch (IOException e) { + sseMap.remove(s); + } + } + } +} diff --git a/src/main/resources/modules/SpringBoot/java/config/ActionConfig.java b/src/main/resources/modules/SpringBoot/java/config/ActionConfig.java index a96c4041..0f5d78f3 100644 --- a/src/main/resources/modules/SpringBoot/java/config/ActionConfig.java +++ b/src/main/resources/modules/SpringBoot/java/config/ActionConfig.java @@ -30,12 +30,14 @@ import java.io.IOException; public class ActionConfig implements BeanDefinitionRegistryPostProcessor { public static final String SCREEN_PREFIX = "screen"; public static final String CONTROL_PREFIX = "control"; + public static final String AJAX_PREFIX = "ajax"; @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException { String aPackage = this.getClass().getPackage().getName(); int i = registryScreen("${basePackage}.action.screen", beanDefinitionRegistry); int i1 = registryControl("${basePackage}.action.control", beanDefinitionRegistry); + int i2 = registryAjax("${basePackage}.action.ajax", beanDefinitionRegistry); System.out.println(); } @@ -87,4 +89,26 @@ public class ActionConfig implements BeanDefinitionRegistryPostProcessor { }); return classPathBeanDefinitionScanner.scan(basePackage); } + + private int registryAjax(String basePackage, BeanDefinitionRegistry beanDefinitionRegistry) { + ClassPathBeanDefinitionScanner classPathBeanDefinitionScanner = new ClassPathBeanDefinitionScanner(beanDefinitionRegistry); + classPathBeanDefinitionScanner.addIncludeFilter(new TypeFilter() { + @Override + public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { + return true; + } + }); + classPathBeanDefinitionScanner.setBeanNameGenerator(new BeanNameGenerator() { + @Override + public String generateBeanName(BeanDefinition beanDefinition, BeanDefinitionRegistry beanDefinitionRegistry) { + String beanClassName = beanDefinition.getBeanClassName(); + if (beanClassName != null && beanClassName.endsWith("Ajax")) { + beanClassName = beanClassName.substring(0, beanClassName.length() - 4); + } + String s = beanClassName.replaceAll(basePackage, AJAX_PREFIX); + return s.toLowerCase(); + } + }); + return classPathBeanDefinitionScanner.scan(basePackage); + } } diff --git a/src/main/resources/modules/SpringBoot/java/config/FreeMarkerConfig.java b/src/main/resources/modules/SpringBoot/java/config/FreeMarkerConfig.java new file mode 100644 index 00000000..14569e39 --- /dev/null +++ b/src/main/resources/modules/SpringBoot/java/config/FreeMarkerConfig.java @@ -0,0 +1,118 @@ +package ${basePackage}.config; + +import ${basePackage}.frame.auth.LocalData; +import ${basePackage}.frame.base.Control; +import freemarker.template.SimpleScalar; +import freemarker.template.TemplateMethodModelEx; +import freemarker.template.TemplateModelException; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.validation.support.BindingAwareModelMap; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.web.servlet.DispatcherServlet; +import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.View; +import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver; + +import javax.annotation.PostConstruct; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.util.List; +import java.util.Locale; + +@Configuration +public class FreeMarkerConfig { + @Autowired + private FreeMarkerViewResolver viewResolver; + @Autowired + private freemarker.template.Configuration configuration; + @Value("${r'${server.servlet.context-path}'}") + private String context; + private String screenPrefix = "/screen/"; + private String controlPrefix = "/control/"; + private String suffix = ".ftl"; + + @PostConstruct + public void setSharedVariable() throws TemplateModelException { + configuration.setSharedVariable("context", context); + configuration.setSharedVariable("screenHolder", new ScreenHolder()); + configuration.setSharedVariable("controlHolder", new ControlHolder()); + } + + private class ScreenHolder implements TemplateMethodModelEx { + + @Override + public Object exec(List list) throws TemplateModelException { + try { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + LocaleResolver localeResolver = (LocaleResolver) request.getAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE); + String servletPath = LocalData.getAction(); + servletPath = servletPath.replaceAll("^/", ""); + + String[] split = servletPath.split("/"); + StringBuilder sb = new StringBuilder(""); + + // 分割组装路径 + for (int i = 0; i < split.length; i++) { + sb.append(split[i]); + if (i != split.length - 1) { + sb.append(File.separator); + } + } + + Locale locale = localeResolver.resolveLocale(request); + String viewName = "screen" + File.separator + sb.toString(); + View view = viewResolver.resolveViewName(viewName, locale); + //无法找到对应screen + if (view == null) { + return ""; + } else { + return screenPrefix + servletPath + suffix; + } + } catch (Exception e) { + e.printStackTrace(); + } + return ""; + } + } + + private class ControlHolder implements TemplateMethodModelEx { + + @Override + public Object exec(List list) throws TemplateModelException { + String control = ""; + if (list.size() != 1) { + return ""; + } + Object o = list.get(0); + if (o instanceof SimpleScalar) { + control = ((SimpleScalar) o).getAsString(); + } + + // 查找是否存在对应控制面板执行器 + Control controlExec = null; + try { + controlExec = LocalData.getApplicationContext().getBean(ActionConfig.CONTROL_PREFIX + "." + control, Control.class); + + HttpServletRequest request = LocalData.getRequest(); + HttpServletResponse response = LocalData.getResponse(); + + BindingAwareModelMap modelMap = new BindingAwareModelMap(); + controlExec.exec(modelMap, request, response); + + for (String key : modelMap.keySet()) { + request.setAttribute(key, modelMap.get(key)); + } + } catch (BeansException e) { + + } + + control = control.replaceAll("/", File.separator); + return controlPrefix + control + suffix; + } + } +} diff --git a/src/main/resources/modules/SpringBoot/java/config/SecurityConfig.java b/src/main/resources/modules/SpringBoot/java/config/SecurityConfig.java index 7ae03bba..4cfce623 100644 --- a/src/main/resources/modules/SpringBoot/java/config/SecurityConfig.java +++ b/src/main/resources/modules/SpringBoot/java/config/SecurityConfig.java @@ -18,6 +18,8 @@ import javax.servlet.http.HttpServletRequest; @EnableGlobalMethodSecurity(securedEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { + @Value("${r"${web.url.auth.included}"}") + private String[] included; @Value("${r"${web.url.auth.excluded}"}") private String[] excluded; @Value("${r"${spring.mvc.static-path-pattern}"}") @@ -29,7 +31,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { .authorizeRequests() .antMatchers(staticPath).permitAll() .antMatchers(excluded).permitAll() - .anyRequest().access("@Authorization.hasPermission(request,authentication)") + .antMatchers(included).access("@Authorization.hasPermission(request,authentication)") .and().cors() .and().headers().frameOptions().disable() .and().csrf().disable(); diff --git a/src/main/resources/modules/SpringBoot/java/config/TaskConfig.java b/src/main/resources/modules/SpringBoot/java/config/TaskConfig.java index dd90bf82..279fe621 100644 --- a/src/main/resources/modules/SpringBoot/java/config/TaskConfig.java +++ b/src/main/resources/modules/SpringBoot/java/config/TaskConfig.java @@ -1,5 +1,6 @@ package ${basePackage}.config; +import ${basePackage}.action.GlobalController; import ${basePackage}.frame.utils.LogUtil; import ${basePackage}.frame.utils.ProcessUtil; import org.springframework.context.annotation.Configuration; @@ -8,7 +9,9 @@ import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.SchedulingConfigurer; import org.springframework.scheduling.config.ScheduledTaskRegistrar; - +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; import java.util.concurrent.Executors; /** @@ -22,7 +25,10 @@ public class TaskConfig implements SchedulingConfigurer { @Scheduled(cron="0/30 * * * * ? ") public void task(){ - LogUtil.i("--------------------Task--------------------"); + SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss"); + HashMap data = new HashMap<>(); + data.put("time", format.format(new Date())); + GlobalController.pushAll(data); } /** diff --git a/src/main/resources/modules/SpringBoot/java/config/WebMvcConfig.java b/src/main/resources/modules/SpringBoot/java/config/WebMvcConfig.java index 317f59b1..af92d99c 100644 --- a/src/main/resources/modules/SpringBoot/java/config/WebMvcConfig.java +++ b/src/main/resources/modules/SpringBoot/java/config/WebMvcConfig.java @@ -37,20 +37,6 @@ public class WebMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new HandlerInterceptorAdapter() { - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - // 处理根Url - String servletPath = request.getServletPath(); - if (servletPath.matches("(.+)\\.htm")) { - Pattern compile = Pattern.compile("(.+)\\.htm"); - Matcher matcher = compile.matcher(servletPath); - if (matcher.find()) { - servletPath = matcher.group(1); - } - } - LocalData.setTarget(servletPath); - return super.preHandle(request, response, handler); - } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { @@ -64,13 +50,6 @@ public class WebMvcConfig implements WebMvcConfigurer { //获取当前用户信息 Token token = LocalData.getToken(); modelAndView.addObject("token", token); - - //主页 - modelAndView.addObject("homePath", homePage); - - //获取项目路径,在项目非根路径下用于拼接URL - String contextPath = request.getContextPath(); - modelAndView.addObject("contextPath", contextPath); } @Override diff --git a/src/main/resources/modules/SpringBoot/java/frame/auth/LocalData.java b/src/main/resources/modules/SpringBoot/java/frame/auth/LocalData.java index 54e11e21..274005db 100644 --- a/src/main/resources/modules/SpringBoot/java/frame/auth/LocalData.java +++ b/src/main/resources/modules/SpringBoot/java/frame/auth/LocalData.java @@ -47,14 +47,14 @@ public class LocalData { /** * 当请求目标 target = '/aa/bb' */ - private static final ThreadLocal targetHolder = new ThreadLocal(); + private static final ThreadLocal actionHolder = new ThreadLocal(); - public static String getTarget() { - return targetHolder.get(); + public static String getAction() { + return actionHolder.get(); } - public static void setTarget(String target) { - targetHolder.set(target); + public static void setAction(String action) { + actionHolder.set(action); } /** diff --git a/src/main/resources/modules/SpringBoot/resources/application-dev.ftl b/src/main/resources/modules/SpringBoot/resources/application-dev.ftl index 5b28c42e..c280cefa 100644 --- a/src/main/resources/modules/SpringBoot/resources/application-dev.ftl +++ b/src/main/resources/modules/SpringBoot/resources/application-dev.ftl @@ -1,6 +1,6 @@ # 开发环境 server.port=8080 -server.servlet.context-path=/ +server.servlet.context-path= spring.mvc.static-path-pattern=/static/** spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:/file-upload spring.application.name=${projectName?default("SpringBoot")} @@ -14,10 +14,6 @@ spring.http.encoding.force=true spring.http.encoding.charset=UTF-8 spring.http.encoding.enabled=true server.tomcat.uri-encoding=UTF-8 -# 根路径、欢迎页 -web.welcome.page=/index.htm -# 不需要验证授权, 或该请求有自己的验证机制 -web.url.auth.excluded=/api,/,/index.htm,/home.htm,/login.htm # 日志配置 logging.path=D:// logging.levels=DEBUG @@ -70,4 +66,14 @@ spring.freemarker.settings.url_escaping_charset=utf-8 # 文件上传配置 spring.servlet.multipart.resolveLazily=false spring.servlet.multipart.max-file-size=100MB -spring.servlet.multipart.max-request-size=100MB \ No newline at end of file +spring.servlet.multipart.max-request-size=100MB + +# 自定义配置 +# 根路径默认页,'/'跳转至该页 +web.welcome.page=/index.htm +# 登录页 +web.login.page=/login.htm +# 拦截验证 +web.url.auth.included=/,/**/*.htm +# 直接放行 +web.url.auth.excluded=/login.htm,/index.htm \ No newline at end of file diff --git a/src/main/resources/modules/SpringBoot/resources/application-prod.ftl b/src/main/resources/modules/SpringBoot/resources/application-prod.ftl index b1fadb95..e129d2aa 100644 --- a/src/main/resources/modules/SpringBoot/resources/application-prod.ftl +++ b/src/main/resources/modules/SpringBoot/resources/application-prod.ftl @@ -1,6 +1,6 @@ # 生产环境 server.port=80 -server.servlet.context-path=/ +server.servlet.context-path= spring.mvc.static-path-pattern=/static/** spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:/file-upload spring.application.name=${projectName} @@ -14,10 +14,6 @@ spring.http.encoding.force=true spring.http.encoding.charset=UTF-8 spring.http.encoding.enabled=true server.tomcat.uri-encoding=UTF-8 -# 根路径、欢迎页 -web.welcome.page=/index.htm -# 不需要验证授权, 或该请求有自己的验证机制 -web.url.auth.excluded=/favicon.ico,/static/**,/api,/login.htm # 日志配置 logging.path=/root/ logging.levels=INFO @@ -70,4 +66,14 @@ spring.freemarker.settings.url_escaping_charset=utf-8 # 文件上传配置 spring.servlet.multipart.resolveLazily=false spring.servlet.multipart.max-file-size=100MB -spring.servlet.multipart.max-request-size=100MB \ No newline at end of file +spring.servlet.multipart.max-request-size=100MB + +# 自定义配置 +# 根路径默认页,'/'跳转至该页 +web.welcome.page=/index.htm +# 登录页 +web.login.page=/login.htm +# 拦截验证 +web.url.auth.included=/,/**/*.htm +# 直接放行 +web.url.auth.excluded=/login.htm,/index.htm,/home.htm \ No newline at end of file diff --git a/src/main/resources/modules/SpringBoot/resources/static/js/ajax.js b/src/main/resources/modules/SpringBoot/resources/static/js/ajax.js index ea1f4142..f9590b2d 100644 --- a/src/main/resources/modules/SpringBoot/resources/static/js/ajax.js +++ b/src/main/resources/modules/SpringBoot/resources/static/js/ajax.js @@ -2,6 +2,8 @@ instance = axios.create({ method: 'post', timeout: 30000, + baseURL: '/ajax', + headers: {'Content-Type': 'application/json;charset=UTF-8'}, }); // 添加请求拦截器 @@ -67,23 +69,17 @@ instance.interceptors.response.use(function (response) { } return Promise.reject(rsp); }); -jsonRequest = function (config) { - return instance.request({ - params: { - method: config.method - }, - url: '${contextPath?default("")}/ajax', - headers: {'Content-Type': 'text/plain'}, - data: config.data - }).then(function (response) { - return Promise.resolve(response.data); - }, function (response) { - return Promise.resolve(response); - }) +jsonRequest = function (data) { + return instance.request(data) + .then(function (response) { + return Promise.resolve(response.data); + }, function (response) { + return Promise.resolve(response); + }) }; fileRequest = function (config) { return instance.request({ - url: '${contextPath?default("")}/upload', + url: '/upload', data: config.data, headers: {'Content-Type': 'multipart/form-data'}, onUploadProgress: function (progressEvent) { @@ -97,10 +93,10 @@ fileRequest = function (config) { }) }; window.ajax = { - example: function (data) { + authLogin: function (data) { return jsonRequest({ - method: "ajax.example.example", - data: data + url: "/system/auth/login", + data: JSON.stringify(data), }) }, fileUpload: function (file) { @@ -115,7 +111,7 @@ window.ajax = { <#if table.getCreate()> ${table.getFName()}Create: function (data) { return jsonRequest({ - method:"ajax.${db.moduleName}.${table.getLName()}.create", + url: "/${db.moduleName}/${table.getLName()}/create", data: JSON.stringify(data), }) }, @@ -123,7 +119,7 @@ window.ajax = { <#if table.getDelete()> ${table.getFName()}Delete: function (data) { return jsonRequest({ - method:"ajax.${db.moduleName}.${table.getLName()}.delete", + url: "/${db.moduleName}/${table.getLName()}/delete", data: JSON.stringify(data), }) }, @@ -131,7 +127,7 @@ window.ajax = { <#if table.getUpdate()> ${table.getFName()}Update: function (data) { return jsonRequest({ - method:"ajax.${db.moduleName}.${table.getLName()}.update", + url: "/${db.moduleName}/${table.getLName()}/update", data: JSON.stringify(data), }) }, @@ -139,7 +135,7 @@ window.ajax = { <#if table.getFind()> ${table.getFName()}Find: function (data) { return jsonRequest({ - method:"ajax.${db.moduleName}.${table.getLName()}.find", + url: "/${db.moduleName}/${table.getLName()}/find", data: JSON.stringify(data), }) }, @@ -147,7 +143,7 @@ window.ajax = { <#if table.getGet()> ${table.getFName()}Get: function(data) { return jsonRequest({ - method:"ajax.${db.moduleName}.${table.getLName()}.get", + url: "/${db.moduleName}/${table.getLName()}/get", data: JSON.stringify(data), }) }, @@ -155,7 +151,7 @@ window.ajax = { <#if table.getSearch()> ${table.getFName()}Search: function (data) { return jsonRequest({ - method:"ajax.${db.moduleName}.${table.getLName()}.search", + url: "/${db.moduleName}/${table.getLName()}/search", data: JSON.stringify(data), }) }, @@ -163,7 +159,7 @@ window.ajax = { <#if table.getGetAll()> ${table.getFName()}GetAll: function (data) { return jsonRequest({ - method:"ajax.${db.moduleName}.${table.getLName()}.get.all", + url: "/${db.moduleName}/${table.getLName()}/getAll", data: JSON.stringify(data), }) }, diff --git a/src/main/resources/modules/SpringBoot/resources/templates/403.ftl b/src/main/resources/modules/SpringBoot/resources/templates/403.ftl index 9ce0223a..a1646512 100644 --- a/src/main/resources/modules/SpringBoot/resources/templates/403.ftl +++ b/src/main/resources/modules/SpringBoot/resources/templates/403.ftl @@ -124,7 +124,7 @@

您没有足够的权限哦!
您正在试图访问一个没有事先授权的页面.或登录已失效。
5 秒后自动跳转登录页
- 立即跳转 + 立即跳转 diff --git a/src/main/resources/modules/SpringBoot/resources/templates/control/header.ftl b/src/main/resources/modules/SpringBoot/resources/templates/control/header.ftl index bf5115c3..d4b1752f 100644 --- a/src/main/resources/modules/SpringBoot/resources/templates/control/header.ftl +++ b/src/main/resources/modules/SpringBoot/resources/templates/control/header.ftl @@ -1,23 +1,23 @@