import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; import jetbrick.template.JetAnnotations.Functions; import jetbrick.template.JetContext; import jetbrick.template.runtime.JetPageContext; import jetbrick.template.web.JetWebContext; import org.springframework.context.MessageSource; import org.springframework.context.NoSuchMessageException; import org.springframework.validation.BindingResult; import org.springframework.validation.Errors; import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; import org.springframework.web.servlet.support.RequestContextUtils; @Functions public class SpringFunctions { private static final List<String> EMPTY_STRING_LIST = Collections.unmodifiableList(new ArrayList<String>()); public static List<String> errors(JetPageContext ctx, String filedName) { HttpServletRequest request = (HttpServletRequest) ctx.getContext().get(JetWebContext.REQUEST); Errors errors = findErrors(ctx); if (errors == null) { System.out.println("没有找到Errors"); return EMPTY_STRING_LIST; } List<FieldError> fes = errors.getFieldErrors(filedName); List<String> msgs = new ArrayList<String>(0); for(FieldError fe : fes) { String[] codes = fe.getCodes(); String defaultMsg = fe.getDefaultMessage(); Object[] args = fe.getArguments(); Locale locale = findLocale(request); MessageSource ms = findMessageSource(request); if (codes == null || codes.length == 0 || ms == null) { msgs.add(defaultMsg); } else { String msg = null; for (int i = 0; i < codes.length; i ++) { try { msg = ms.getMessage(codes[i], args, locale); } catch (NoSuchMessageException e) { // 忽略 } if (msg == null) { msg = defaultMsg; } } msgs.add(msg); } } return Collections.unmodifiableList(msgs); } public static List<String> errors(JetPageContext ctx) { HttpServletRequest request = (HttpServletRequest) ctx.getContext().get(JetWebContext.REQUEST); Errors errors = findErrors(ctx); if (errors == null) { return EMPTY_STRING_LIST; } List<ObjectError> oes = errors.getGlobalErrors(); List<String> msgs = new ArrayList<String>(0); for (ObjectError oe : oes) { String[] codes = oe.getCodes(); String defaultMsg = oe.getDefaultMessage(); Object[] args = oe.getArguments(); Locale locale = findLocale(request); MessageSource ms = findMessageSource(request); if (codes == null || codes.length == 0 || ms == null) { msgs.add(defaultMsg); } else { String msg = null; for (int i = 0; i < codes.length; i ++) { try { msg = ms.getMessage(codes[i], args, locale); } catch (NoSuchMessageException e) { // 忽略 } if (msg == null) { msg = defaultMsg; } } msgs.add(msg); } } return Collections.unmodifiableList(msgs); } @SuppressWarnings("unchecked") private static Errors findErrors(JetPageContext ctx) { try { JetContext jetContext = ctx.getContext(); Field[] fileds = JetContext.class.getDeclaredFields(); Field f = null; for (Field field : fileds) { if (field.getName().equals("context")) { f = field; break; } } if (f == null) { return null; } f.setAccessible(true); Map<String, Object> context = (Map<String, Object>) f.get(jetContext); Set<String> keyset = context.keySet(); String key = null; for (String k : keyset) { if (k.startsWith(BindingResult.MODEL_KEY_PREFIX)) { key = k; break; } } if (key == null) { return null; } return (Errors) jetContext.get(key); } catch (Exception e) { // e.printStackTrace(); } return null; } private static MessageSource findMessageSource(HttpServletRequest request) { return RequestContextUtils.getWebApplicationContext(request); // WebApplicationContext本身就是MessageSource的实现 } private static Locale findLocale(HttpServletRequest request) { return RequestContextUtils.getLocale(request); } }
由JSR303标注验证的Bean
public class TestForm implements java.io.Serializable { private static final long serialVersionUID = 4120123239547893935L; @NotNull private Integer id; @NotNull @Length(min = 3, max = 12) private String name; @NotNull private Integer age; // getter & setter }
Controller
@Controller public class TestController { @RequestMapping(value = "/test", method = {RequestMethod.GET}) public String test(@Validated TestForm form, BindingResult br, ModelMap modelMap) { br.reject(null, "故意加入一个全局错误"); br.reject(null, "另一个全局错误"); br.rejectValue("id", null, "id field的一个由java代码添加的错误"); if (br.hasErrors()) { return "test"; } return "ok"; } }
jetx
<html> <head> <base href="${webroot()}" /> <title>错误</title> </head> <body> <h1>ERROR JETX</h1> <div> <h3>全局错误</h3> #set(List<String> gel = errors()) <ul> #for(String msg : gel) <li>${msg}</li> #end </ul> </div> <div> <h3>Field错误 (id)</h3> #set(List<String> idMsg = errors("id")) <ul> #for(String msg : idMsg) <li>${msg}</li> #end </ul> </div> <div> <h3>Field错误 (name)</h3> #set(List<String> nameMsg = errors("name")) <ul> #for(String msg : nameMsg) <li>${msg}</li> #end </ul> </div> <div> <h3>Field错误 (age)</h3> #set(List<String> ageMsg = errors("name")) <ul> #for(String msg : ageMsg) <li>${msg}</li> #end </ul> </div> </body> </html>