/** * Copyright © 2015-2020 JeePlus All rights reserved. */ package com.jeeplus.common.web; import java.beans.PropertyEditorSupport; import java.io.IOException; import java.util.Date; import java.util.List; import javax.servlet.http.HttpServletResponse; import javax.validation.ConstraintViolationException; import javax.validation.ValidationException; import javax.validation.Validator; import org.apache.commons.lang3.StringEscapeUtils; import org.apache.shiro.authc.AuthenticationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.ui.Model; import org.springframework.validation.BindException; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import com.jeeplus.common.beanvalidator.BeanValidators; import com.jeeplus.common.mapper.JsonMapper; import com.jeeplus.common.utils.DateUtils; /** * 控制器支持类 * @author jeeplus * @version 2013-3-23 */ public abstract class BaseController { /** * 日志对象 */ protected Logger logger = LoggerFactory.getLogger(getClass()); /** * 管理基础路径 */ @Value("${adminPath}") protected String adminPath; /** * 前端基础路径 */ @Value("${frontPath}") protected String frontPath; /** * 前端URL后缀 */ @Value("${urlSuffix}") protected String urlSuffix; /** * 验证Bean实例对象 */ @Autowired protected Validator validator; /** * 服务端参数有效性验证 * @param object 验证的实体对象 * @param groups 验证组 * @return 验证成功:返回true;严重失败:将错误信息添加到 message 中 */ protected boolean beanValidator(Model model, Object object, Class... groups) { try{ BeanValidators.validateWithException(validator, object, groups); }catch(ConstraintViolationException ex){ List list = BeanValidators.extractPropertyAndMessageAsList(ex, ": "); list.add(0, "数据验证失败:"); addMessage(model, list.toArray(new String[]{})); return false; } return true; } /** * 服务端参数有效性验证 * @param object 验证的实体对象 * @param groups 验证组 * @return 验证成功:返回true;严重失败:将错误信息添加到 flash message 中 */ protected boolean beanValidator(RedirectAttributes redirectAttributes, Object object, Class... groups) { try{ BeanValidators.validateWithException(validator, object, groups); }catch(ConstraintViolationException ex){ List list = BeanValidators.extractPropertyAndMessageAsList(ex, ": "); list.add(0, "数据验证失败:"); addMessage(redirectAttributes, list.toArray(new String[]{})); return false; } return true; } /** * 服务端参数有效性验证 * @param object 验证的实体对象 * @param groups 验证组,不传入此参数时,同@Valid注解验证 * @return 验证成功:继续执行;验证失败:抛出异常跳转400页面。 */ protected void beanValidator(Object object, Class... groups) { BeanValidators.validateWithException(validator, object, groups); } /** * 添加Model消息 * @param message */ protected void addMessage(Model model, String... messages) { StringBuilder sb = new StringBuilder(); for (String message : messages){ sb.append(message).append(messages.length>1?"
":""); } model.addAttribute("message", sb.toString()); } /** * 添加Flash消息 * @param message */ protected void addMessage(RedirectAttributes redirectAttributes, String... messages) { StringBuilder sb = new StringBuilder(); for (String message : messages){ sb.append(message).append(messages.length>1?"
":""); } redirectAttributes.addFlashAttribute("message", sb.toString()); } /** * 客户端返回JSON字符串 * @param response * @param object * @return */ protected String renderString(HttpServletResponse response, Object object) { return renderString(response, JsonMapper.toJsonString(object)); } /** * 客户端返回字符串 * @param response * @param string * @return */ protected String renderString(HttpServletResponse response, String string) { try { response.reset(); response.setContentType("application/json"); response.setCharacterEncoding("utf-8"); response.getWriter().print(string); return null; } catch (IOException e) { return null; } } /** * 参数绑定异常 */ @ExceptionHandler({BindException.class, ConstraintViolationException.class, ValidationException.class}) public String bindException() { return "error/400"; } /** * 授权登录异常 */ @ExceptionHandler({AuthenticationException.class}) public String authenticationException() { return "error/403"; } /** * 初始化数据绑定 * 1. 将所有传递进来的String进行HTML编码,防止XSS攻击 * 2. 将字段中Date类型转换为String类型 */ @InitBinder protected void initBinder(WebDataBinder binder) { // String类型转换,将所有传递进来的String进行HTML编码,防止XSS攻击 binder.registerCustomEditor(String.class, new PropertyEditorSupport() { @Override public void setAsText(String text) { setValue(text == null ? null : StringEscapeUtils.escapeHtml4(text.trim())); } @Override public String getAsText() { Object value = getValue(); return value != null ? value.toString() : ""; } }); // Date 类型转换 binder.registerCustomEditor(Date.class, new PropertyEditorSupport() { @Override public void setAsText(String text) { setValue(DateUtils.parseDate(text)); } // @Override // public String getAsText() { // Object value = getValue(); // return value != null ? DateUtils.formatDateTime((Date)value) : ""; // } }); } }