MVC 模型
MVC 是Model、View和Controller 的缩写,分别代表Web应用程序中的三种职责
Model模型
用于存储数据以及处理用户请求的业务逻辑
View视图
向控制器提交数据,显示模型中的数据
Controller控制器
根据视图提出的请求判断将请求和数据交给哪个模型处理,将处理后的有关结果交给哪个视图更新显示
Spring MVC 工作原理
Spring MVC 接口
接口 | 说明 |
---|---|
DispatcherServlet 接口 | 所有请求都经过DispatcherServlet来统一发行,在DispatherServlet将请求分发给Controller之前需要借助Spring MVC 提供的 HandlerMapping 定位到具体的Controller |
HandlerMapping 接口 | 负责完成客户请求到Controller映射 |
Controller 接口 | 将处理用户请求 一旦Controller处理完用户请求,将返回ModelAndView对象给 DispatcherServlet前端控制器,ModelAndView中包含了模型(Model)和视图(View) |
ViewResolver 接口 (视图解析器) | 在Web应用中负责查找View对象,从而将相应结果渲染给客户 |
从宏观角度考虑,DispatcherServlet是整个Web应用的控制器
从微观考虑,Controller是单个Http请求处理过程中的控制器,ModelAndView是Http请求过程中返回的模型(Model)和视图(View)
基于注解的控制器
@Controller
在Spring MVC 中使用 org.springframework.stereotype.Controller
注解类型声明某类的实例时一个控制器
@RequestMapping
在基于注解的控制器类中可以为每个请求编写对应的处理方法
使用 org.springframework.web.bind.annotation.RequestMapping
注解类型将请求与处理一一对应
value属性
将请求URI映射到方法,是默认属性,若只有一个value属性,可省略该属性
方法级别注解
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class IndexController {
@RequestMapping(value="/index/login")
public String login() {
return "login"; //跳转到“/WEB-INF/jsp/login.jsp”
}
@RequestMapping(value="/index/register")
public String register() {
return "register";
}
}
类级别注解
Controller接收请求参数的常见方式
通过实体Bean接收请求参数
通过一个实体Bean来接收请求参数,适用于 get
和 post
提交请求的方式。
Bean的属性名称必须与请求参数名称相同
@RequestMapping("/register")
public String register(UserForm user,Model model) {
if("zhangsan".equals(user.getUname()) && "123456".equals(user.getUpass())){
logger.info("成功");
return "login";//注册成功,跳转到login.jsp
}else{
logger.info("失败");
//在register.jsp 页面上使用EL表达式取出 model 的 uname 值
model.addAttribute("uname",user.getUname());
return "register";//返回register.jsp
}
}
通过处理方法的形参接收请求参数
适用于 get
和 post
提交请求的方式
直接把表单参数写在控制器类相应方法的形参中,即形参名称与请求名称完全相同。
@RequestMapping("/register")
public String register(String uname,String upass,Model model) {
if("zhangsan".equals(uname) && "123456".equals(upass)){
logger.info("成功");
return "login";//注册成功,跳转到login.jsp
}else{
logger.info("失败");
//在register.jsp 页面上使用EL表达式取出 model 的 uname 值
model.addAttribute("uname",uname);
return "register";//返回register.jsp
}
}
通过 HttpServletRequest
接收请求参数
适用于 get
和 post
提交请求的方式
@RequestMapping("/register")
public String register(HttpServletRequest request,Model model) {
String uname = request.getParameter("uname");
String upass = request.getParameter("upass");
if("zhangsan".equals(uname) && "123456".equals(upass)){
logger.info("成功");
return "login";//注册成功,跳转到login.jsp
}else{
logger.info("失败");
//在register.jsp 页面上使用EL表达式取出 model 的 uname 值
model.addAttribute("uname",uname);
return "register";//返回register.jsp
}
}
通过 @PathVariable
接收URL中的请求参数
@RequestMapping(value="/register/{uname}/{upass}",method=Request Method.GET)
public String register(@PathVariable String uname,@PathVariable String upass,Model model) {
if("zhangsan".equals(uname) && "123456".equals(upass)){
logger.info("成功");
return "login";//注册成功,跳转到login.jsp
}else{
logger.info("失败");
//在register.jsp 页面上使用EL表达式取出 model 的 uname 值
model.addAttribute("uname",uname);
return "register";//返回register.jsp
}
}
通过 @RequestParam
接收请求参数
适用于 get
和 post
提交请求的方式
@RequestMapping("/register")
public String register(@RequestParam String uname,@RequestParam String upass,Model model) {
if("zhangsan".equals(uname) && "123456".equals(upass)){
logger.info("成功");
return "login";//注册成功,跳转到login.jsp
}else{
logger.info("失败");
//在register.jsp 页面上使用EL表达式取出 model 的 uname 值
model.addAttribute("uname",uname);
return "register";//返回register.jsp
}
}
通过 @ModelAttribute
接收请求参数
适用于 get
和 post
提交请求的方式
当@ModelAttribute 注解放到处理方法的形参上时,用于将多个请求参数封装到一个实体对象,从而简化数据绑定流程,而且自动暴露为模型数据,在视图页面展示时使用
@RequestMapping("/register")
public String register(@ModelAttribute("user") UserForm user) {
if("zhangsan".equals(user.getUname()) && "123456".equals(user.getUpass())){
logger.info("成功");
return "login";//注册成功,跳转到login.jsp
}else{
logger.info("失败");
//在register.jsp 页面上使用EL表达式取出 model 的 uname 值
//@ModelAttribute("user") 与 model.addAttribute("user",user) 的功能相同
return "register";//返回register.jsp
}
}
重定向
重定向 是将用户从当前处理请求定向到另一个视图 (例如JSP) 或处理请求,以前的请求(Request)中存放的信息全部失效,并进入到一个新的request作用域
重定向过程:
客户浏览器发送http请求,Web服务器接受后发送302状态码响应及对应新的location给客户浏览器,客户浏览器发现是302响应,则自动再发送一个新的http请求,请求URL是新的location地址,服务器根据此请求寻找资源并发送给可以。
在这里location可以重定向到任意URL,即然是浏览器重新发送了请求,那么就没什么request传递的概念了。在客户浏览器的地址栏中显示的是其重定向的路径,客户可以观察到地址的变化。重定向行为是浏览器做了至少两次的访问请求
重定向是客户端行为
转发
是将用户对当前处理的请求转发给另一个视图或处理请求,以前request中存放的信息不回失效
转发是服务器行为
转发过程:
客户浏览器发送http请求,Web服务器接受此请求,调用内部的一个方法在容器内部完成请求处理和转发动作,将目标资源发送给客户;
在这里转发的路径必须使同一个Web容器下的URL,其不能转向到其他的Web路径上,中间传递的是自己的容器内的request。在客户浏览器的地址栏中显示的仍然是其第一次访问的路径,也就是说客户是感觉不到服务器做了转发的。转发行为是浏览器只做了一次访问请求
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/index")
public class IndexController {
@RequestMapping("/login")
public String login(){
//转发到一个请求方法(同一个控制器类中可以省略/index/)
return "forward:/index/isLogin";
}
@RequestMapping("/isLogin")
public String islogin(){
//重定向到一个请求方法
return "redirect:/index/isRegister";
}
@RequestMapping("/isRegister")
public String isRegister(){
//转发到一个视图,return默认是转发实现
return "register";
}
}
应用 @Autowired 进行依赖注入
需要接口,和 接口实现 辅助完成
@ModelAttribute
- 绑定请求参数到实体对象(表单的命令对象)
- 注解一个非请求处理方法
被@ModelAttribute注解的方法将在每次调用该控制器类的请求处理方法前被调用。这种特性可以用来控制登录权限,当然控制登录权限有很多,例如:拦截器
,过滤器