MVC三层结构 (M->C->V)
requset–>中心总控制器(DispatcherServlet)
中心控制器接收到用户请求后:将请求转发到HandlerMapping (方法映射/方法索引)
I. M 即HandlerMapping(方法映射)
找到处理请求对应方法controller
的路径
- 根据请求的地址遍历注解 找到
controller
路径,返回给总控制器 - 总控制器根据路径,将请求参数转发给对应的
HandlerAdapter(内容提供者)
中对应的controller(控制器)
II.C 即Controller(控制器)和HandlerAdapter(内容适配器)
对请求的数据进行处理并告知需要使用的view视图
- 处理请求和数据,并将处理好的请求和数据封装到
ModelAndView中(模型和视图)
类似于安卓中的ViewModel
- 将封装好的
ModelAndView(视图和内容)
,返回给HandlerAdapter(内容适配器)
HandlerAdapter(内容提供者)
把处理好的数据返回给总控制器,并由总控制器传递给ViewResolver(视图解析者)
III.V 即ViewResolver(视图解析者)和View(视图层)
解析视图并渲染返回给中心总控制器(DispatcherServlet)
- 解析
ModelAndView
中的数据和视图信息 - 将解析好的信息返回给总控制器
- 调用
View
渲染JSP视图
Response–>中心总控制器(DispatcherServlet)
将视图和数据响应给请求的用户
可以看出:
- 中心控制器相互联系着每一个逻辑处理,因此冠名
中心总控制器(DispatcherServlet)
当之无愧 - MVC三层结构在数据处理中实际上是按照
M-->C-->V
的顺序。
如图所示:
注:Controller方法补充说明:
1. 构造器方法
- 定义公用构造器,参数为定义过Spring注解的对象
- spring框架会在启动控制器时,将对应对象生成并注入到构造器
- 通过构造器将地址赋值给当前类中的对象
实例(以创建一个登录服务为例,相关服务引用的代码见最后,下同):
private final UserService service;
public LoginController(UserService service) {
this.service = service;
}
2.@Autowired
- 可以替代构造器方法
- 直接在声明的对象上使用注解,控制器被创建时会自动注入
- 此方法不推荐使用
实例(同样以创建一个登录服务为例):
@Autowired
private final UserInfoService service;
3.ModelAndView 模型和视图
setViewName()
设置对应视图的名称,与视图层文件名一一对应- 不需要后缀,直接写名称是转发
- 加上前缀
redirect:
为302重定向
addObject(key,obj)
像解析器中传入以键值对方式的对象
实例(以登录服务为例):
@RequestMapping(path = "/dologin")
public ModelAndView login(HttpServletRequest request, HttpServletResponse response, User user){
User loginUser = service.login(user);
ModelAndView modelAndView=new ModelAndView();
if(loginUser!=null){
request.getSession().setAttribute("user",loginUser);
/* 不写 redirect: 表示请求转发 带上表示302重定向*/
modelAndView.setViewName("/hello");
}else {
try {
response.getWriter().write("<script>alert('登录失败');history.go(-1)</script>");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
return modelAndView;
}
4. ModelAndView 自动拆装
- 将返回对象设置为
String
,视图名,直接返回为字符串 - 添加数据等直接使用
request
的域对象即可 例如addObject(key,obj)
对应request.setAttribute(key,obj)
实例(同样以登录服务为例):
@RequestMapping(path = "/dologin")
public String login(HttpServletRequest request, HttpServletResponse response, User user){
User loginUser = service.login(user);
if(loginUser!=null){
request.getSession().setAttribute("user",loginUser);
/* 不写 redirect: 表示请求转发 带上表示302重定向*/
return "redirect:/hello";
}else {
try {
response.getWriter().write("<script>alert('登录失败');history.go(-1)</script>");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
附:Service和Bean代码
- 在接口的实现类中使用注解
@Service
可以在控制层自动生成接口对象(参见上文Controller方法补充说明)
@Service
public class UserInfoServiceImpl implements UserService {
//这里是实现类
}
- 在javaBean对象上添加注解
@Component
,Spring会自动注入对象(参见上文Controller方法补充说明)
@Component
public class User{
//javaBean内容
}
- 在配置文件中配置
context:component-scan
和包名,Spring会自动扫描该包下带注解的对象
<context:component-scan base-package="cn.hll520.lpc">