本文主要包含:
1.springMVC视图解析器配置(InternalResourceViewResolver)
2.数据输出中 Model 、Map、 ModelMap及ModelAndView关系
3.<url-pattern>标签拦截规则
4. 自定义转换器实现日期类型参数
5.springMVC自带针对post请求的编码过滤器 (CharacterEncodingFilter)
6. springMVC对Restful风格的支持
7. 过滤器、拦截器、监听器
8. Multipart实现文件上传
9.异常处理机制
10.重定向参数传递(flash属性)
1.springMVC视图解析器配置(InternalResourceViewResolver)
在springMVC配置文件中
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
2.数据输出中 Model 、Map、 ModelMap及ModelAndView关系
springMVC在handler方法上传入Map、Model、ModelMap和ModelAndView参数(可以在方法上传入,也可以在方法内声明),并向这些参数中保存数据(放入到请求域),都可以在页面获取到
Model 、Map及 ModelMap 实例getClass打印类型为org.springframework.validation.support.BindingAwareModelMap
而ModelAndView getCalss 打印类型为org.springframework.web.servlet.ModelAndView
public class BindingAwareModelMap extends ExtendedModelMap
public class ExtendedModelMap extends ModelMap implements Model
public class ModelMap extends LinkedHashMap<String, Object> {
public class ModelAndView {
/** View instance or view name String. */
@Nullable
private Object view;
/** Model Map. */
@Nullable
private ModelMap model;
public ModelAndView addObject(String attributeName, @Nullable Object attributeValue) {
getModelMap().addAttribute(attributeName, attributeValue);
return this;
}
}
3.<url-pattern>标签拦截规则
web.xml中配置DispatcherServlet前端控制器,并将springMvc.xml配置给DispatcherServlet前端控制器后,需要通过<url-pattern>标签定义拦截规则 <url-pattern>中配置方式
A. / 拦截所有,除了jsp文件
<url-pattern>/</url-pattern>
B. /* 拦截所有,包括jsp文件
<url-pattern>/*</url-pattern>
C.带后缀
<url-pattern>*.action</url-pattern>
分析:
为什么配置 / 时,会拦截所有静态文件(静态文件:除servlet、jsp之外的js,css,png等)?
因为tomcat容器中有一个web.xml(父),自己的项目也有一个web.xm(子),是一个继承关系,夫tomcat的web.xml中有一个 DefaultServlet,配置的 url-pattern 是一个 /(如下);而在自己的项目中配置了 / , 相当于覆写了父 web.xml的配置
为什么不拦截.jsp呢 ?
因为父web.xml中有一个JspServlet,这个servlet拦截.jsp文件,而我们并没有覆写这个配置,所以springmvc此时不拦截jsp,jsp的处理交给了tomcat
<servlet> <servlet-name>default</servlet-name> <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>0</param-value> </init-param> <init-param> <param-name>listings</param-name> <param-value>false</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>jsp</servlet-name> <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class> <init-param> <param-name>fork</param-name> <param-value>false</param-value> </init-param> <init-param> <param-name>xpoweredBy</param-name> <param-value>false</param-value> </init-param> <load-on-startup>3</load-on-startup> </servlet>
<!-- The mapping for the default servlet --> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- The mappings for the JSP servlet --> <servlet-mapping> <servlet-name>jsp</servlet-name> <url-pattern>*.jsp</url-pattern> <url-pattern>*.jspx</url-pattern> </servlet-mapping>
4. 自定义转换器实现日期类型参数
A. 自定义类实现Converter接口,实现其convert方法 (注意 Converter中需要传两个类型 前一个为源类型,后一个为转换之后的类型即:目标类型)
import org.springframework.core.convert.converter.Converter;
public class StringConvertToDate implements Converter<String, Date> {
@Override
public Date convert(String s) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
return simpleDateFormat.parse(s);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
}
B.在springMVC配置文件中: 注册自定义转换器 (FormattingConversionServiceFactoryBean)
<bean id="formattingConversionServiceFactoryBean" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.kay.converter.StringConvertToDate"></bean>
</set>
</property>
</bean>
C. 在springMVC配置文件中 :<mvc:annotation-driven> 中conversion-service属性指向FormattingConversionServiceFactoryBean
<mvc:annotation-driven conversion-service="formattingConversionServiceFactoryBean"/>
5.springMVC自带针对post请求的编码过滤器 (CharacterEncodingFilter)
在web.xml中增加过滤器
<filter>
<filter-name>encoding</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>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
6. springMVC对Restful风格的支持
http get请求 查询资源;user/1 get
http put请求资源 更新;user/1 put
http delete 删除资源 ; user/1 delete
同样的URL地址,根据请求类型不同,操作不同的handler
A.@PathVarible注解
@PutMapping("/handle05/{id}")
public String handle05(@PathVariable("id")String id){}
B. 请求转换过滤器
前期请求类型只有GET 及 POST,Restful风格根据不同的请求,通过GET/PUT/DELETE/POST
进行资源的查询/修改/删除/新增;springMVC提供HiddenHttpMethodFilter过滤器;将特定的post请求转换为put和delete请求
HiddenHttpMethodFilter
在post请求传入的参数中,增加 参数 _method 其值配置为put则请求类型为PutMapping;其值为delete时请求的类型为DeleteMapping
<!--配置springmvc请求方式转换过滤器,会检查请求参数中是否有_method参数,如果有就按照指定的请求方式进行转换-->
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
@PutMapping("/handle/{id}")
public String handle05(@PathVariable("id")String id) {}
@DeleteMapping("/handle/{id}")
public String handle06(@PathVariable("id")String id) {}
<input type="hidden" name="_method" value="put"/>
7. 过滤器、拦截器、监听器
servlet:处理Request请求和Response响应
A.自定义拦截器
1). 自定义类实现HandlerInterceptor,重写对应方法
public class MyInterceptor01 implements HandlerInterceptor {
/**
* handler逻辑方法执行之前
*可用于方法鉴权
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("-------------------- MyInterceptor01 preHandle --------------");
return true; //return 是否放行, true 放行,false 终止
}
/**
* handler的方法执行之后,但是还没有返回页面
* 此时可以通过对modelAndView 可以对数据和视图进行修改
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("-------------------- MyInterceptor01 postHandle --------------");
}
/**
* 页面已经渲染完毕
* 可以在此处做捕获异常的处理
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("-------------------- MyInterceptor01 afterCompletion --------------");
}
}
2) 在springmvc配置文件中,配置自定义拦截器
** 代表拦截当前目录下及其子目录下的所有url
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean id="myInterceptor01" class="com.kay.interceptor.MyInterceptor01"></bean>
</mvc:interceptor>
</mvc:interceptors>
拦截所有还可以配置成以下
<mvc:interceptors> <bean id="myInterceptor01" class="com.kay.interceptor.MyInterceptor01"></bean> </mvc:interceptors>
B.多拦截器执行流程
1)配置文件中注册拦截器的上下顺序即为拦截器顺序
2)preHandle()按照拦截器的配置顺序执行,postHandle()和afterCompletion()则会按照配置顺序的反序执行
8. Multipart实现文件上传
A.引入文件上传jar依赖(自编写代码编译不需要此jar,但是spring容器在创建multipartResolver时需要,否则会报错)
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
B.在springmvc配置文件中,注册文件上传解析器,id必须为multipartResolver
<!-- 文件上传解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 最大上传大小 in bytes -->
<property name="maxUploadSize" value="1024000"></property>
<!-- Default is ISO-8859-1, according to the Servlet spec.-->
<!-- <property name="defaultEncoding" value=""></property>-->
</bean>
C.前端请求传参需要是post、type="file" 并且enctype="multipart/form-data"
<form method="post" enctype="multipart/form-data" action="/demo/upload">
<input type="file" name="uploadFile"/>
<input type="submit" value="上传"/>
</form>
D.Controller中使用 MultipartFile 接受文件信息 且MultipartFile 对应的参数名称必须和type=file的字段名保持一致(此处为 uploadFile)
@PostMapping("/upload")
public String upload(MultipartFile uploadFile, HttpServletRequest request) throws IOException {
String originalFilename = uploadFile.getOriginalFilename(); // 文件原名称
originalFilename.substring(originalFilename.lastIndexOf("."), originalFilename.length()); // 获取扩展名 .png
String upload = request.getSession().getServletContext().getRealPath("upload");
String dataString = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
File folder = new File(upload + "/" + dataString); // /upload/日期 文件夹
if (!folder.exists()) {
folder.mkdirs();
}
String fileName = UUID.randomUUID().toString();
uploadFile.transferTo(new File(folder, fileName + originalFilename)); // 将文件从MultipartFile对象中的写入到文件中
return "success";
}
9.异常处理机制
异常处理器 HandlerExceptionResolve ,常用的是注解 @ExceptionHandler,结合@ControllerAdvice controller增强注解使用,其配置的异常拦截对所有controller都生效(注意:@ControllerAdvice需要被component-scan扫描到!!)
@ControllerAdvice
public class GlobeExceptionHandler {
@ExceptionHandler(ArithmeticException.class)
public void myExceptionHandler(ArithmeticException exception, HttpServletResponse httpServletResponse) {
try {
httpServletResponse.getWriter().write("error" + exception.getMessage());
return;
} catch (IOException e) {
e.printStackTrace();
}
}
@ExceptionHandler(Exception.class)
public ModelAndView myExceptionHandler(Exception exception) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg", exception.getMessage());
modelAndView.setViewName("error");
return modelAndView;
}
}
10.重定向参数传递(flash属性)
重定向请求时,浏览器请求URL会改变,参数会丢失,在请求时需要将参数重新拼接传递
@RequestMapping("/testA") public String testA(String name) { return "redirect:testB?name=" + name; }
以上方式存在问题:这种get请求的拼接方式,参数的长度有限制,而且安全性也不够高;
springMVC提供了flash属性机制,向上下文中添加flash属性,框架会在session中记录该属性值,当跳转到页面之后框架会自动删除flash属性,不需要我们手动删除
RedirectAttributes addFlashAttribute (注意此处使用@ModelAttribute接收)
@RequestMapping("/testA")
public String testA(RedirectAttributes redirectAttributes, String name) {
redirectAttributes.addFlashAttribute("name", name);
return "redirect:testB";
}
@RequestMapping("/testB")
public String testB(@ModelAttribute("name") String name) {
return "success";
}