1、MVC设计模式(这里讲的是b/s情况下的模式)
2、springMVC框架与spring的关系
springMVC只是spring框架的一个模块;如下图是spring整个框架的内容:
3、springMVC的框架结构原理
1、 用户发起请求,请求到DispatcherServlet前端控制器
DispatcherServlet(中央调度),负责request和response,负责调用处理器映射器查找Handler,负责调用处理器适配器执行Handler,有了前端控制器降低了各各组件之间的耦合性,系统扩展性提高。
2、 DispatcherServlet前端控制器请求处理器映射器HandlerMapping查找Handler
根据用户请求的url,根据一定的规则去查找(比如:xml配置,注解)
3、 HandlerMapping处理器映射器将Handler返回给前端控制器
4、 DispatcherServlet前端控制器调用HandlerAdapter处理器适配器执行Handler
程序员编写的Handler是按照适配器要求的规则去执行Handler
5、 HandlerAdapter处理器适配器执行Handler
适配器按照一定规则去执行Handler
6、 Handler执行完成,返回ModelAndView
ModelAndView是springmvc的封装对象,将model和view封装在一起。
7、 HandlerAdapter处理器适配器将ModelAndView返回给前端 控制器
8、 前端控制器调用视图解析器,进行视图解析,解析完成给前端控制器返回View
View是springmvc的封装对象,是一个接口,实现类包括jspview,pdfview。。。。
9、 前端控制器调用view进行视图渲染
将模型数据填充到view(将model数据填充到request)响应给用户
10、前端控制器响应给用户。
4、这里详细的说明一下springmvc平常要了解的(开发是不常用的,一般都是用注解)三大组件:1、处理器映射器常用的两个是(在注解开发中就是指的requestMapping注解):
<!-- 处理器映射器 根据url匹配bean的name 处理器映射器实现了HandlerMapping接口 -->
<bean
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
<!-- 简单url映射的处理器映射器 -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/hello1.action">hello_controller</prop>
<prop key="/hello2.action">hello_controller</prop>
<prop key="/hello3.action">hello_controller3</prop>
</props>
</property>
</bean>
对应的controller类的配置:
<!-- 配置action -->
<bean id="hello_controller" name="/helloworld.action" class="cn.itcast.springmvc.Hello" />
<!-- 配置action -->
<bean id="hello_controller3" class="cn.itcast.springmvc.Hello1" />
根据处理器映射器就可以找到对应的handler(函数)
package cn.itcast.springmvc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
/**
*
* <p>Title: Hello</p>
* <p>Description: 使用SimpleControllerHandlerAdapter适配器</p>
* <p>Company: www.itcast.com</p>
* @author
* @version 1.0
*/
public class Hello implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("message", "helloworld!!!!!!");
//响应到jsp的逻辑试图
//modelAndView.setViewName("/WEB-INF/jsp/hello.jsp");
return modelAndView;
}
}
2、了解两个处理器适配器(实际上就是我们在使用springmvc的controller注解)
<!-- 处理器适配器 实现了HandlerAdapter接口 action按照适配器要求开发 ,规则是实现Controller接口 -->
<bean
class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
<!-- 配置HttpRequestHandlerAdapter处理器适配器 -->
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter" />
使用不同的适配器在MVC的C层的类需要实现不同的接口
使用SimpleControllerHandlerAdapter适配器,就要使用SimpleControllerHandlerAdapter适配器的规则进行处理
/**
*
* <p>Title: Hello</p>
* <p>Description: 使用SimpleControllerHandlerAdapter适配器</p>
* <p>Company: www.itcast.com</p>
* @author
* @version 1.0
*/
public class Hello implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
ModelAndView modelAndView = new ModelAndView();
//下面的方法就相当于request.setAttribute("message", message);
modelAndView.addObject("message", "helloworld!!!!!!");
return modelAndView;
}
}
使用 使用HttpRequestHandlerAdapter适配器,就要使用HttpRequestHandlerAdapter适配器的规则进行处理
/**
*
* <p>Title: Hello1</p>
* <p>Description: 使用HttpRequestHandlerAdapter</p>
* <p>Company: www.itcast.com</p>
* @version 1.0
*/
public class Hello1 implements HttpRequestHandler {
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//向页面显示一行提示信息
String message = "hellworld1";
request.setAttribute("message", message);
//指定转向页面,使用request指定页面完整路径
request.getRequestDispatcher("/WEB-INF/jsp/hello.jsp").forward(request, response);
}
}
3、视图解析器
<!-- 视图解析器 解析jsp视图,默认使用jstl,要求classpath下有jstl的jar包 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 视图的前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 视图的后缀 -->
<property name="suffix" value=".jsp" />
</bean>
这样使用视图解析器,就可以在controller层直接使用逻辑视图名称进行页面的响应:
modelAndView.setViewName("hello");
这里可以参考git仓库资源中的源码: 点击打开链接
5、针对springMVC在平常的开发中注解使用如下:
1、@controller
标识该类为控制器类,@controller、@service、@repository分别对应了web应用三层架构的组件即控制器、服务接口、数据访问接口
2、 @RequestMapping
进行url映射,一个方法对应一个url,定义方法:在action方法上定义requestMapping
3、在平常的开发中会使用 根路径+子路径 来辨别action的URL
4、 URI模板模式映射
(使用url的模板式映射的思想是:让每一条资源数据都有唯一的一个URL路径)
5、请求方法限定
可以限定为get、post、或两者都可以
限定GET方法
@RequestMapping(method = RequestMethod.GET)
如果通过Post访问则报错:
HTTP Status 405 - Request method 'POST' not supported
例如:
@RequestMapping(value="/useredit/{userid}",method=RequestMethod.GET)
限定POST方法
@RequestMapping(method = RequestMethod.POST)
如果通过Post访问则报错:
HTTP Status 405 - Request method 'GET' not supported
GET和POST都可以
@RequestMapping(method={RequestMethod.GET,RequestMethod.POST})
6、springMVC的请求参数绑定(重点)
这里请求的参数绑定在handler处理器的形式参数中(Springmvc 通过参数解析器,将客户端请求的 key/value 解析成方法形参数);参数解析器:
Spring提供了很多参数解析器,将key/value的数据解析成形参,通过反射解析method中的参数(类型、名称),按照类型和名称规则解析形参;
属性编辑器:
将key/value转换成pojo中的属性
6.1 默认支持的参数类型
- HttpServletRequest
- 通过request对象获取请求信息
- HttpServletResponse
- 通过response处理响应信息
- HttpSession
- 通过session对象得到session中存放的对象
- Model
- 通过model向页面传递数据,如下:
- model.addAttribute("user",new User("李四"));
- model也可以通过modelMap或map将数据传到页面。
6.2 表单对象-简单数据类型
Action方法的形参数默认支持:string、int、double等简单类型,建议使用包装类型(可以设置null)。
注意:对于date类型的参数需要注册属性编辑器。
使用方法:
直接在形参上定义
也可以在pojo中通过属性传递简单类型
6.3表单对象-pojo类型
第一种,不需要封装目标bean
6.4 字符串数组绑定
6.5、 List绑定参数类型
页面向action传递复杂的批量数据,比如学生的成绩信息(课程名称、成绩)
页面定义:
Scores:包装对象中list属性的名称
Coursename:包装对象中list中pojo的属性名称。
Score:包装对象中list中pojo的属性名称。
如果上边下标相同的Coursename和Score设置在一个pojo中。
Action方法定义:
使用List<pojo>接收上边的接收,pojo中包括上边课程名称(coursename)和成绩(score)
6.6、 @RequestParam绑定单个请求参数
value:参数名字,即入参的请求参数名字,如value=“studentid”表示请求的参数区中的名字为studentid的参数的值将传入;
required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报400错误码;
defaultValue:默认值,表示如果请求中没有同名参数时的默认值
需求 :
学生查询方法中必须要有一个参数group(学生分组)
实现:
7、 springMVC中结果转发
Redirect:请求重定向
浏览器中地址栏的url通过Redirect变了,重新定义了一个request。
Action方法通过Redirect重定向到另一个方法,方法形参无法带到另一个方法。
定义方法:
//请求重定向
return "redirect:querystudent.action";
Forward:页面转发
浏览器中地址栏的url通过Forward不变,没有重新定义了一个request。
Action方法通过Forward转发到另一个方法,方法形参可以带到另一个方法。
定义方法:
//页面转发
return "forward:querystudent.action";
8、springMVC中 @RequestBody @ResponseBody注解实现json数据交互
Json数据在企业中使用好处:
Json在企业开发中已经作为通用的接口参数类型。
Json数据在页面(客户端)解析很方便。
Json定义:
var obj={”name”:”张三”,”age”:12}//key/value格式
Json数据解析:
obj.name
在处理器适配器上配置json的解析器,原因是处理器适配器处理handler
配置
<!--注解适配器 -->
<!-- <bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
json转换器
<property name="messageConverters">
<list>
<bean
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
</list>
</property>
</bean> -->
controller层
/**
*
* <p>Title: JsonAction</p>
* <p>Description: json转换测试</p>
* <p>Company: www.itcast.com</p>
* @author 传智.燕青
* @date 2014-12-15下午5:38:43
* @version 1.0
*/
@Controller
public class JsonAction {
//请求json响应json
@RequestMapping("/requestJson")
public @ResponseBody Student requestJson(@RequestBody Student student)throws Exception{
System.out.println(student);
return student;
}
//请求key/value响应json
@RequestMapping("/responseJson")
public @ResponseBody Student responseJson(Student student)throws Exception{
System.out.println(student);
return student;
}
}
9、springMVC的拦截器
拦截器是针对handlerMapping的拦截器,由handlerMapping查找Handler后,将拦截器返回给前端控制器(DispatcherServlet)。
间接配置全局拦截器:让springmvc框架自动向每个handlerMapping中注册拦截器
<!--拦截器 -->
<mvc:interceptors>
<!--多个拦截器,顺序执行 -->
<!-- <mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="cn.itcast.springmvc.interceptor.HandlerInterceptor1"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="cn.itcast.springmvc.interceptor.HandlerInterceptor2"></bean>
</mvc:interceptor> -->
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="cn.itcast.springmvc.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
定义拦截器
实现HandlerInterceptor接口。
public class HandlerInterceptor1 implements HandlerInterceptor {
//handler,springmvc根据url找到Handler(只有一个方法)
//执行时机:进入Handler方法之前执行,如果返回false表示拦截,如果返回true表示放行
//使用场景:用于用户身份校验,用户权限拦截校验
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
System.out.println("HandlerInterceptor1..preHandle");
return false;
}
//执行时机:进入Handler方法之后 ,在返回modelAndView之前
//使用场景:使用modelAndView,向页面传递通用数据,使用统一的view
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("HandlerInterceptor1..postHandle");
}
//执行时机:Handler方法执行完成,(modelAndView已经返回)
//使用场景:统一异常处理,统一记录系统日志,用于action方法执行监控(在preHandle记录一个时间点,在afterCompletion记录执行结束时间点,将结束时间点减去开始执行时间点,得到执行时长)
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("HandlerInterceptor1..afterCompletion");
}
10、springmvc驱动
<!--注解映射器 -->
<!-- <bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" /> -->
<!--注解适配器 -->
<!-- <bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
json转换器
<property name="messageConverters">
<list>
<bean
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
</list>
</property>
</bean> -->
<!-- 使用<mvc:annotation-driven />替换上边定义的处理器映射器和适配器 并且默认是支持@RequestBody @ResponseBody这两个注解的--> <mvc:annotation-driven />
参考代码案例:
点击打开链接