转载请注明来源 赖赖的博客
核心思想明了,骨架已经建立,就可以一点一点的丰满细节,反哺骨架和核心思想
前面介绍了Spring MVC 是怎么接受一个访问的,想必你已经明白了基本的访问过程,作为一个应用系统,登录模块都必不可少,不妨今天就来做一个简单的登录模块,顺便熟悉一下Spring MVC的访问入参获取和拦截器的使用
https://github.com/laiyijie/SpringLearning
如图所示,虽然目录结构看起来复杂了一些(就是文件夹深度深了一点儿而已),其实最源文件只有五个。所以不要紧张,这非常简单,而且相比上一课,只多出了一个文件,和少量的配置
- http://127.0.0.1:8080/demo/user/login?username=laiyijie&password=lailai
第一次和最后一次的输入是完全一样的确实完全不同的两个结果?
由于第一次没有登录,然后返回的是403权限不足,第二次是登录以后访问这个链接,可以正常返回。
依照上一章的知识,访问会被引流到由@RequestMapping
注解的函数执行,我们不妨直接找到UserController
这个文件,访问是由这个控制器进行处理的
package me.laiyijie.demo.controller;
import org.springframework.stereotype.Controller;
import javax.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/hi")
@ResponseBody
public String hello(@RequestParam(value = "name", defaultValue = "world") String name) {
return "hello " + name;
}
@RequestMapping("/login")
@ResponseBody
public String login(@RequestParam("username") String username, @RequestParam("password") String password,
HttpSession httpsession) {
if ("laiyijie".equals(username) && "lailai".equals(password)) {
httpsession.setAttribute("username", username);
return "login success";
}
return "loging failed";
}
}
代码有几处变化:
@RequestMapping
注解,根据前面的执行结果可以知道,如果@RequestMapping
注解应用到类上,那么这个类中的所有方法的URL都增加这个注解的前缀,在这个例子中,都增加了 /user
,所以原来的/hi
变成了/user/hi
@RequestParam
标注的入参,该参数就是映射入参 127.0.0.1/demo/user/login?username=laiyijie&password=lailai
而其对应的函数声明有如下两个参数@RequestParam("username") String username, @RequestParam("password") String password
@RequestParam
获取了问号后面的键值对参数 hi
这个函数中我们这样使用@RequestParam(value = "name", defaultValue = "world") String name
设置了一个默认值,这样的话即使我们不传这个参数也会返回 hello world
(例如第三次访问) login
函数中新增了一个HttpSession
的入参 DispatcherServlet
分配URL对应控制器的时候会根据函数声明自动注入的一个参数,相应的还可以参考官方文档 HttpSession
从而可以操作Session
中的属性(Session在这个例子中是为了保存登录状态)login
函数中,在用户名和密码正确以后除了会返回login success
以外还会设置一个名为username
的Session
属性用来证明登录成功 那么问题来了,在第一次访问/uesr/hi
的时候是怎么会返回403
错误的呢?
这就要引入Spring MVC的一个重要组件,拦截器(Interceptor)
package me.laiyijie.demo.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String username = (String) request.getSession().getAttribute("username");
if (username != null) {
return true;
}else{
response.sendError(403);
return false;
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
不用看这么多代码,其实就两点:
HandlerInterceptor
接口 preHandle
方法(此方法用于在分配给Controller
之前执行,当同意继续访问的时候返回true
否则返回false
) Session
的username
属性 true
继续执行 403
错误并且返回false
是不是很简单?看了这个接口其实就可以明白拦截器处于的位置:
/demo/user/hi
访问被/demo
接受preHandel
方法)/user/hi
对应的方法hi
否则返回错误 那么又有一个新问题来了,/user/login
为什么没有被拦截?为什么没有返回403
错误?
那就要看Interceptor
的配置了:
拦截器配置如下(相比上节课新增):
interceptors
也就是拦截器组(对,里面可以有很多个拦截器)interceptor
/demo
的访问 /xx/xx
只能代表/xx
/user/login
) 简单的两个功能实现了一个简单的登录模块。
@RequstMapping
可以在类前注释,代表这个类中所有处理函数都要带其标注的一个前缀 @RequestParam
在Controller
处理函数的入参前注释,可以将例如?username=laiyijie&password=lailai
这样的参数绑定到对应的入参中@RequestParam
可以设置默认值,这样即使访问不带这个参数也可以有一个默认的输入,使用方式是@RequestParam(defaultValue="xxx")
Controller
中的处理函数可以增加HttpSession
的入参,由DispatcherServlet
自动注入,还有更多的属性可以参考官方文档 拦截器
通过继承HandlerInterceptor
接口,并使用
配置实现Controller
之前处理(preHandle
),处理结果为false可以阻止其进入Controller
中处理
)
)
4.0.0
me.laiyijie
demo
0.0.1-SNAPSHOT
war
1.8
1.8
1.8
org.springframework
spring-context
4.3.2.RELEASE
org.springframework
spring-webmvc
4.3.2.RELEASE
javax.servlet
javax.servlet-api
3.1.0
provided
org.apache.maven.plugins
maven-compiler-plugin
3.1
1.8
新增一个依赖javax.servlet-api
作用于为provided
,由容器提供
appServlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
/WEB-INF/spring/appServlet/servlet-context.xml
1
appServlet
/