前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringMVC框架基础知识(03)

SpringMVC框架基础知识(03)

作者头像
海拥
发布2021-08-23 15:17:29
3810
发布2021-08-23 15:17:29
举报
文章被收录于专栏:全栈技术

1. 重定向

在SpringMVC框架中,如果处理请求的方法的返回值类型是String,且方法之前没有添加@ResponseBody注解时,使用redirect:目标路径作为返回结果,即可以实现重定向,例如:

代码语言:javascript
复制
return "redirect:hello.do";

2. 转发与重定向

转发:是服务器内部的行为,是由服务器端的控制器将请求转发到视图组件的过程,由于整个过程是发生在服务器内部的,所以,对于客户端来说,是不知道这个过程的,在客户端的浏览器的地址栏中的URL也就一直是最初发出请求的URL,在整个过程中,客户端也只发出了1次请求,如果刷新页面,会再次提交请求,从代码方面来看,转发时,控制器需要给出的只是“视图名称”即可,然后,根据服务器内部的相关配置确定具体的视图组件,之所以是这样,还是因为“转发是服务器内部的行为”,结合服务器端的配置一起使用也是非常正常的!由于转发是服务器内部端内部的行为,所以,服务器端的控制器可以转发任何数据到视图组件!

重定向:在整个过程中,客户端发出第1次请求时,服务器的响应方式是重定向,其具体表现是服务器端会向客户端发出302HTTP响应码,表示“重定向”,同时,还会向客户端响应目标路径,当客户端收到响应码是302时,就会自动的发出第2次请求,并根据服务器端响应的目标路径发出请求。由于客户端是明确第2次请求的目标的,所以,在客户端的浏览器的地址栏中会显示第2次请求的URL。从代码方面来,重定向时,必须给出明确的目标路径,客户端将根据这个路径发出第2次请求!由于前后共有2次请求,同时基于HTTP协议是无状态协议,在没有结合其它技术时,服务器端处理第1次请求时得到的数据并不可以用于处理第2次请求。

3. 使用Session

在SpringMVC中,在处理请求的方法的参数列表中添加HttpSession session对象,就可以使用Session了!

一般情况下,保存在Session中的数据会消失的情景有:

  • 服务器端的Tomcat重启后,Session中的数据会消失;
  • 当客户端的最后一次请求已经超时,Session中的数据会消失,超时时间可以由服务器端进行设置;
  • 当客户端软件被关闭后,将无法访问到此前的Session数据,同时,在超时后,此前的Session数据也会消失!

一般情况下,会保存到Session中的数据大致是这些类型的:

  • 用户身份的唯一标识,例如:用户的id、用户名等;
  • 高频率使用的数据,例如:用户名、头像这种高频率显示的数据,或者用户权限等;
  • 不便于使用其它技术实现存储或传递的数据。

4. Interceptor拦截器

在SpringMVC中,可以创建Interceptor(拦截器)组件,使得若干种不同的请求都会先经过拦截器组件,并且,拦截器组件可以对请求进行阻止,或放行。

注意:拦截器的目的并不一定是要“阻止”,也许,只是希望若干种不同的请求都执行相同的代码片断,然后,拦截器100%放行,也是可以的!

当需要拦截器,可以自定义类(对所在的包没有要求),实现HandlerInterceptor拦截器接口,例如:

代码语言:javascript
复制
public class LoginInterceptor implements HandlerInterceptor {

	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("LoginInterceptor.preHandle()"); // syst
		return true;
	}

	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("LoginInterceptor.postHandle()");
	}

	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("LoginInterceptor.afterCompletion()");
	}

}

所有的拦截器必须被注册之后才会发挥作用!关于拦截器的注册,必须重写SpringMVC的配置类中的addInterceptors()方法,通过方法的参数对象来注册拦截器,例如:

代码语言:javascript
复制
@ComponentScan("cn.tedu.spring")
@Configuration
@EnableWebMvc
public class SpringMvcConfigurer implements WebMvcConfigurer {

	/**
	 * 添加拦截器链
	 */
	public void addInterceptors(InterceptorRegistry registry) {
		// 注意:配置拦截器作用的相关路径时,路径值必须使用 / 作为第1个字符
		LoginInterceptor interceptor = new LoginInterceptor();
		registry.addInterceptor(interceptor).addPathPatterns("/hello.do");
	}
    
}

通过测试运行,可以发现,在拦截器中的preHandle()方法是运行在控制器之前的,并且,当该方法返回false时,表示“阻止运行”,会导致控制器中的方法不会被执行,当该方法返回true时,表示“放行”,接下来,控制器中的方法就会执行,所以,在拦截器的3个方法中,只有preHandle()是具备真正意义上的“拦截”效果的!

如果需要设计规则“只有登录了才允许后续的访问”,就可以在preHandle()中对登录信息进行验证,如果已登录,则放行,如果未登录,则拦截,且重定向到登录页!例如:

