1、springmvc三大组件:HandlerMapping,HandlerAdaptor、ViewResolver
在springmvc.xml中添加如下配置:
<!-- 定义JSP视图解析器-->
<!--根据项目使用的模板引擎,视图解析器可以配置多个,比如jsp,freemaker-->
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/"></property>
<property name="suffix" value=".jsp"></property>
<property name="order" value="1" />
</bean>
<!-- 开启基mvc的自动配置,自动注册合适的HandlerMapping和HanlerAdaptor-->
<mvc:annotation-driver>
2、拦截路径区分:
在tomcat的web.xml文件中默认配置了两个serverlet
<!-- 默认配置的servlet,当没有servlet处理请求时,使用这个,返回404 -->
<!--tomcat中配置的默认servlet优先级低于mvc中配置的,
如果在mvc中配置 / ,会覆盖这个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>
/ 拦截动态请求和静态资源,但是不拦截 .jsp
/* 拦截所有请求的所有文件夹,但是 【不拦截静态资源】、也拦截.jsp
/** 拦截所有请求的所有文件夹和子文件夹,不拦截静态资源,拦截.jsp
jsp请求被拦截后,controller返回的jsp页面会再次发请求到服务器,
请求的url是:jsp页面所在相对路径,比如:/WEB-INF/pages/index.jsp
3、拦截静态资源解决方案
方案一:
tips:静态资源必须放在webapp的根目录下,否则无效
<mvc:default-servlet-handler/>
方案二:
mapping:约定的静态资源的url规则
location:约定的静态资源的存放位置
<mvc:resource location="classpath:/" mapping="resources/**">
4、日期类型转换:实现Converter接口 来自定义类型转换器
/**
* Description:自定义日期类型转换器
*
* @author:53493
* @date 2022/12/31 21:43
*/
public class DataConvertor implements Converter<String, Date> {
@Override
public Date convert(String source) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
try {
Date date = format.parse(source);
return date;
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
在springmvc的配置文件中注册自定义converter
<bean id="conversionServiceBean" class="com/lagou/springboot_01_demo/DataConvertor.java:21">
<properties>
<set>
<bean class = "com.abc.springboot_01_demo.DataConvertor"></bean>
</set>
</properties>
</bean>
<!--关联到HandlerAdaptor上-->
<mvc:annotation-driven conversion-service="conversionServiceBean">
5、HandlerMapping
HandlerMapping:处理请求和hanlder之间的映射关系,根据url路径,找到对应的handler,返回的是**HandlerExecutionChain**
HandlerIntercetor
6、HandlerAdaptor
解析参数
查找controller
返回处理结果,包括参数绑定
7、form表单中 method只能写post和get,如果要发送put请求,需要特殊处理,如下:
1、在<form>表单中添加隐藏域标签
name:固定值(_method)
value:要发送的请求类型
<input type="hidden" name="_method" value="put">
2、在web.xml中添加过滤器
<!-- 配置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>
8、post请求中中文参数乱码
方案:使用filter(拦截器可以很好的解决乱码问题)
springmvc提供了编码过滤器,在web.xml中添加配置
<!-- springmvc提供的针对post请求的编解码过滤器-->
<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>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
get请求乱码,需要在tomcat下的server.xml添加配置
<Connector URIEncoding="utf-8" port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
9、filter和HandlerInterceptor的区别
Filter定义在web.xml中,在servlet前后起作用
HandlerInterceptor定义在在mvc的配置文件中,在handler前后起作用
10、配置多个静态资源目录
1、在mvc配置文件中配置
2、页面上的<script> 标签会发送请求到服务器,其中的src属性也需要根据以下的路径进行映射
<mvc:resource location="WEB-INF/js" mapping="/js/**">
11、参数绑定
参数绑定:取数参数值,赋值给handler的形参
1、springmvc对原生servlet的api的支持,比如HttpServletRequest/HttpServletResponse/HttpSession
直接在handler方法的形参中直接声明使用即可
2、springmvc接收简单数据类型(八种基本数据类型及包装类)
直接在handler方法的形参中声明即可
要求:传递的参数名和声明的参数名一致,
当不一致的时候,使用@RequestParam("xx") 指定
tips:推荐使用包装数据类型,避免出现参数为null时出现报错
对于Boolean类型,只接受4个值:true,false,0,1
3、接收pojo类型参数,直接形参声明即可,类型就是pojo的类型
但要求传的参数名必须和pojo的属性名保持一致
4、pojo包装类型(属性是一个pojo类型)
1)绑定时直接形参声明即可
2)传参参数名和pojo属性保持一致,可以通过 属性名+"." 的方式进一步绑定数据
12、ajax交互和@RequestBoby
交互:两个方向
1)前端到后台:前端ajax发送json格式字符串,后台直接接收为pojo参数,使用@RequestBoby,标注到方法的形参上。
注意:@RequestBody取的时body请求体中的数据,get方式请求无法使用这个注解来【绑定参数】
2)后台到前端:后台直接返回pojo对象,前端接收为【json对象】或字符串,使用直接@ResponseBody,
标注到方法上,或 【返回值前面】
注意:添加@ResponseBody之后,不再走视图解析器的那个流程,
而是等同于servlet原生的response对象直接输出数据
13、拦截器(Inteceptor)、监听器(Listener)、过滤器(Filter)
一、Filter(web.xml中):对request请求起到过滤的作用,作用在servlet之前,
如果配置为 【/ *】可以对所有资源访问(servlet,js/css静态资源等)过滤
二、Listener(web.xml中):实现了javax.servlet.servletContextListener接口的组件,
它随着web应用的启动而启动,只初始化一次,然后会一直运行监视,随web应用的停止而销毁。
作用一:做一些初始化工作,web应用中spring容器启动的ContextLoaderListener
作用二:监听web中特定的事件HttpSession,ServletRequest的创建和销毁;变量的创建、销毁、
修改等,可以在动作前后增加处理,比如:统计在线人数,HttpSessionListener等。
------------- 以上两个组件是j2ee的组件,配置在web.xml中-----------
三、Interceptor:是mvc表现层自己的框架,不会拦截静态资源,只会拦截handler方法。
可以拦截三处:
1)在handler业务执行前拦截一次
2)在handler业务执行完毕但是未跳转页面之前拦截一次
3)在跳转页面之后拦截一次
request---->filter--->interceptor(handler执行之前拦截一次)
--->controller--->interceptor(handler执行之后拦截一次)
---->视图渲染(经过DispatcherServlet中转)--->interceptor(跳转页面之后拦截一次,可以修改modelAndView的数据)
-->response
*****三次拦截在一个interceptor实现类中******
拦截器可以有多个,对一个请求进行多次拦截。
四、自定义拦截器:
1)实现HandlerInterceptor接口,重写里面的方法
2)在mvc的配置文件中添加配置
<mvc:interceptors>
<mvc:interceptor>
<!--**代表当前目录及子目录下的所有url-->
<mvc:mapping path="/**"/>
<!--在mapping的基础上,需要排除的url-->
<mvc:exclude-mapping path="/demo/**">
<bean class="xxx.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
五、多个拦截器的拦截顺序
interceptor1(preHandler)--->interceptor2(pre)
--->handler
--->i2(post)--->i1(post)
-->DispatcherServlet(render)
-->i2(afterCompletion)--->i1(afterCompletion)
-----------------进 和 出,顺序相反--------------
14、处理multipart形式的数据(文件上传)
1) 引入需要的jar包
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
2)客户端
1、form表单
2、method=post
3、enctype=multipart/form-data
4、action=handler路径
4、file组件
<input type="file" name="uploadFile" />
3)服务端
1、重命名(给一个唯一的名字)
2、存储到磁盘(考虑同一个目录文件太多,可以按照日期创建文件夹)
3、把文件存储路径更新到数据库
4)在springmvc配置文件中添加【文件上传解析器】
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!---设置属性值,单位是字节,-1代表没有限制,默认就是-1-->
<property name="maxUploadSize" value="500000"></property>
</bean>
代码如下:
/**
* 上传文件
* @param uploadFile 必须和form表单中的<input type=”file“ name="uploadFile">的name相同
* @return
*/
@RequestMapping("/upload")
public ModelAndView upload(MultipartFile uploadFile, HttpSession session) throws IOException {
// 原始名称
String originalFilename = uploadFile.getOriginalFilename();
String ext = originalFilename.substring(originalFilename.lastIndexOf(".") + 1, originalFilename.length());
String newName = UUID.randomUUID().toString() + "." + ext;
// 存储,到指定的文件夹(当前项目的目录,或者共享盘,通过nginx配置访问路径)
// 得到项目下的uploads文件的磁盘路径,这里的/指的是webapp根目录
String realPath = session.getServletContext().getRealPath("/uploads");
String datePath = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
File folder = new File(realPath + "/" + datePath);
if(!folder.exists()){
folder.mkdir();
}
uploadFile.transferTo(new File(folder,newName));
// TODO
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("date",new Date());
modelAndView.setViewName("success");
return modelAndView;
}
15、springmvc的异常处理机制
一、设置全局异常处理(定义异常处理类)
@ControllerAdvice
public class GlobalExceptionResolver {
// 针对ArithmeticException异常类型
@ExceptionHandler(ArithmeticException.class)
public ModelAndView handlerExcption(ArithmeticException exception, HttpServletResponse response){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg",exception.getMessage());
modelAndView.setViewName("error");
return modelAndView;
}
}
二、针对某一个controller类进行异常处理
在这个controller类中编写异常处理方法(和上面一样的逻辑)
@ExceptionHandler(ArithmeticException.class)
public ModelAndView handlerExcption(ArithmeticException exception, HttpServletResponse response){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg",exception.getMessage());
modelAndView.setViewName("error");
return modelAndView;
}
16、springmvc 重定向参数传递问题
一、转发和重定向
转发:A找B,B找C然后B返回A(B的个人行为)
url不会变,参数也不会丢失,一个请求
重定向:A找B,B指向C,A找C
url会变,参数会丢失,两个请求
二、传递参数的方案:在方法上添加RedirectArrtibutes类型的参数
代码如下:
@RequestMapping("/handlerRedirect")
public String handlerRedirect(String name,RedirectAttributes redirectAttributes){
// andFlashArrtibute方法设置了一个false类型属性,该属性会被暂存到session中,
// 在跳转到页面之后该属性销毁
// 也可以自己放到session中,但是跳转之后需要自己来销毁
redirectAttributes.addFlashAttribute("name",name);
return "redirect:handler01";
// 方案一:拼接参数,安全性和参数长度受限
// return "redirect:handler01?name="+name;
}
@RequestMapping("/handler01")
public void handler01(String name,ModelAndView modelAndView){
// TODO
modelAndView.setViewName("success");
}