spring实战-Spring中Filter以及处理Exception方式

来源:互联网 发布:一落叶而知天下秋启示 编辑:程序博客网 时间:2024/06/06 08:46

第七篇:spring实战-Spring中Filter以及处理Exception方式

Filter对于Web应用程序是至关重要的,如果web请求的字符转换,XSS攻击拦截等等

在SpringMVC中添加Filter也是非常方便的,可以通过重写AbstractAnnotationConfigDispatcherServletInitializer的getServletFilters()来实现

如我们前几节构架的应用程序,是无法将中文字符从前端传到服务器中去的,此时我们需要一个必要的字符转换,可以通过Filter来实现

1,构建一个SetCharacterEncodingFilter

package com.halfworlders.idat.filter;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;public class SetCharacterEncodingFilter implements Filter {      @Override      public void doFilter(ServletRequest request, ServletResponse response,              FilterChain filterChain) throws IOException, ServletException {          if (request.getCharacterEncoding() == null) {              request.setCharacterEncoding("UTF-8");          }          filterChain.doFilter(request, response);      }@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void destroy() {}  }  
2,在IdatWebAppInitializer中重写getServletFilters()方法

/** * 添加一个或多个Filter * 返回的所有Filter都会映射到DispatcherServlet上,所以没有为Filter设置映射路径 */@Overrideprotected Filter[] getServletFilters() {return new Filter[] {new SetCharacterEncodingFilter()};}
以上两步就实现了一个Spring Filter并将其应用到SpringMVC应用程序中去了。



如果我们的程序一直在正在的代码路径中运行就非常完美了,但是这是不可能的,程序中总是会出现各种异常的情况,如果不对程序异常的情况做处理,是非常糟糕的,简单点可能是给用户一个不友好的页面,严重的可能会由于异常堆栈直接向客户端暴露服务器应用程序的私密信息,甚至有些异常不加处理可能会导致应用程序奔溃。

所以一个健壮的应用程序应该包含完整的异常处理机制

Spring针对HTTP异常,实现了一个非常方便的处理方式,可以增加客户页面的友好提示,同时不泄露服务器信息,同时可以通过一个简单的实现,处理所有控制器的异常信息,但是也可以通过在单个控制器类实现@ExceptionHandler(AppException.class)来处理单个控制器HTTP异常,以下主要演示通过控制器通知的方式统一的为控制器提供异常处理。

控制器通知类定义

package com.halfworlders.idat.handler;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import com.halfworlders.idat.exception.AppException;/** * 定义控制器类 * @author lllhappy * */@ControllerAdvicepublic class IdatExceptionHandler {/** * 定义异常处理方法,可以为每个种类的异常定义一个处理方式 * @return */@ExceptionHandler(AppException.class)public String appExceptionHandler(){return "error/appException";}}

通过以上方式就可以将控制器中抛出的AppException类型的异常捕获到,并通过error/appException页面给用户友好提示,而不是简单粗暴的给用户一个异常堆栈的页面



前面章节有演示通过post方式提交数据后,控制器中通过redirect:的方式返回重定向,这样做时方式用户提交后点击刷新按钮,或者后退箭头后,导致客户端再次post提交

但是redirect:不同forward:,我们知道forward:是请求转发,转发的同时可以将request带到下一次回话中,也同时可以将数据带过去,但是redirect:不行,参考点击打开链接

SpringMVC给了我们很好的处理方案,一种可以通过重定向URL进行数据传递,另外还可以通过RedirectAttributes使用flash属性将对象属性整体传递给下一次会话

@RequestMapping(value = "/create", method = RequestMethod.POST)public String create(@Valid Interface intf, Errors errors, RedirectAttributes model) {// 如果校验不通过的话,返回创建表单页面if (errors.hasErrors()) {return "createForm";}Interface rintf = idatService.save(intf);// name属性将填充到一下URL模板的name占位符中model.addAttribute("name", rintf.getName());// 通过flash属性,在重定向之前将整个模型对象全部打包复制到会话中,会存活到下一次请求才消失model.addFlashAttribute("intf", rintf);return "redirect:queryInterfacesByName/{name}/intf";}
重定向接受方控制器

@RequestMapping(value = "/queryInterfacesByName/{name}/intf", method = RequestMethod.GET)public String queryInterfacesByName(@PathVariable("name") String name, Model model) {// 先检查是否已经存在对应的intf属性,如果不包括,才会去数据库中查询if (!model.containsAttribute("intf")) {Interface interfaces = idatService.queryInterfacesByName(name);model.addAttribute("intf", interfaces);}return "interface";}





原创粉丝点击