代码语言:javascript
复制
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    System.out.println("LoginInterceptor.preHandle()"); // syst
    HttpSession session = request.getSession();
    if (session.getAttribute("loginUsername") == null) {
        String contextPath = request.getContextPath(); // springmvc02
        response.sendRedirect(contextPath + "/login.do");
        return false;
    }
    return true;
}

关于拦截器的配置,首先,在同一个项目中,可以存在若干个拦截器组件,形成“拦截器链”,如果某个请求会经历多个拦截器组件,必须每个拦截器都放行,才能向后继续执行,如果其中任何一个拦截器执行效果是“阻止”,则尝试访问的控制器将不会被执行!注册拦截器时,注册的先后顺序决定各拦截器的执行顺序!

在配置拦截路径时,可调用的方法addPathPatterns()被重载了2次:

代码语言:javascript
复制
public InterceptorRegistration addPathPatterns(String... patterns) {
    return addPathPatterns(Arrays.asList(patterns));
}

public InterceptorRegistration addPathPatterns(List<String> patterns) {
    this.includePatterns.addAll(patterns);
    return this;
}

所以,在配置拦截路径时,可以使用List<String>或可变参数String...来表示若干个被拦截的路径。

在配置请求路径时,还可以使用星号(*)作为通配符,例如,尝试拦截的路径有:

代码语言:javascript
复制
/blog/publish.do
/blog/edit.do
/blog/delete.do
/blog/list.do

只需要配置为以下路径即可:

代码语言:javascript
复制
/blog/*

需要注意的是:在配置拦截路径时,使用1个星号(*)的通配符只能匹配1个层级的资源,无法匹配多层级资源!例如配置为/blog/*时,就不可以匹配到/blog/2020/list.do,如果需要匹配若干个层级(1层或多层)的资源,就需要使用2个星号(**),例如配置为:

代码语言:javascript
复制
/blog/**

当然,一旦使用了通配符,就可能导致匹配的范围过大的问题!毕竟有相同前缀,但是后缀不同的若干个请求路径中,可能有些需要经过拦截器,而有些并不需要经过拦截器!例如:用户注册、用户登录都不必经过“登录拦截器”,但是修改资料、修改密码、修改头像、验证手机、验证邮箱等诸多操作都是需要经过“登录拦截器”,就会存在“如果不使用通配符,就必须一个个的配置拦截路径,工作量较大,如果使用通配符,可能将用户注册、用户登录也匹配进去,导致匹配过大”的问题!所以,SpringMVC还提供了配置“排除路径”的做法,也就是“在已经配置的路径范围中排除某些路径”,类似于“白名单”,其方法是:

代码语言:javascript
复制
public InterceptorRegistration excludePathPatterns(String... patterns) {
    return excludePathPatterns(Arrays.asList(patterns));
}

public InterceptorRegistration excludePathPatterns(List<String> patterns) {
    this.excludePatterns.addAll(patterns);
    return this;
}

例如,可以配置为:

代码语言:javascript
复制
registry.addInterceptor(new LoginInterceptor())
    	.addPathPatterns("/user/**")
    	.excludePathPatterns("/user/reg.do", "/user/login.do");

以上代码就表示“以/user/开头的路径都是需要被拦截的,但是,/user/reg.do/user/login.do这2个路径是例外的,不需要被拦截器处理”。

5. 过滤器与拦截器的区别

相似之处:

都可以使得若干个请求路径都执行过滤器组件/拦截器组件中的代码片断,都可以在执行之后选择“阻止”或“放行”,都有“链”的概念。

区别:

  • 过滤器Filter是Java EE中的组件,只要是Java Web项目都可以使用过滤器,包括在SpringMVC项目中也可以使用过滤器;拦截器Interceptor是SpringMVC框架中的组件,只有使用了SpringMVC框架的项目,才可以使用拦截器,并且,只有被SpringMVC框架处理的请求才可能被拦截器所处理,例如,将DispatcherServlet映射的路径(在SpringMvcInitializergetServletMappings()方法的返回值)配置为*.do时,只有以.do为后缀的请求才可能被拦截器处理,而例如.jpg类似的请求将不会被拦截器处理,当然,如果有必要的话,也可以将DispatcherServlet映射的路径配置为/*,则任何请求都可能被拦截器处理。
  • 过滤器Filter可以配置若干个映射路径,可以使用通配符,但是,却不能从中剔除部分请求路径,也就是“不能配置白名单”,在配置时可能比较麻烦;拦截器Interceptor在配置映射的请求路径时,既可以配置拦截路径(黑名单),又可以配置排除路径(白名单),配置更加简单、灵活。
  • 过滤器Filter是执行在所有Servlet组件之前的;而拦截器Interceptor的第1次执行是在DispatcherServlet之后,且在Controller之前的。

小结:

在SpringMVC项目中,应该优先使用拦截器Interceptor组件,除非某些代码片断必须在Servlet之前执行!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/05/30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 重定向
  • 2. 转发与重定向
  • 3. 使用Session
  • 4. Interceptor拦截器
  • 5. 过滤器与拦截器的区别
相关产品与服务
云服务器
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档