springMVC的核心就是DispatcherServlet程序,所有的请求都是先进入这个Servlet对象。 官方的图:
使用:
(1)准备log 和 spring的xml配置文件
(2)在web.xml中配置dispatchServlet
方式一:
<!-- The front controller of this Spring Web application, responsible for handling all application requests -->
<servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!-- 给Spring的核心组件,告诉它,springMVC的配置文件在哪 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- load-on-startup表示当前这个Servlet程序,当Web服务器一启动的时候,就创建和初始化 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Map all requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<!-- / 拦截全部请求。/支持restful风格 -->
<url-pattern>/</url-pattern>
</servlet-mapping>
方式二:
(1)在web.xml配置文件所在的目录下创建一个springMVC配置文件
(2)这个配置文件的命名规则:前段控制器servlet的名称+"-servlet.xml"
(3)@Controller的类中方法加 @RequestMapping注解 表示SpringMVC中注册一个控制器 return默认执行转发
**
springMVC中的各种注解 **
**RequestMapping注解**
1 RequestMapping的value属性: /表示到工程名 映射到代码的webcontent目录
params属性: 当前请求地址必须要有的参数
params="username" 表示 请求地址必须带有username参数
params="username=abc" 表示 请求参数中必须要有username,而且值还必须是abc
params="username!=abc" 表示 1、请求参数中不能有username参数。2、有username参数,但值不能等于abc
params="!username" 表示 请求地址不能带有username参数
params= {"username!=abc","!password"} params可以有多个值,每个值之间是&&关系,表示要求:( 请求地址中不能有username参数 || username参数值不能等于 abc && 不能有password参数 )
headers属性:可以限定请求头中的内容 ,例如可以限定某个版本的浏览器
method属性:method=RequestMethod.GET或者method=RequestMethod.POST 表示当前请求必须是GET或者POST才可以访问
2@RequestMapping注解写在类上面表示这是一个controller控制器类,访问地址是:http://ip:port/工程名/Controller地址/方法上的地址
3通配符在@RequestMapping中的使用:
1绝对匹配:就是上面所写的方式
2?问号:表示一个任意字符
3*星号:可以匹配任意多个字符
当一个路径同时匹配多个规则的时候,调用方法的优先顺序是:
绝对匹配--->>>>?问号匹配---->>>>*星号匹配
4/?匹配一层目录并且只有一个字符 /*匹配一层目录多个字符 /**匹配多层目录并且有多个字符
## Controller类方法自动注入原生api##
可以注入HttpServletRequest HttpSession HttpServletResponse等类
## 普通参数入参##
1可以通过注入request对象进而获取参数 但不推荐这个
2直接在方法上设置参数就可以获取了!~(要求参数名和方法的参数名一样)
用数组接收多个值
@RequestParam (value="aaa",required=false,defaultValue="ccc" )入参:
springmvc会自动将请求过来的aaa参数注入进去, required=false意味着可以不传递该参数默认是null,defaultValue是没有传递值的时候修改的默认值
## @RequestHeader获取请求头入参 ##
@RequestHeader(value = "User-Agent") String userAgent,@RequestHeader(value = "Host") String host
上面是方法的参数,可以注入请求头User-Agent Host等的值
## @CookieValue获取Cookie值入参 ##
@CookieValue(value = "JSESSIONID") String jsessionid 可以注入cookie中的JSESSIONID
## 注入一个pojo对象类型的参数 ##
直接在方法参数上写上你的对象
## 注入及联对象(对象中包含对象)的参数 ##
表单写的参数就是 pojo1.pojo2 即可
**
视图解析器
**
<!-- 配置Spring的视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- prefix配置返回的视图的前缀 -->
<property name="prefix" value="/jsp/"/>
<!-- suffix配置返回的视图的后缀 -->
<property name="suffix" value=".jsp"/>
</bean>
**
springMVC的返回值
**
1默认情况下,返回return字符串。会经过视图解析器做字符串前后缀拼接的操作,然后做转发操作
2显示地转发:
// 在返回的字符串前面显示的标注 forward:表示显示的转发
// 使用显示的转发,视图解析器就不会工作了
绝对路径转发:return "forward:/jsp/return.jsp";
/ 表示绝对路径http://ip:port/工程名/
整个地址表示转发到http://ip:port/工程名/jsp/return.jsp
相对路径转发:return "forward:jsp/return.jsp";
当前浏览器地址栏地址是:http://localhost:8080/mvc_hello/p/return2
相对路径是参数当前浏览器地址栏的地址
得到的转发路径是:http://localhost:8080/mvc_hello/p/jsp/return.jsp
3显示地重定向:
return "redirect:/jsp/return.jsp"; 视图解析器不工作
也有绝对路径和相对路径 跟2中的规则一样
4返回ModdelAndView
// ModelAndView 也可以设置返回的资源
ModelAndView modelAndView = new ModelAndView();
// 设置视图名
modelAndView.setViewName("return");
return modelAndView;
默认的会经过试图解析器 同时也拥有显示转发和显示重定向 跟上面的一样
5返回void:
1会直接请求相应的jsp 一般我们禁止这么使用
2返回void的情况可以在参数中注入原生api然后进行相应代码操作
**
数据在域中的保存
**
Request对象中保存数据:
方式一:参数中加一个HttpServletRequest对象 然后在方法中保存数据到request中再转发 (不推荐)
方式二:参数中用Map或者Model或者ModelMap或者ModelAndView类型参数中存你的值 会自动保存到request中 推荐!~
在参数中写 Map Model ModelMap三个接收的都是同一个对象BindingAwareModelMap隐含模型
BindingAwareModelMap
* 继承了
* ExtendedModelMap -----实现>>>>>>Model接口
继承了
* ModelMap
继承了
* LinkedHashMap
继承了
* HashMap ------实现>>>>>> Map接口
Session中保存数据:
方式一:参数中加一个HttpSession对象 然后在方法中保存数据到Session中再转发 (不推荐)
ServletContext域中保存数据:
ServletContext不可以直接在参数中注入
方式一:@autowired注入
方式二:注入session 然后通过session.getServletContext()获取
**
@ModelAttribute注解
**
@ModelAttribute注解
@ModelAttribute这个注解可以标注在方法和参数上。
@ModelAttribute三个常见作用:
(1)被标注了@ModelAttribute的方法都会在Controller的目标方法之前执行。
(2)因为目标方法的参数(JavaBean对象)会先从隐含模型中获取值传入,所以我们可以在被标注了@ModelAttribute的方法参数写好隐含模型,并且在方法中赋值
(3)目标方法中,如果有对象参数(非原生API,是那些pojo对象),它会先按照参数的类型取类名,然后首字母小写,从隐含模型中取值注入。利用@ModelAttribute注解标注在参数上,参数值会按照指定的key从隐含模型中获取值。
**
springMVC乱码解决
**
POST请求乱码需要加一个filter过滤器:
<filter>
<!-- 配置Filter解决post请求乱码 -->
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<!-- 配置post请求进来的字符集 -->
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<!-- 配置响应的字符集 -->
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
GET请求乱码在tomcat的server.xml配置文件中做如下的配置:
**
springMVC中静态资源请求问题
**
因为springMVC中的前段控制器的拦截地址跟服务器的默认静态资源地址冲突了 所以会有静态资源请求无效的情况 需要做:
<!-- 配置Spring支持静态资源请求 -->
<mvc:default-servlet-handler/> 加了这个就只支持静态资源了!
<!-- 启用SpringMVC注解驱动 -->
<mvc:annotation-driven></mvc:annotation-driven>
这个是springMVC的标配,加了上面两个后就会先检查是否匹配注解的资源(controller)不匹配再找静态资源
**
Restful风格
一种软件设计风格
**
1、把请求参数加入到请求的资源地址中
2、原来的增,删,改,查。使用HTTP请求方式,POST、DELETE、PUT、GET分别一一对应。
GET请求 对应 查询
http://ip:port/工程名/book/1 HTTP请求GET 表示要查询id为1的图书
http://ip:port/工程名/book HTTP请求GET 表示查询全部的图书
POST请求 对应 添加
http://ip:port/工程名/book HTTP请求POST 表示要添加一个图书
PUT请求 对应 修改
http://ip:port/工程名/book/1 HTTP请求PUT 表示要修改id为1的图书信息
DELETE请求 对应 删除
http://ip:port/工程名/book/1 HTTP请求DELETE 表示要修改id为1的图书信息
使用:restful风格可以直接使用 controller中的@RequestMapping注解的method方法写好相应的请求类型
发起PUT请求和DELETE请求:
1、要有post请求的form标签
2、在form表单中,添加一个额外的隐藏域_method=”PUT”或_method=”DELETE”
3、在web.xml中配置一个Filter过滤器org.springframework.web.filter.HiddenHttpMethodFilter(注意,这个Filter一定要在处理乱码的Filter后面 否则会导致乱码的filter无效就会有乱码产生 )因为HiddenHttpMethodFilter在它的doFilterInternal方法中首先就用了request.getParameter方法来获取你的_method参数 我们知道post请求解决乱码的代码request.setCharacterEncoding需要在request.getParameter方法之后的~
在高版本的tomcat中跳转会有405问题:
方法一:修改jsp页面中的page指令isErrorPage="true",就可以访问了
<%@ page language="java" contentType="text/html; charset=UTF-8"
isErrorPage="true"
pageEncoding="UTF-8"%>
方法二:把转发改成为重定向redirect:/
@PathVariable 路径参数获取
requestMapping中value写成 .../{参数} 然后用@PathVariable将变量注入到你的参数中
第一种情况,一个path参数:
注意:@PathVariable标记的路径变量,不能为空,必须有值
第二种情况,多个path参数:一般不这么使用
**
SpringMVC的标签库
一般也不用
**
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>这是springmvc的标签
springMVC的标签form标签可以关联Request域中bean对象(类名首字母小写)
我们在隐含模型中保存的key值。也一定要跟form:form标签中的modelAttribute值对应上。
这是添加用户页面
<form:form action="${ pageContext.request.contextPath }/addPerson" method="delete"
modelAttribute="person">
name:<form:input path="name"/><br/>
<%-- birthDate:<form:input path="birthDate"/><br/> --%>birthDate有问题 因为没有相应的转换器能把String转换成java的Date类型 需要我们自定义~
email:<form:input path="email"/><br/>
salary:<form:input path="salary"/><br/>
<input type="submit" />
</form:form>
有挺多缺点且相对而言麻烦 好处就在于上述标签是会自动解析的
*******自定义类型转换器***********:
1自己代码实现的方式
(1)实现Converter接口
可以仿照java源码进行转换 成功的话就返回Date类型
(2)注入到ConversionService中
在容器中配置FormattingConversionServiceFactoryBean类 来创建ConversionService组件 用来类型转换
<bean>
<property name="converters">
<set>
<bean class="你的自定义converter类">
</set>
</property>
</bean>
(3)将ConversionService注入到WebDataBinder中
这个功能在springmvc注解驱动中进行操作:
<mvc:annotation-driven conversion-service="FormattingConversionServiceFactoryBean的id"></mvc:annotation-driven >
成功转换后就会通过bean的set方法注入你的date类型啦!
2注解方式:
在你的类里面的Date类型参数上写注解:@DateTimeFormat(pattern="string的格式")
**********利用Hibernate-Validate进行字段校验 并且进行错误信息的回显***********
@AssertTrue 用于boolean字段,该字段只能为true
@AssertFalse 该字段的值只能为false
@CreditCardNumber 对信用卡号进行一个大致的验证
@DecimalMax 只能小于或等于该值
@DecimalMin 只能大于或等于该值
@Digits(integer=,fraction=) 检查是否是一种数字的整数、分数,小数位数的数字
@Email 检查是否是一个有效的email地址
@Future 检查该字段的日期是否是属于将来的日期
@Length(min=,max=) 检查所属的字段的长度是否在min和max之间,只能用于字符串
@Max 该字段的值只能小于或等于该值
@Min 该字段的值只能大于或等于该值
@NotNull 不能为null
@NotBlank 不能为空,检查时会将空格忽略
@NotEmpty 不能为空,这里的空是指空字符串
@Null 检查该字段为空
@Past 检查该字段的日期是在过去
@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内
@Size(min=, max=) 检查该字段的size是否在min和max之间,可以是字符串、数组、集合、Map等
@URL(protocol=,host,port) 检查是否是一个有效的URL,如果提供了protocol,host等,则该URL还需满足提供的条件
(1)导入包后在bean对象上使用校验的注解
(2)在Controller的方法参数上,给需要验证的bean对象。添加验证注解@Valid,以及在验证对象后跟一个BindingResult 对象用于接收验证的错误信息 错误信息可以在controller方法中进行操作
(3)利用springMVC的注解进行错误信息的回显:<form:errors path="跟前面的name一样">
*********自定义错误信息*********
(1)写一个properties文件 键值对 键是下面的字段 值是你自定义语句
(2)配置ResourceBundleMessageSource的bean让spring容器去加载自定义的错误信息 id就是messageSource 属性property name=“basename” value=“1中properties配置文件无后缀名”
**************错误信息中占位符的作用**********
可以自动传递参数进来
{0}表示第一个传入的参数。 {0}第一个参数固定是验证的属性名 以此类推
**
文件上传
**
分四个步骤:
1、准备一个文件上传的表单
method="post" enctype="multipart/form-data"
2、导入文件上传需要的jar包
commons-fileupload-1.2.1.jar、commons-io-1.4.jar
3、配置文件上传解析器 CommonsMultipartResolver
<!-- 配置在SpringMVC中解决文件上传的协议的解析器
id 必须是multipartResolver (主要功能接口的首字母小写)
-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 配置字符集为UTF-8 -->
<property name="defaultEncoding" value="UTF-8" />
</bean>
4、配置Controller控制器的代码
用MultipartFile进行文件的接收
有isEmpty tansferto getOriginalFilename方法
**
相关注解
**
1 @ResponseBody 加了这个注解的意义就在于return之后返回的是json而不是跳转地址了
(1)、导入json相关的包到web工程中
jackson-annotations-2.1.5.jar
jackson-core-2.1.5.jar
jackson-databind-2.1.5.jar
(2)、编写一个请求的方式接收请求,并返回数据对象
(3)、在方法上添加注解@ResponseBody自动将返回值json化
2 @JsonFormat修改时间在json中的格式
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 加在Date属性上或者Date的get方法上
3@RequestBody接收POST请求中的请求体数据
将此注解加在String字符串前面即可
4使用HttpEntity参数获取请求头和请求体
接收的参数就是HttpEntity类对象即可
httpEntity.getHeaders() httpEntity.getBody()
5使用ResponseEntity返回值操作响应头和响应体 **************实现文件的下载****************~~
@RequestMapping(value = "/download")
public ResponseEntity<byte[]> download(HttpSession session) {
try {
ServletContext ctx = session.getServletContext(); //通过session 获取 ServletContext
InputStream is = ctx.getResourceAsStream("/WebContent目录下你的资源");
byte[] buffer;
buffer = new byte[is.available()];
is.read(buffer);
is.close();
String mimeType = ctx.getMimeType("/WebContent目录下你的资源");获取数据类型
// 响应头的目的就是告诉我返回的类型是什么 以及 如何操作我返回的东西
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("Content-Type", mimeType);
httpHeaders.add("Content-Disposition", "attachment; filename=下载的文件名.jpg");
// 第一个参数是你要返回的数据--我们要实现文件下载,就需要把下载的文件字节内容都放body中
// 第二个参数是 响应头
// 第三个参数是你要返回的响应状态码和响应 状态描述 符
ResponseEntity<byte[]> responseEntity = new ResponseEntity<byte[]>(
buffer, httpHeaders, HttpStatus.OK);
return responseEntity;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
大功告成!~
**
HandlerInterceptor拦截器
可以拦截controller方法包括内部映射的 不拦截直接的jsp请求
**
1、编写一个类去实现HandlerInterceptor接口
三个方法:preHandle 在目标方法执行前调用 return true表示放行
postHandle 在目标方法执行后调用
afterCompletion 目标方法执行完 跳完页面渲染完之后调用
2、到Spring的容器配置文件中去配置拦截器,并且配置拦截地址
<mvc:interceptors> 里头可以配置多个拦截器
<mvc:interceptor>一个这个标签算一个
<!-- 拦截的地址 -->
<mvc:mapping path="/一般可以是你的controller地址"/>
<!-- 拦截器具体实现类 -->
<bean class="你的拦截器类" />
</mvc:interceptor>
</mvc:interceptors>
正常情况下拦截器的执行顺序:
preHandle 目标方法执行 postHandle 页面渲染的代码 afterCompletion
出现异常的情况下拦截器的执行顺序:
一:目标方法前返回false的情况:
1、目标方法前执行 返回false
2、这是目标方法 不执行
3、目标方法之后 不执行
4、这是渲染页面 不执行
5、页面渲染完成! 不执行
二:目标方法前返回true的情况,目标方法异常
1、目标方法前执行 返回true
2、这是目标方法 异常
3、目标方法之后 不执行
4、这是渲染页面 渲染异常页面
5、页面渲染完成! 执行
三:目标方法前返回true的情况,目标方法后异常
1、目标方法前执行 返回true
2、这是目标方法 执行
3、目标方法之后 异常
4、这是渲染页面 渲染异常页面
5、页面渲染完成! 执行
四:目标方法前返回true的情况,渲染页面异常
1、目标方法前执行 返回true
2、这是目标方法 执行
3、目标方法之后 执行
4、这是渲染页面 异常
5、页面渲染完成! 执行
**
使用@ExceptionHandler拦截异常
**
拦截本controller中的异常(局部异常):
(1)controller中写一个方法 加上@ExceptionHandler注解 返回值是你要去的异常页面 参数是Exception对象 可以用modelAnd
View保存错误信息 转发过去错误页面就可以显示异常信息了!~
(2)controller中可以有多个(1)中的异常方法 异常类型越精确就越优先处理
@ControllerAdvice它可以处理所有Controller中产生的异常(全局异常) 即所有controller中的异常都可以处理
(1)加载类上面 (2)方法同样需要写@ExceptionHandler 也适用多个错误控制 越精确越优先!
在局部异常处理和全局异常处理同时存在的时候,优先顺序是:
1、局部优先 ---->>>> 2、精确优化
**
配置SimpleMappingExceptionResolver类映射异常
**
<!-- 配置SimpleMappingExceptionResolver简单异常映射解析器 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 异常映射属性 固定值的 -->
<property name="exceptionMappings">
<props>
<!--
key写上异常全类名
在prop标签中填写那批的跳转地址
-->
<prop key="java.lang.Exception">forward:/error.jsp</prop>
<prop key="java.lang.RuntimeException">forward:/error.jsp</prop>
<prop key="java.lang.ArithmeticException">forward:/error1.jsp</prop>
<prop key="java.lang.NullPointerException">forward:/null.jsp</prop>
</props>
</property>
</bean>