文章目录
1. SpirngMVC
1.1 概述
SpringMVC它是一种基于Java实现的MVC设计模型的请求驱动类型的轻量级Web框架.
它是通过一套注解,让一个简单的pojo类成为处理请求的控制器,基于pojo类中的方法,
一个方法就是之前的一个Servlet,无需实现任何接口,同时支持RESTful风格编程的请求.
本质就是一个Servlet
MVC : Model View Controller
Model : 主要用于数据的封装,=>pojo=>JavaBean
View : 解析jsp,生成html页面=>jsp
Controller : 控制器,用于服务器和客户端交互 一个Servlet
请求驱动类型 :
请求-相应类型
1.2 优势
1. 清晰的角色划分,分工明确
2. SpringMVC可以和Spring框架实现无缝衔接
3. 支持RESTful风格,简单的文件上传
4. 约定大于配置的契约式编程支持
5. 基于注解的零配置支持
6. 功能强大的数据验证,格式,绑定机制等等
1.3 快速入门
- 导包
Spring核心包,日志包,aop,web+webmvc+jstl,servlet,jsp - 创建数据库和表,创建controller包和类,在类上添加@Controller注解
- 创建springMVC配置文件
- 在web.xml配置前端控制器
//假设已经从数据库查询到信息
List<Role> list = new ArrayList<>();
list.add(new Role(1,"学生","学习", new Date()));
list.add(new Role(2,"老师","教课", new Date()));
list.add(new Role(3,"副教授","研究", new Date()));
list.add(new Role(4,"教授","研究", new Date()));
list.add(new Role(5,"院士","研究", new Date()));
list.add(new Role(6,"国士","荣誉,偶像", new Date()));
ModelAndView modelAndView = new ModelAndView();
//使用ModelAndView封装数据
modelAndView.addObject("list",list);
//使用ModelAndView跳转页面
modelAndView.setViewName("/WEB-INF/view/role/roleList.jsp");
return modelAndView;
}
}
配置文件applicationContext-mvc.xml
<context:component-scan base-package="com.zy"/>
web.xml
<!--配置前端控制器 , 与servlet的一样-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--加载配置文件-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext-mvc.xml</param-value>
</init-param>
<!--加载时机,数字越小越先加载-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<!--建议使用扩展名进行配置-->
<url-pattern>*.action</url-pattern>
</servlet-mapping>
1.4 SpringMVC架构
-
DispatcherServlet 前端控制器
它是整个流程的控制中心,由它来调用其他组件处理用户的请求
作用 : 降低组件之间的耦合性 -
HandlerMapping 处理器映射器
负责根据用户url请i去找到Handler(处理器)
springMVC提供了不同的映射器实现机制 : 配置文件方式,实现接口方式,注解方式等
@RequestMapping(),就是采用注解方式,也是目前最流行的方式 -
Handler处理器
handler是继前端控制器的后端控制器,在前端控制器调配下Handler对具体的用户进行请求处理 -
HandlerAdapter 处理器适配器
通过HandlerAdapter对处理器进行解析执行. 主要是一种适配器模式的匹配 -
ViewResovler 视图解析器
将处理结果生成View视图 -
View组件
springMVC提供了很多个View视图,如jstlView,freemarkView,pdfView等,对于java开发来说,最常用的是jspView -
说明
在springMVC各个组件中,处理器适配器, 处理器映射器, 视图解析器,我们称之为springMVC的三大组件. 可以认为一个中心三个基本点. 需要用户开发的组件有Handler和View
执行流程
- 项目启动,加载web.xml,开始加载DispatcherSerlvet(前端控制器),读取配置文件,创建spring容器,生成DispatcherServlet对象,存储在Spring容器中;通过组件扫描,把controller扫进spring容器中.
- 当客户端请求发送过来时,首先经过前端控制器,前端控制器根据请求的资源映射调用处理器映射器组件HandleMapping,匹配url,当匹配到url之后,把结果返回给前端控制器.
- 前端控制器收到结果后调用处理器适配器,来匹配具体是哪一个方法,当方法被匹配到后,如果方法上有参数,调用HttpMessageConverter,进行数据格式校验、数据封装。数据校验之后,开始把数据绑定到参数上,调用处理器来执行具体的方法业务内容.
- 处理器处理完,把结果返回给处理器你适配器,处理器适配器再把结果(ModelAndView)返回给前端控制器.
- 前端控制器根据结果来调用视图解析器,同时把view视图(String字符串表示的)传输给视图解析器ViewResovler视图解析器根据视图匹配服务器中到底哪一个视图(JSP视图)找到之后,把视图再返回给前端控制器.
- 前端控制器根据视图调用视图组件View,同时把视图信息传输给View组件,View组件开始解析,把逻辑视图转换成为物理视图,生成html页面,返回给前端控制器.前端控制器把html静态页面和model数据一块通过响应的方式发送给客户端.
1.5 相关组件的配置
为什么前面没有配置相关组件也可以正常使用呢?
因为在spring-webmvc的jar中有一个DispacherServlet.properties配置文件,当我们没有配置组件时,它会默认使用该配置文件的组件
- 配置处理器映射器,处理器适配器
<!--配置处理器映射器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<!--处理器映射器-->
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>
- 注解驱动
在springMVC中提供了注解驱动加载处理器映射器和处理器适配器,所以上面的两行配置可以注释
<!--注解驱动 涵盖处理器映射器和处理器适配器-->
<mvc:annotation-driven/>
- 视图解析器
在这里主要用来做资源跳转
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"/><!--前缀-->
<property name="suffix" value=".jsp"/><!--后缀-->
</bean>
- 静态资源放行
如果前端控制器在中采用缺省配置(/),就意味着要拦截当前的静态资源,需要开发者自己配置
如果应用当中需要使用静态资源,此时就需要静态资源放行
注意 : 此处有缓存,需要先清除浏览器的Cookie
- 方式一
前端控制器本质就是Servlet, 在tomcat服务器内部配置对缺省配置有单独的处理,它采用的是静态资源放行.
想要使用tomcat默认对缺省配置的处理,需要开启tomcat的缺省配置
<!--方式一 采用tomcat默认的处理方式 开启tomcat的缺省配置-->
<mvc:default-servlet-handler/>
2. SSM
开发步骤
- 导包
- 在resources资源文件夹下面新建两个目录。一个是spring(Spring的核心配置),一个是mybatis(核心配置)
- 把db.properties文件和log4j.properties文件导入到resources目录下。
- 在spring目录下创建springmvc.xml文件
设置处理器映射器和处理器适配器的注解驱动
开启扫描controller组件
配置视图解析器 添加前后缀
<!--开启注解驱动 配置 处理器映射器和处理器适配器-->
<mvc:annotation-driven/>
<!--开启扫描controller组件-->
<context:component-scan base-package="com.zy.web.controller"/>
<!--配置视图解析器 添加前后缀-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--静态资源放行配置-->
<!-- <mvc:default-servlet-handler/>--
- 在spring目录下创建applicationContext-dao.xml
2.1参数绑定
-
@RequestParam注解使用
请求参数绑定说明
绑定机制:
1. 表单提交数据都是以key-value的方式
2. springMVC绑定过程是把表单提交的参数,作为控制器中方法的参数进行绑定的
3. 要求提交的表单的name属性和参数名称必须一致 -
name属性 : 映射表单中提交的参数名称
-
required属性
默认为true,一旦使用该注解,就必须指定name属性 -
defaultValue属性
设定方法参数的默认值,如果表单中请求参数没有传输具体值,那么此时方法参数使用配置的默认值
public ModelAndView test03RequestParam(@RequestParam(name = "id")Integer rid){}
- 中文乱码
在web.xml
<!--设置编码格式-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
- 参数绑定pojo
如果表单中的name属性名称与pojo的属性名称一致,可以使用pojo进行接收表单数据 - 参数绑定pojo包装类
OGNL表达式
如果表单中的name属性名称和包装类中的属性名称产生映射,则可以采用OGNL表达式的方式进行映射
格式 :
包装类的属性名称.pojo中的属性名称 就可以实现name属性值往pojo包装类装配 - 数组类型参数绑定
如果表单中的name属性只有多个,此时可以在pojo类中定义为数组类型,让它们产生关联映射 - 集合类型参数绑定
当表单中需要提交多条记录时,可以采用多记录提交
实现方式 : 在pojo类中定义集合属性,请求方法参数可以直接使用pojo
每一行都是一个对象,每一列都是pojo的属性
仅仅适用于pojo不能直接把值传入相应的方法参数上 - 格式类型转换(日期)
只有yyyy/MM/dd的日期格式才能往Date里装配,否则报参数非法
表达提交的数据基本都是字符串类型.后台接收的时候,如果有整形类型Integer,此时数据也可以封装上去,因为spring框架内部提供了很多默认的数据类型转换类
如果要自定义转换类型,可以实现Converter接口,重写conver()方法
<!--自定义日期格式转换器-->
<bean class="org.springframework.format.support.FormattingConversionServiceFactoryBean" id="conversionService">
<property name="converters" >
<list>
<bean class="com.converter.StringToDate"/>
</list>
</property>
</bean>
<!--开启注解驱动 配置 处理器映射器和处理器适配器-->
<mvc:annotation-driven conversion-service="conversionService"/>
@DateTimeFormat()
可以在pojo的日期属性上打上该注解
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date r_rTime;
2.2 @RequestMapping
- 多个路径匹配
//多个路径映射
@RequestMapping(path = {"/test05","/test055"})
public String test05() {
return "role/addRole";
}
- 窄化路径
在类上打上该注解,写上公共的资源路径,以后该类只接受**/role/**的请求
@RequestMapping("/role")
- 限定请求方法
可以通过method属性限定请求的方式,类型是RequestMethod
一般使用GET或POST
@RequestMapping(path = {"/test05","/test055"},method = {RequestMethod.GET,RequestMethod.POST})
还有另一种方法: 不使用RequestMapping注解,用其他注解
@GetMapping
@PostMapping
@DeleteMapping
@PutMapping
2.3 controller的方法的返回值
- ModelAndView
返回数据和视图,内部封装的数据实现的原理,是使用了servlet中的Request对象,也就是说数据实质上存进了request域对象中,可以使用addobject()传输数据,使用setViewName()方法指定视图地址
@RequestMapping("/roleList.action")
public ModelAndView test() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("/role/roleList");
return modelAndView;
}
- void空返回值
如果返回值是void,那就不需要指定视图地址,即无需跳转页面.
void的空返回值主要用于Ajax功能,Ajax只需要返回数据,不需要指定视图 - String字符串返回值
如果方法的返回值为String,相当于modelAndView.setViewName("/role/roleList");
本质就是指定的视图地址,可以搭配视图解析器使用(前后缀)
@RequestMapping("/test055")
public String test05(Model model) {
model.addAttribute("list",lists)
return "role/addRole";
}
假设所需要跳转的jsp页面不在视图解析器的范围,则需要进行内部转发或重定向
return "forward:/admin.jsp";//内部转发
return "redirect:/admin.jsp"
按以前的说法重定向是需要拼接虚拟目录的request.getContextPath(),但是在这里不需要,springMVC的组件会自动匹配
重定向不可以访问WEB-INF下的资源,内部转发可以访问
重定向无法传输Model的数据,本质是一个request对象
2.3 全局异常处理器
- 开发步骤
(1). 定义一个异常处理类,实现HandlerExceptionResolver接口,重写抽象方法
(2). 在xml配置文件中配置
public class GlobalExceptionsHandler implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("friend");
modelAndView.addObject("o",o);
modelAndView.addObject("e",e);
return modelAndView;
}
}
<bean class="com.exception.GlobalExceptionsHandler"/>
2.4 文件上传
@RequestMapping("/uploadFile.action")
public String fileUpload(String username, MultipartFile photoFile) throws IOException {
//文件重命名
String filename = photoFile.getOriginalFilename();
String fileNewName = UUID.randomUUID().toString()+System.currentTimeMillis()+filename;
//mvc实现上传
photoFile.transferTo(new File("D:\\picture\\新建文件夹\\"+fileNewName));
return null;
}
<!--配置文件上传解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize">
<value>1048576</value>
</property>
</bean>
2.5 RESTful编程风格的支持
它是一个资源定位和资源操作的风格.它不是标准也不是协议,只是一种风格.
RESTful风格请求使用: "url+请求方式",表示一次请求的目的
代码更简洁,更有层次感,更易于实现**缓存机制**
- 需要借助注解@PathVariable
- 在@RequestMapping注解中的path属性值格式${变量名}
//http://localhost:8080/ParameterBinding/department/1.action
@RequestMapping("/department/{id}.action")
public String testRESTful(@PathVariable Integer id) {
System.out.println(id);
return null;
}
2.6 拦截器
springMVC的处理器拦截功能类似于Servlet规范中的过滤器Filter,用于对处理器Handler进行预处理和后处理
区别就是和Filter加载时机不一样. 过滤器Filter在前端控制器前加载,拦截器在前端控制器之后加载
- 开发步骤
(1) 创建一个类实现HandlerInterceptor接口. 重写该接口的三个方法
preHandle
预处理回调方法,实现处理器的预处理,在客户端请求到达控制器之前进行拦截(登录校验或权限验证)
该方法的返回值为boolean,如果为true,放行,如果为false,则请求到不了前端控制器.可以使用内部转发重新指定一个界面
posHandle
后处理回调方法. 控制器中代码已经加载完毕(在组装ModelAndView对象之前),此时可以在该方法中定义ModelAndView中的数据. 指定Model中传输的数据,指定跳转的视图地址,也可以把它置为null.
afterCompletion
在整个方法请求结束后, 组装完ModelAndView, 即将传输给前端控制器之前拦截.
(2) 把自定义拦截器交给spring容器管理
<!--配置自定义拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--映射后端请求的资源路径 **代表拦截所有 -->
<mvc:mapping path="/**"/>
<bean class="com.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>