一,演示项目的相关信息
1,地址:
https://github.com/liuhongdi/filtertest
2,功能:演示给带有filter的controller做单元测试
3,项目结构:如图:
说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest
对应的源码可以访问这里获取: https://github.com/liuhongdi/
说明:作者:刘宏缔 邮箱: 371125307@qq.com
二,java代码说明
1,filter/TimeFilter.java
public class TimeFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("----------------time filter init"); } //过滤功能,我们统计请求所花费的时间 @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("----------------time filter doFilter begin"); HttpServletRequest request = (HttpServletRequest) servletRequest; String path = request.getRequestURI(); String v = request.getParameter("v"); System.out.println("filter: v: "+v); if (v == null || v.equals("")) { ServletUtil.printString("缺少参数"); return; } String method = request.getMethod(); System.out.println("filter: method: "+method); //if () long startTime = System.currentTimeMillis(); filterChain.doFilter(servletRequest,servletResponse); long endTime = System.currentTimeMillis(); System.out.println("timefilter: "+path + " costtime: "+ (endTime-startTime) +"ms "); System.out.println("----------------time filter doFilter end"); } @Override public void destroy() { System.out.println("----------------time filter destroy"); } }
2,util/ServletUtil.java
public class ServletUtil { //获取request public static HttpServletRequest getRequest() { return getRequestAttributes().getRequest(); } //获取response public static HttpServletResponse getResponse() { return getRequestAttributes().getResponse(); } //获取session public static HttpSession getSession() { return getRequest().getSession(); } //获取ServletRequestAttributes public static ServletRequestAttributes getRequestAttributes() { RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); return (ServletRequestAttributes) attributes; } //得到当前的url地址 public static String getUrl() { HttpServletRequest request= getRequestAttributes().getRequest(); String ip = request.getRemoteAddr(); String url = request.getRequestURL().toString(); String param = request.getQueryString(); //System.out.println("param:"+param); String finalurl = ip+"--"+url; if (param != null) { finalurl= ip+"--"+url+"?"+param; } return finalurl; } //将字符串渲染到客户端 public static String printString(String string) { try { HttpServletResponse response= getResponse(); response.setContentType("text/html"); response.setCharacterEncoding("utf-8"); //response.getWriter().print(string); PrintWriter out = response.getWriter(); //response.getWriter().print(resp); out.write(string); out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } return null; } //判断请求是否是ajax public static boolean isAjax() { HttpServletRequest request= getRequest(); return (request.getHeader("X-Requested-With") != null && "XMLHttpRequest".equals(request.getHeader("X-Requested-With").toString())); } }
3,controller/HomeController.java
@Controller @RequestMapping("/home") public class HomeController { //示例controller,供统计时间用 @GetMapping("/home") @ResponseBody public String homeMethod(@RequestParam("v") String version) { System.out.println("controller v:"+version); try { Thread.sleep(1000); //延时1秒 } catch(InterruptedException e) { e.printStackTrace(); } return "this is home,v="+version; } }
4,config/DefaultMvcConfig.java
@Configuration @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) public class DefaultMvcConfig implements WebMvcConfigurer { //add filter //registration.addUrlPatterns("/icons/*", "/style/*", "/script/*", "/dwr/*", "/icons/*", "/coverArt.view", "/avatar.view"); //registration.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid2/*"); @Bean public FilterRegistrationBean addTimeFilterBean() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new TimeFilter()); registration.setName("timeFilter"); registration.setOrder(1); //请求中过滤器执行的先后顺序,值越小越先执行 registration.addUrlPatterns("/home/*","/abc/*"); return registration; } }
5,controller/HomeControllerTest.java
@AutoConfigureMockMvc @SpringBootTest class HomeControllerTest { @Autowired private HomeController homeController; @Autowired private MockMvc mockMvc; @Test @DisplayName("测试controller返回") void home1() throws Exception { MvcResult mvcResult = mockMvc.perform(get("/home/home?v=3") .contentType(MediaType.APPLICATION_FORM_URLENCODED)) .andReturn(); String content = mvcResult.getResponse().getContentAsString(); assertThat(content, equalTo("this is home,v=3")); } @Test @DisplayName("测试过滤器返回") void home2() throws Exception { MvcResult mvcResult = mockMvc.perform(get("/home/home") .contentType(MediaType.APPLICATION_FORM_URLENCODED)) .andReturn(); String content = mvcResult.getResponse().getContentAsString(); assertThat(content, equalTo("缺少参数")); } }
三,测试效果
四,备注
1,如果使用了FilterRegistrationBean引入fitler,
又同时在filter的类上加了@Component注解,
则使用mockmvc时会导致filter被执行两次
大家注意只使用一种引入方式
五,查看spring boot的版本:
. ____ _ __ _ _ /\ / ___'_ __ _ _(_)_ __ __ _ ( ( )\___ | '_ | '_| | '_ / _` | \/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.4.4)