一、静态资源不拦截

第二部分最后显示的几个页面其实都加载了css和js等文件,要不然不会显示的那么好看(假装好看吧),前面已经说了,我们在web.xml中配置了url的拦截形式是/,那么DispatcherServlet会拦截除了jsp外的所有资源,包括静态资源,那么为什么我们的页面还是加载了css和js等资源呢,是因为我们在springmvc.xml中进行了如下配置:

location="/css/"代表根目录下的css文件夹,都哪些资源不拦截呢,是/css/**,**意思就是只要是css文件夹下的都不拦截。

二、springmvc请求处理流程

当我们在浏览器访问:http://localhost:8080/login的时候,前端控制器解析url,得到请求资源标示符/,执行处理器映射器去映射对应的handler对象,获得该handler配置的所有相关对象(包括Handler对象以及对应的拦截器),最后以HandlerExecutionChain对象的形式返回,如果用户自定义了拦截器,开始执行拦截器的preHandle()方法,在此方法中对请求进行拦截或者放行,如果用户没有定义拦截器则没有这步操作。然后前端控制器调用处理器适配器去执行对应的handler,就是controller中对应的方法,例如此例中对应我们UserController中的showLogin()方法,执行完毕后返回ModelAndView,包括要返回的页面以及设置的属性。然后前端控制器开始调用ViewReslover去解析,解析完后发现原来要返回/WEB-INF/jsp/login.jsp这个页面。然后再去渲染这个页面,例如页面中可能要取一些后台传过来的值。最后响应给客户端浏览器。

三、定义登录拦截器

如果用户在没有登录的情况下,有些资源是不能让用户访问的,这个时候我们需要对请求的url进行过滤,然后决定是放行还是拦截。来看com.neu.interceptor.LoginInterceptor这个类

前面已经说了,在执行controller中具体的方法之前,需要执行自定义拦截器的preHandler()方法。在此方法中,我们定义规则如下:如果是访问主页,登录页面,或者是注册页面,或者是登录操作,或者是注册操作都放行。因为这些操作还进行拦截,用户就永远不能登录注册了。request.getRequestURI()方法返回的是请求资源标识符,例如访问http://localhost:8080/login,uri就是/login。如果用户访问的不是以上资源,那么我们需要判断用户是否登录,就是判断session中有没有user属性。由于在UserController的登录方法login(),一旦用户登录成功,我们就给session的user属性设置了值。来看一下:

所以,如果是登录状态,也放行。否则就直接重定向到登录页面,返回false。如果放行的情况下:会开始执行UserController中对应的handler方法,然后就是后续的一系列操作。当然,如果想让自定义的拦截器生效,需要在springmvc.xml中进行配置

登录拦截器当然也会拦截我们的静态资源,所以我们需要过滤掉静态资源的拦截,如上图中红框的配置。

四、用户注册功能

当我们在登录页面点击Create Account,会跳转到注册页面。来看看跳转的过程,先打开login.jsp

这个超链接访问的是${pageContext.request.contextPath}/register,${pageContext.request.contextPath}就相当于我们的工程根路径。所以这个url相当于是访问http://localhost:8080/register,首先前端控制器会拦截,映射到到具体的handler,这个时候handler还不能执行,因为登录拦截器的preHandler()方法会先执行,发现原来这个请求不需要拦截,放行。开始执行handler对应的方法showRegister(),然后就跳转到register.jsp页面了。来看看这个页面的表单都有什么

三个字段,用户名,密码,确认密码,还有一个提交按钮,页面中引入的js一会再说。我们发现username和password的name字段正好和com.neu.pojo.User的username和password属性对应,那么我们就可以使用User对象来接收这两个参数,发现确认密码confirmPass和User的属性不匹配怎么办,没关系,我们在UserController的register()方法参数中加个String confirmPass就行了,这样这个参数也能够接收到了。来继续看UserController

先查询注册的用户是否存在,如果存在就跳转到register.jsp,如果不存在就补全pojo属性,插入数据库。这里密码我们使用的是spring自带的MD5加密,然后跳转到success.jsp。这里有些地方需要说一下,当查询到注册的用户已存在的时候,我们调用了returnRegisterData()方法来设置页面回显的值。

读者可能发现,在注册页面,每个表单字段都有个value属性,例如username那块,value="${username }",这样在model中设置的username属性值就可以取到了,其他的一样。message属性用来定义错误信息,我们在注册页面的一个div中显示它。

当然,这个div不是页面一打开就显示的,例如我们第一次访问注册页面填写表单的时候就不能显示它,只有后台回显数据的时候才显示它,这是register.js控制的,来看看这个js。

这里我们使用了jquery,$(function(){})中的内容页面加载完毕就执行,先获取显示错误信息的这个div(var meg = $("#td-meg-div");),然后判断这个div内有没有内容(if (meg.html() == "")),如果没有内容,说明是第一次打开注册页面填写表单,后台不会传过来message值,div中${message}自然内容就为空了,那么我们就隐藏这个div(meg.hide();),如果是回显数据到注册页面呢,那么这个div就有内容,有内容就不隐藏呗,反正默认div就是显示的。在register.js中我们还给提交按钮绑定了click事件,加上了一些前端表单验证,验证成功后就提交。

还有我们给回车键也加上了一个监听事件,13就代表回车键码

注册成功后,会跳转到success.jsp,来看看这个jsp

在页面中我们还定义了5秒跳转的js,5秒后跳转到登录页面

四、用户登录功能

首先来看login.jsp页面

和注册页面类似,两个表单字段username和password,加上一个提交按钮,一个重置按钮,当然也少不了我们回显错误信息的div。login.js和register.js的内容大同小异,这里我们就不再重复了。来看看处理登录请求

代码比较简单,大家应该都能看明白。下面我们演示一下整个流程吧

来个正确的试试

看下数据库有没有添加进来

我这里因为实验了很多次,id本来我们设置的是自增的,所以显示id=43,不奇怪,如果是第一此插入会是id=1

这个时候我们先不登录,继续使用刚才的用户名注册,看看错误信息回显了没有

和预期的一样,正确显示错误信息。我们来登录试试吧!

赶紧登录成功吧,去看看主页,这次我们输入正确的用户名密码再次访问,会跳转到主页

主页终于出来了,确认很简陋,体谅博主前端技术太菜,做不出优雅的界面。点击注销试试

在index.jsp中点击注销会访问/logout,去UserController中看看

这里只是简单的把session中保存的用户信息删除,然后重定向到/login这个handler,然后跳转到登录页面。

五、全局错误页面

当用户在浏览器中输入不存在的页面或者以不允许的请求方式去提交表单都会出现一些错误信息,当然为了更友好的展示错误信息,我们可以在web.xml中配置错误页面

例如我们在浏览器中输入http://localhost:8080/dwqdqwdqwd/dedf32325,就会跳转到error.jsp

至此,整个项目就搭建完毕了。写博客的过程中发现,把自己会的东西用通俗易懂的语言讲给别人真是一件很费力的事情。不过这也有好处,相当于加深一遍印象,也加深了自己的理解。项目驱动是最好的老师,希望大家都可以动手去实现一下!不懂的可以在下面留言。谢谢阅读!

最新文章

  1. JavaScript中的继承
  2. Xamarin设备相关图片尺寸要求
  3. MapReduce的输入输出
  4. poj 2060 Taxi Cab Scheme (最小路径覆盖)
  5. 翻译-让ng的$http服务与jQuerr.ajax()一样易用
  6. dede仿站笔记
  7. 致终将火爆的NFC——ISO14443 TypeA
  8. iOS 中UITableViewController 中tableView 会被状态栏覆盖的问题
  9. iOS转场动画
  10. Echart饼图、柱状图、折线图(pie、bar、line)加入点击事件
  11. 业务接口+UI层的设计(基于Castle实现的Repository)
  12. vue 从入门到精通(一)
  13. Influxdb1.2.2安装
  14. 从PRISM开始学WPF(二)Prism-更新至Prism7.1
  15. LeetCode算法题-Minimum Depth of Binary Tree(Java实现)
  16. odoo系统中name_search和name_get用法
  17. 做了一道cf水题
  18. Navicat 12破解工具 +安装包
  19. ZeroMQ API(四) 套接字
  20. ESP8266调试记录

热门文章

  1. Glide加载图片的事例
  2. Hibernate、Spring和Struts工作原理及使用理由
  3. CentOS7.2 安装iptables
  4. kafka java api消费者
  5. linux服务器上的jenkins远程触发构建windows server 2012服务器上的jenkins任务
  6. SVN提交文件冲突怎么办?
  7. HDU 1171 Big Event in HDU 杭电大事件(母函数,有限物品)
  8. 从汇编看c++中临时对象的析构时机
  9. 转过来的Xpath语法
  10. python学习(day1)