MVC架构
MVC是一种著名的设计模式,特别是在 Web应用程序领域。模式全都是关于将包含业务数据的模块与显示模块的视图解耦的。
一个层次的重定向几乎可以解决计算机业中的所有问题。确实,在模型和视图之间引入重定向层可以解决问题。
此重定向层是控制器。控制器将接收请求,执行更新模型的操作,然后通知视图关于模型更改的消息。
MVC:模式的步骤:
(1)浏览器发送请求到控制器(这里要知道控制器的作用)
(2)控制器不处理请求的具体业务,而是交给模型层来处理接着去访问数据库
(3)模型层将处理好的结果返回给控制层
(4)控制层将逻辑视图响应给浏览器(浏览器显示的是渲染过的视图)
MVC(Model-View-Controller)三元组的概念:
1、Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或 JavaBean 组件(包含数据和行为), 不过现在一般都分离开来:Value Object(数据) 和 服务层(行为)。 也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。
2、领域模型javaBean组件等价于域模型层 + 业务逻辑层 + 持久层(M)
3、View(视图):负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西(V)。
4、Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图(C)
springmvc对工作原理解释说明:
(1)用户发送请求到springmvc框架提供的DispatcherServlet 这个前端控制器
(2)前端控制器会去找处理器映射器(HandlerMapping),处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet 。
(3)根据处理器映射器返回的处理器,DispatcherServlet 会找“合适”的处理器适配器(HandlerAdapter)
(4)处理器适配器HandlerAdpater会去执行处理器(Handler开发的时候会被叫成Controller也叫后端控制器) 执行之前会有转换器、数据绑定、校验器等等完成上面这些才会去正在执行Handler
(5)后端控制器Handler执行完成之后返回一个ModelAndView对象
(6)处理器适配器HandlerAdpater会将这个ModelAndView返回前端控制器DispatcherServlet。前端控制器会将ModelAndView对象交给视图解析器ViewResolver。
(7)视图解析器ViewResolver解析ModelAndView对象之后返回逻辑视图。
(8)前端控制器DispatcherServlet对逻辑视图进行渲染(数据填充)之后返回真正的物理View并响应给浏览器。
servlet拦截方式:
(1)拦截固定后缀的url,比如设置为 *.do、*.action, 例如:/user/add.action,
此方法最简单,不会导致静态资源(jpg,js,css)被拦截。
(2)拦截所有,设置为/,例如:/user/add /user/add.action
此方法可以实现REST风格的url,很多互联网类型的应用使用这种方式。但是此方法会导致静态文件(jpg,js,css)被拦截后不能正常显示。需要特殊处理。
(3)拦截所有,设置为/*,此设置方法错误,因为请求到Action,当action转到jsp时再次被拦截,提示不能根据jsp路径mapping成功。
springmvc.xml的配置文件解释说明
HandlerMapper处理器映射器
根据bean的name进行查找Handler处理器,将请求的url配置在bean的name中
这是一个默认的映射处理器,即使不配置,那么也是默认就是这个
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>
HandlerAdapter适配器
注意:这个适配器不是必须配置的,这是默认的、他在servlet容器已启动就被加载
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
注解配置文件的解释:
springmvc注解说明:
<!-- 注解扫描!!!-->
<context:component-scan base-package="com.ecc"/>
<!-- 注解映射器
说明 :对类中标记@ResquestMapping的方法进行映射,根据ResquestMapping定义的url匹配ResquestMapping标记的方法,
匹配成功返回HandlerMethod对象给前端控制器,HandlerMethod对象中封装url对应的方法Method -->
<!--
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
-->
<!-- 注解适配器
说明:注解式处理器适配器,对标记@ResquestMapping的方法进行适配。 -->
<!--
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
-->
注意,注意,注意:
springmvc使用<mvc:annotation-driven>
自动加载RequestMappingHandlerMapping和RequestMappingHandlerAdapter,
可用在springmvc.xml配置文件中使用<mvc:annotation-driven>替代注解处理器和适配器的配置。
<!-- 配置视图解析器 -->
<!-- InternalResourceViewResolver:支持JSP视图解析 -->
<!-- viewClass:JstlView表示JSP模板页面需要使用JSTL标签库,所以classpath中必须包含jstl的相关jar包; -->
<!-- prefix 和suffix:查找视图页面的前缀和后缀,最终视图的址为: 前缀+逻辑视图名+后缀,
逻辑视图名需要在controller中返回ModelAndView指定,比如逻辑视图名为hello,
则最终返回的jsp视图地址 "WEB-INF/view/hello.jsp" -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/view/"/>
<property name="suffix" value=".jsp"/>
</bean>
web.xml的配置:
<!-- DispatcherServlet:前端控制器配置前端控制器servlet -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--加载前端控制器配置文件,上下文配置位置-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- 表示随WEB服务器启动 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
controller层的示例:
@Controller
@RequestMapping("/")
public class HelloController {
@RequestMapping("hello")
public String helloSpringmvc(){
return "hello";
}
}
controller方法返回值
(1)返回ModelAndView
controller方法中定义ModelAndView对象并返回,对象中可添加model数据、指定view。
(2)返回void
在controller方法形参上可以定义request和response,使用request或response指定响应结果:
使用request转向页面,如下:
request.getRequestDispatcher("页面路径").forward(request, response);
也可以通过response页面重定向:
response.sendRedirect("url")
也可以通过response指定响应结果,例如响应json数据如下:
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串");
(3)返回字符串
逻辑视图名
controller方法返回字符串可以指定逻辑视图名,通过视图解析器解析为物理视图地址。
//指定逻辑视图名,经过视图解析器解析为jsp物理路径:/WEB-INF/view/item/editItem.jsp
return "item/editItem";
Redirect重定向
Contrller方法返回结果重定向到一个url地址,如下商品修改提交后重定向到商品查询方法,参数无法带到商品查询方法中。
//重定向到queryItem.action地址,request无法带过去
eg:重定向demo
return "redirect:queryItem.action";
redirect方式相当于“response.sendRedirect()”,转发后浏览器的地址栏变为转发后的地址,
因为转发即执行了一个新的request和response。
由于新发起一个request原来的参数在转发时就不能传递到下一个url,如果要传参数可以/item/queryItem.action后边加参数, 如下:
eg:重定向传参
/item/queryItem?...&…..
forward转发
controller方法执行后继续执行另一个controller方法,如下商品修改提交后转向到商品修改页面,修改商品的id参数可以带到商品修改方法中。
//结果转发到editItem.action,request可以带过去
return "forward:editItem.action";
forward方式相当于“request.getRequestDispatcher().forward(request,response)”,转发后浏览器地址栏还是原来的地址。
转发并没有执行新的request和response,而是和转发前的请求共用一个request和response,所以转发前请求的参数在转发后仍然可以读取到。