SpringMVC day03

1. 重定向(Redirect)

在SpringMVC项目中,如果处理请求的方法的返回值是String类型的,则返回值默认表示转发到的视图名称,如果需要使用重定向,则应该使用redirect:作为前缀,并加上重定向到的目标路径(在网址中体现的)

return "redirect:index.do";

2. 使用Session

Session是保存在服务器端的内存中的数据。

在SpringMVC框架中,在处理请求的方法的参数列表中添加HttpSession类型的参数,即可使用Session!例如向Session中存入数据:

session.setAttribute("username", username);

后续,在Java程序中,就可以获取以上数据:

String username = session.getAttribute("username");

如果需要在Thymeleaf模版页面中显示Session中的数据,可以例如:

<span th:text="${session.username}">XXX</span>

后续,当需要清除Session中的数据时,调用invaliate()方法即可:

session.invalidate();

在SpringMVC中,也提供了框架所特有处理Session的做法,可以通过ModelMap封装Session中的数据,并结合在类之前添加@SessionAttriubtes({"id", "username"})注解来确定ModelMap中哪些数据是Session数据!但是,这种做法并不直观,并且与传统的Session机制不同,甚至都无法通过session.invalidate()清除Session的数据,只能通过SpringMVC框架的机制进行管理!通常,并不推荐这样使用Session!

使用传统的方式(使用HttpSession)的唯一缺点是不便于执行单元测试!但是,一般控制器中的方法并不会执行单元测试!通常,可以直接在浏览器的地址栏中输入URL来测试控制器中的方法,或者,使用专业的测试软件进行测试!

甚至,在一些大型的应用中,根本就不会去使用Session。

3. 拦截器(Interceptor)

3.1. 基本概念

假设设定规则:如果用户没有登录,不允许访问用户中心页面!

@RequestMapping("user.do")
public String showUser(HttpSession session) {
	System.out.println("UserController.showUser()");
	
	// 判断用户是否已经登录
	if (session.getAttribute("username") == null) {
		// 如果没有登录,转到登录页
		System.out.println("\t没有登录信息");
		return "redirect:login.do";
	}
	return "user"; 
}

在绝大部分应用中,需要用户登录才可以进行的操作种类非常多,那么,处理相关请求时,都需要添加以上判断登录的代码!但是,在多个处理请求的方法中都粘贴相同的代码,这样的做法是不可行的,工作量较大,不易于调整,不易于管理维护!

在SpringMVC框架中,使用拦截器可以解决以上问题!

拦截器(Interceptor)是可以执行在控制器之前的组件,则可以在拦截器对若干种请求进行相关判断,以决定是否执行控制器中的方法!最终选择阻止运行,或选择放行!

3.2. 创建拦截器类

在SpringMVC框架中,可以将自定义的拦截器放在任何包中!即:并不要求放在组件扫描范围之内!

可以创建cn.tedu.spring.LoginInterceptor拦截器,实现HandlerInterceptor接口:

public class LoginInterceptor implements HandlerInterceptor {

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

	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()");
	}
	
}
3.3. 配置拦截器

拦截器必须在spring.xml中添加配置:

<!-- 配置拦截器链 -->
<mvc:interceptors>
	<!-- 配置第1个拦截器 -->
	<mvc:interceptor>
		<!-- 拦截路径 -->
		<mvc:mapping path="user.do"/>
		<!-- 拦截器类 -->
		<bean class="cn.tedu.spring.LoginInterceptor" />
	</mvc:interceptor>
	<!-- 配置第2个拦截器 -->
	<!-- 配置第3个拦截器 -->
</mvc:interceptors>

通过运行,可以看到效果及结论:

  1. preHandle()方法返回false时,表示阻止继续运行,在浏览器显示一片空白,并且,阻止继续运行时,控制器中的方法并不会被执行,拦截器类中剩下的2个方法也不会执行!

  2. preHandle()方法返回true时,表示放行,即允许向后执行,则浏览器可以显示希望访问的页面,在Eclipse的控制台中,可以看到先执行了控制器的方法,然后依次执行了拦截器中的postHandle()afterCompletion()方法!即:preHandle() -> 控制器中的方法 -> postHandle() -> afterCompletion

所以,可以在preHandle()中添加对Session的判断:

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
		throws Exception {
	System.out.println("LoginInterceptor.preHandle()");
	
	// 判断用户是否已经登录
	if (request.getSession()
			.getAttribute("username") == null) {
		// 重定向到登录页
		String contextPath = request.getContextPath();
		response.sendRedirect(contextPath + "/login.do");
		// 如果没有登录,则阻止继续运行
		return false;
	}
	
	// 放行
	return true;
}

然后,在处理user.do请求的showUser()方法中,就不再需要判断Session的代码了!

-------------------------

附1:关于GET请求与POST请求

GET与POST都是HTTP请求的提交方式之一,其实,还有其它的提交方式,例如PUT、DELETE等,但是,一般只使用GET与POST这2种。

如果使用GET方式提交请求,请求参数将被体现在URL中,例如http://localhost:8080/reg.do?username=root&password=1234,如果使用POST方式提交请求,请求参数将被封装在请求体中,并不会表现在URL中!

由于GET请求会把请求参数的名称与值都体现在URL中,所以,被视为是一种不安全的提交方式,通常,不建议用于提交敏感数据,例如涉及账号安全的、涉及用户隐私的等,另外,还会受到URL长度的限制,通常理解为2K即可(具体值取决于浏览器和服务器端的限制值)。

以上GET请求存在的问题,在POST请求中都不存在!但是,POST请求并不能完全取代GET请求,有些操作必须通过GET方式才可以实现,例如:搜索,收藏,分享。

另外,GET请求的提交效率要高于POST请求!当使用GET方式提交请求时,URL中的参数将直接提交到服务器;当使用POST方式提交请求时,其实并不会直接提交请求参数,当服务器端接收到请求后,客户端会使用同一个连接继续提交请求参数,也就说,POST请求是分2次完成的!

附2:转发与重定向

首先,转发是服务器端内部的行为,而重定向则不是!

在转发过程中,客户只向服务器端发出过1次请求!在重定向过程中,客户端发出第1次请求后,服务器端响应了302及目标路径,然后客户端发出了第2次请求!

在转发过程中,客户端只与服务器端的控制器直接交互,所以,在客户端的浏览器中,只显示请求的路径,即控制器的路径!在重定向过程中,客户端与服务器出现2次交互过程,在浏览器中,显示的是最后一次交互的URL!

在编程时,使用SpringMVC框架,当处理请求的方法的返回值是String时,转发的返回值是视图名称,重定向的返回值中redirect:右侧是路径

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8PqyVEeb-1572542192876)(01.png)]

如果使用重定向,客户端浏览器中的URL是最后一次请求的URL,应该可以反复刷新页面,却不会重复此前提交的数据!如果希望刷新时不会重复提交此前的数据,则必须使用重定向!

使用重定向也是有缺点的!因为重定向的过程中出现过多次请求,基于HTTP协议是无状态协议,则第1次请求时产生的数据,在第2次处理请求的过程中,是不可以直接使用的!而转发是服务器内部的行为,整个处理过程中,只发生过1次请求,所以,控制器中产生的数据可以直接由页面来呈现!

附3:使用Session存储哪些数据

Session是保存在服务器端内存中的数据,如果服务器端设置Session的有效期是30分钟,则保存到Session中的数据至少会存在30分钟以上的时间!

通常,会存入到Session的数据有:

  1. 用户的身份标识,例如用户的id;

  2. 使用频率较高的数据,例如用户名;

  3. 不便于使用其它技术存取的数据。

附3:封装

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值