You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

321 lines
12 KiB

5 years ago
package xyz.wbsite.dbtool.web.action;
5 years ago
import com.fasterxml.jackson.core.TreeNode;
5 years ago
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
5 years ago
import org.springframework.beans.factory.annotation.Value;
5 years ago
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
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;
5 years ago
import xyz.wbsite.dbtool.web.config.ActionConfig;
import xyz.wbsite.dbtool.web.frame.auth.LocalData;
5 years ago
import xyz.wbsite.dbtool.web.frame.base.*;
5 years ago
import xyz.wbsite.dbtool.web.frame.utils.MapperUtil;
5 years ago
5 years ago
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
5 years ago
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
5 years ago
import java.lang.reflect.Parameter;
5 years ago
import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* ControllerController
* htm{@link GlobalController#action(Model, HttpServletRequest, HttpServletResponse)}
5 years ago
* ajax{@link GlobalController#ajax(String, String, String, HttpServletRequest, HttpServletResponse, String, MultipartFile)}
5 years ago
* {@link GlobalController#exceptionHandler(HttpServletRequest, HttpServletResponse, Model, Exception)}
* {@link GlobalController#sse(String)}
* <p>
* Request
* Api#Example#Request ==> ##Request
*
* @author author
* @version 0.0.1
* @since 2019-06-16
*/
@Controller
@ControllerAdvice
public class GlobalController implements ErrorController {
@Value("${web.welcome.page}")
private String homePage;
@Value("${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("<a>").append(message).append("</a><br>");
for (int i = 0; i < length; i++) {
msg.append("<a>").append(exception.getStackTrace()[i]).append("</a><br>");
}
} 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, HttpServletResponse response) {
switch (response.getStatus()) {
case 404:
return "404";
case 403:
try {
response.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;
}
}
/**
* layoutscreen
* 使layoutViewNameTranslator
*
* @param model
* @param request
*/
@RequestMapping({"/**/*.htm"})
public String action(Model model, HttpServletRequest request, HttpServletResponse response) {
String servletPath = request.getServletPath();// /**/*.htm
String layout = "/layout/default";
String action = LocalData.getAction();// **/*
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(HttpServletResponse.SC_NOT_FOUND);
return error(request, response);
}
// 尝试执行Screen执行器(服务器渲染),并返回视图模板
try {
String beanClassName = (ActionConfig.SCREEN_PREFIX + action).toLowerCase();
Screen screenExec = LocalData.getApplicationContext().getBean(beanClassName, Screen.class);
screenExec.exec(model, request, response);
if (response.getStatus() != HttpServletResponse.SC_OK) {
return error(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("/ajax/{module}/{target}/{method}")
@ResponseBody
5 years ago
public Object ajax(
@PathVariable String module,
@PathVariable String target,
@PathVariable String method,
HttpServletRequest request,
HttpServletResponse response,
@RequestBody(required = false) String data,
@RequestParam(name = "file", required = false) MultipartFile file) {
5 years ago
try {
String beanClassName = (ActionConfig.AJAX_PREFIX + module + "/" + target).toLowerCase();
Object ajax = LocalData.getApplicationContext().getBean(beanClassName);
Class ajaxClass = ajax.getClass();
5 years ago
Method[] methods = ajaxClass.getDeclaredMethods();
Method methodC = null;
for (Method meth : methods) {
if (meth.getName().equals(method)) {
methodC = meth;
}
5 years ago
}
5 years ago
if (methodC == null) {
BaseResponse baseResponse = new BaseResponse();
baseResponse.addError(ErrorType.BUSINESS_ERROR, "未找到对应的方法!");
return baseResponse;
}
Parameter[] parameters = methodC.getParameters();
Object[] arg = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
Parameter parameter = parameters[i];
if (parameter.getType() == HttpServletRequest.class) {
arg[i] = request;
} else if (parameter.getType() == HttpServletResponse.class) {
arg[i] = response;
} else if (parameter.getType() == TreeNode.class) {
arg[i] = MapperUtil.toTree(data);
} else if (parameter.getType() == String.class) {
arg[i] = data;
} else if (parameter.getType() == MultipartFile.class) {
arg[i] = file;
5 years ago
} else if (BaseRequest.class.isAssignableFrom(parameter.getType())) {
arg[i] = MapperUtil.toJava(data, parameter.getType());
5 years ago
}
}
return methodC.invoke(ajax, arg);
5 years ago
} catch (BeansException e) {
5 years ago
e.printStackTrace();
BaseResponse baseResponse = new BaseResponse();
5 years ago
baseResponse.addError(ErrorType.BUSINESS_ERROR, "未找到对应的目标!");
5 years ago
return baseResponse;
5 years ago
} catch (IllegalAccessException e) {
5 years ago
e.printStackTrace();
BaseResponse baseResponse = new BaseResponse();
5 years ago
baseResponse.addError(ErrorType.BUSINESS_ERROR, "方法执必须公开!");
5 years ago
return baseResponse;
5 years ago
} catch (InvocationTargetException e) {
5 years ago
e.getTargetException().printStackTrace();
BaseResponse baseResponse = new BaseResponse();
baseResponse.addError(ErrorType.BUSINESS_ERROR, "方法执行错误[" + e.getTargetException().getMessage() + "]");
return baseResponse;
5 years ago
}
}
private static ConcurrentHashMap<String, SseEmitter> sseMap = new ConcurrentHashMap();
/**
* Ssejs
* 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);
}
}
}
}
5 years ago

Powered by TurnKey Linux.