在SpringMVC项目中,如果处理请求的方法的返回值是String类型的,则返回值默认表示转发到的视图名称,如果需要使用重定向,则应该使用redirect:作为前缀,并加上重定向到的目标路径(在网址中体现的)!
return "redirect:index.do";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。
假设设定规则:如果用户没有登录,不允许访问用户中心页面!
@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)是可以执行在控制器之前的组件,则可以在拦截器对若干种请求进行相关判断,以决定是否执行控制器中的方法!最终选择阻止运行,或选择放行!
在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()"); } }拦截器必须在spring.xml中添加配置:
<!-- 配置拦截器链 --> <mvc:interceptors> <!-- 配置第1个拦截器 --> <mvc:interceptor> <!-- 拦截路径 --> <mvc:mapping path="user.do"/> <!-- 拦截器类 --> <bean class="cn.tedu.spring.LoginInterceptor" /> </mvc:interceptor> <!-- 配置第2个拦截器 --> <!-- 配置第3个拦截器 --> </mvc:interceptors>通过运行,可以看到效果及结论:
当preHandle()方法返回false时,表示阻止继续运行,在浏览器显示一片空白,并且,阻止继续运行时,控制器中的方法并不会被执行,拦截器类中剩下的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的代码了!
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次完成的!
首先,转发是服务器端内部的行为,而重定向则不是!
在转发过程中,客户只向服务器端发出过1次请求!在重定向过程中,客户端发出第1次请求后,服务器端响应了302及目标路径,然后客户端发出了第2次请求!
在转发过程中,客户端只与服务器端的控制器直接交互,所以,在客户端的浏览器中,只显示请求的路径,即控制器的路径!在重定向过程中,客户端与服务器出现2次交互过程,在浏览器中,显示的是最后一次交互的URL!
在编程时,使用SpringMVC框架,当处理请求的方法的返回值是String时,转发的返回值是视图名称,重定向的返回值中redirect:右侧是路径。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8PqyVEeb-1572542192876)(01.png)]
如果使用重定向,客户端浏览器中的URL是最后一次请求的URL,应该可以反复刷新页面,却不会重复此前提交的数据!如果希望刷新时不会重复提交此前的数据,则必须使用重定向!
使用重定向也是有缺点的!因为重定向的过程中出现过多次请求,基于HTTP协议是无状态协议,则第1次请求时产生的数据,在第2次处理请求的过程中,是不可以直接使用的!而转发是服务器内部的行为,整个处理过程中,只发生过1次请求,所以,控制器中产生的数据可以直接由页面来呈现!
Session是保存在服务器端内存中的数据,如果服务器端设置Session的有效期是30分钟,则保存到Session中的数据至少会存在30分钟以上的时间!
通常,会存入到Session的数据有:
用户的身份标识,例如用户的id;
使用频率较高的数据,例如用户名;
不便于使用其它技术存取的数据。