1.WEB-INFO下的资源安全
在Web-INFO下的资源,不能通过浏览器直接访问,需要内部跳转(也就是需要转发,重定向不行)
2.注册中央调度器--->DispatcherServlet
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--自定义加载mvc配置文件的位置-->
<!--若不定义,则默认加载web-info下的[servlet-name]-servlet.xml 文件名-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<!--随着web容器tomcat的启动而创建。只要是大于0的数值都是可以的,数字越小代表加载的顺序越早-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
3.什么是请求?
- 地址栏提交
- 表单提交
- 超链接
- 页面图片
- 引入js库
- .......等等
4.DispatcherServlet 配置url-pattern的三种方式
- /* 最大拦截,不管静态,动态资源,统统全部拦截!动态资源:jsp,php。。。
- / 会拦截静态资源,页面返回404。静态资源:像图片、css、js等
- *.do controller访问路劲写好就可以很方便的过滤了。
5.restful请求
安卓系统就是这个请求。这个就必须要使用/的形式了!!而*.do的形式就不行了!
6.restful请求如何处理静态资源访问的问题
(以下方法选一种即可!!)
-
在web.xml中,写上:需要返回什么资源就写什么后缀,一种资源就要下一个下面的东西。<servlet-mapping><servlet-name>default</servlet-name><url-pattern>*.jpg</url-pattern></servlet-mapping>
-
在springmvc.xml中配置mvc标签<!-- 当在web.xml 中 DispatcherServlet使用 <url-pattern>/</url-pattern> 映射时,能映射静态资源 --><mvc:default-servlet-handler/>
-
在springmvc.xml中配置mvc:resources标签该标签是spring3.0.4后引入的,专门处理静态资源的访问问题<!-- 静态资源映射 --><mvc:resources mapping="/static/**" location="/WEB-INF/static/"/>
7.相对路径和绝对路径
一、绝对路径:以http协议开头的,绝对路径
二、相对路径分两类
①以/开头 ②不以/开头
①以/开头的又分两类:
前端路径:在html,jsp页面中的html(不是在java代码块中的)
后端路径:在java代码中出现的,xml啊,propertites啊,java代码中啊。
前端路径的参照路径是web服务器的根,不包含项目名,如:http://127.0.0.1:8080
后端路径的参照路径是web应用的根,包含项目名,如:http://127.0.0.1:8080/demo01
注意两个后面都是没有/的!
②不以/开头的参照路径是当前访问路径去掉资源路径。
例如当前访问的是:http://127.0.0.1:8080/demo01/xxxxx/ooo/hello.do
那么相对路径就是http://127.0.0.1:8080/demo01/xxxxx/ooo/
8.重定向的特例!!
重定向写的路劲应该按前端路径来看待!!因为重定向了!!记住就好
9.SpirngMVC的流程分析
- 处理器映射器--->通过url来找到具体对应的Handler,也就是Controller
- 处理器映射器找到具体的Controller后,将Controller+Interceptor封装到一起,包装成处理器执行链返回
- 处理器适配器--->查看该Handler也就是Controller是具体实现的哪一个接口,是Controller,还是HttpRequestHandler接口,来决定使用哪一个适配器进行处理Handler对象。
10.SpringMVC中默认的组件配置
11.视图解析器
- internalResouceViewResolver
- beanNameViewResolver
- xmlResouceViewResolver
- ResourceBundleViewResolver
后面三种是差不多的,如果是访问内部资源就用jstlView,如果是外部资源就用RedirectView
如果要设置视图解析器的优先级,只需设置下order属性即可!,大于0的整数,数字越小加载顺序越早!!
视图分为逻辑视图和物理视图。
12.POST和GET请求
在处理器中默认两种请求都是可接受的!!
一般设置就设置POST请求,单单设置一个GET没有任何意义!
13.解决中文乱码问题
在web.xml中配置一个Spring的字符过滤器CharacterEncodingFilter<!-- 设置filter编码开始 -->
<filter>
<filter-name>Set Character Encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<async-supported>true</async-supported>
<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>Set Character Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 设置filter编码结束 -->
14.springMVC中的注解
- @Controller 标明该类是处理器,需要在配置文件中添加组件扫描器
- @RequestMapping 映射路径,标在类上就是命名空间,在方法上就是访问的资源路径
- @RequestParam 设置参数的一些属性,列入,默认值啊,是否是必须的啊等等
- @ResponseBody 表明该方法响应体返回!需添加mvc注解驱动
15.注解的参数
若注解中有多个参数,如果这样定义@Annotation("aaa"),那么就是赋值给默认属性value
16.Controller层方法的返回值
- ModelAndView----》既有视图,又有数据
- void----》1.通过ServletAPI对象(request、response、、)进行跳转和数据处理。
2.ajax跳转。通过response对象拿到printWiter对象的out方法输出,页面的ajax接收即可!一般不用这种,后期用String直接接受即可!
- String----》1.返回的是本地视图资源
2.视图名(需要注册BeanNameViewResolver),若要返回视图,则不能加@RsponseBody
- Object----》返回结果对象,是相应体。需要3步
1.添加@ResponseBody
2.添加mvc注解驱动
3.添加jackson核心包
注意,返回响应体若有乱码问题,需要在@RequestMapping中添加produces属性text/html;charset=utf-8
至于produces的属性要用什么,都在MediaType这个类中有定义!!例如:
@RequestMapping(value="/01",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
然后前端用ajax接接收即可。各种类型都可以。
17.重定向与转发
默认是转发,若要重定向则需写上redirect:资源路径
注意,这里的重定向以/开头的路劲依然是后台路劲,绝对于项目。只有Serlet中用response的重定向以/开头是前台路劲,绝对于服务器。
重定向主要是用Model对象,将数据(只能是基本数据)放在model中然后重定向,url后面会自动拼接参数。
18.异常处理
- SimpleMappingExceptionResolver在xml中注册即可,无需bean的id,设置下错误页面啊,错误信息对象啊,等一些属性即可!这个是最简单的,框架自带的。这种只能简单的设置错误跳转页面,不能在发生异常时做一些其他的处理!
- 如果想要在发生异常时再一起处理程序,需要用户自定义一个类,并注册!该类继承HandlerExceptionResolver,并重写其方法。
- 注解式自定义全局异常处理(重点哦)
@ControllerAdvice
//该注解被@Component注解了,所以可以被扫描注入
public class MyAnnotationExceptionHandlerResolver {
//参数放需要捕获的异常class对象
@ExceptionHandler(ArithmeticException.class)
//需要什么参数就放啥参数,可别放太过分的参数哦
public ModelAndView HandlerException1(Exception e, HttpServletRequest request, HttpServletResponse response){
ModelAndView mv = new ModelAndView();
System.out.println("--------");
System.out.println("执行自定义代码块、、、");
System.out.println(e);
System.out.println(request);
System.out.println(response);
System.out.println("--------");
mv.setViewName("/WEB-INF/jsp/error.jsp");
mv.addObject("ex",e);
return mv;
}
@ExceptionHandler()
public void HandlerException2(Exception e){
System.out.println("--------");
System.out.println("执行自定义代码块、、、");
System.out.println(e);
System.out.println("--------");
}
}
19.类型转换器
基本类型的转换都能轻松完成,框架已经帮我们实现了。
但是有些类型不能转换需要我们自己定义,比如日期,日期有很多种格式...
自定义类型转换器,需要实现接口Converter接口,然后再mvc注解驱动标签要添加conversion-service属性
<mvc:annotation-driven conversion-service=""/>
总的来说,一般定义一个什么类型转换器。。麻烦,一般就都直接在Controller层处理,而且前端页面也会有一些限制。实际工作代码中几乎不用。
20.数据回显
就是表单提交的时候,把用户提交过来的信息都拿过来,然后如果有表单填错的情况,会把之前填的数据再带回去。
其实就是异常处理那里,添加了request对象,从request对象中拿用户填写的信息,然后前端页面用el表达式显示出来。
(用不到吧?)
21.@ControllerAdvice的使用
官方介绍:
表示带注释的类可以帮助“控制器”。
作为一种专业化@Component,允许通过类路径扫描来自动检测实现类。
它通常用于定义@ExceptionHandler, @InitBinder以及@ModelAttribute 适用于所有@RequestMapping方法的方法。
之一的annotations(),basePackageClasses(), basePackages()或它的别名value() 可以被指定,以限定控制器,以协助的特定子集。当应用多个选择器时,应用“或”逻辑 - 意味着选定的控制器应至少匹配一个选择器。
默认行为(即如果使用没有任何选择器),@ControllerAdvice注释类将协助所有已知的控制器。
请注意,这些检查是在运行时完成的,因此添加许多属性并使用多个策略可能会产生负面影响(复杂性,性能)。
简单说就是可以进行全局性的操作。
@ExceptionHandler, @InitBinder以及@ModelAttribute也可以直接用在单个Controller中,但是那样的话就仅仅只是对单个Controller起作用了。
22.@InitBinder的使用
@InitBinder
public void initBinder(WebDataBinder webDataBinder){
webDataBinder.registerCustomEditor(Date.class,new MyDateEditor());
}
注意:可以注册多个!!底层是Map形式的。自定义一个资源编辑器,重写set方法即可!
webDataBinder.registerCustomEditor(Date.class,new MyDateEditor());
webDataBinder.registerCustomEditor(Date.class,new MyDateEditor());
webDataBinder.registerCustomEditor(Date.class,new MyDateEditor());
自定义propertyEditor类继承PropertiesEditor该类
public class MyDateEditor extends PropertiesEditor{
@Override
public void setAsText(String text) throws IllegalArgumentException {
String patten=null;
if(Pattern.matches("^\\d{4}/\\d{2}/\\d{2}$",text)){ //2017/10/23
patten="yyyy/MM/dd";
}
if(Pattern.matches("^\\d{4}\\d{2}\\d{2}$",text)){ //20171023
patten="yyyyMMdd";
}
if(Pattern.matches("^\\d{4}-\\d{2}-\\d{2}$",text)){ //2017-10-23
patten="yyyy-MM-dd";
}
DateFormat df=new SimpleDateFormat(patten);
try {
setValue(df.parse(text));
} catch (ParseException e) {
e.printStackTrace();
}
}
}
在哪个Controller里面里就对哪个Controller起作用,如果是在@ControllerAdvice里面写就是全局有用
24. 验证器 validator
使用的最多的是Hibernate 的验证器。
首先需要导入jar包:
然后再mvc注解驱动中添加如下:
<mvc:annotation-driven validator=""/>
注册本地验证器,设置验证器提供class,然后再注册Hibernate的验证器即可!
<bean id="myValidator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass" value=""/>
</bean>
之后就是在实体类的属性上添加像@NotNull啊,@Min啊,@Max啊,@Size啊,@Pattern啊等验证信息即可。
还需要再Controller层写上这样的东西
@Validator不能添加在String和基本类型的前面。
如果验证失败,BindingResult对象中会有所有的错误信息。
项目中应该是几乎不用的。除非是安全性非常高的项目。
25.mvc注解驱动的用处
<mvc:annotation-driven/>
1.处理响应体,@ResponseBody
2.处理类型转换器,添加conversion-service属性
3.处理验证器,添加validator属性
4.处理文件上传
5.....
26.文件上传
1.前端的form表单,method一定要设置为post,且encType为multipart/form-data
2.添加mvc注解驱动
3.添加common的fileupload包
<!--文件上传的支持-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
4.Controller层的配置
@Controller
@RequestMapping("/test")
public class MyController04 {
@RequestMapping("/upload")
public String register(MultipartFile img, HttpServletRequest request, HttpSession session) throws Exception {
String path=session.getServletContext().getRealPath("/images");
String Filename = img.getOriginalFilename();
//path根目录,Filename子目录即文件么
File file=new File(path,Filename);
img.transferTo(file);
request.setAttribute("message","上传成功");
return "/WEB-INF/jsp/hello.jsp";
}
}
5.在springmvc.xml中配置
<!--这个id必须是这样,这个id已经在DispatcherServlet中定义了,所以id必须是这个-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--设置默认编码解决的是上传上来文件名中若有乱码的问题-->
<property name="defaultEncoding" value="utf-8"/>
<!--总上传大小-->
<property name="maxUploadSize" value="3145728"/>
<!--单个文件大小-->
<property name="maxUploadSizePerFile" value="1048576"/>
<!--大小的单位是字节Byte 1MB=1024*2015 Byte-->
</bean>
上传多个文件的支持,就是在Controller的方法的参数改成MultipartFile[] img 并添加@RequestParam注解,向框架表明,这个类型的参数要组装成一个数组!其他操作和单个文件上传是一样的。
27.拦截器部分
1.需要自己写个类实现HandlerInterceptor接口,并实现里面的三个方法
/**
* 自定义类实现HandlerInterceptor接口
*/
public class MyInterceptor implements HandlerInterceptor{
//前置处理器,方法之前
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("执行MyInterceptor的---preHandle()方法");
//true 和 false 来决定是否拦截
return true;
}
//后置处理器,只的是方法走完了,但是还没有把数据给视图处理
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("执行MyInterceptor的---postHandle()方法");
}
//完成处理器,指的是全部跑完了,已经把数据都处理,马上要把数据给浏览器之前!!!
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("执行MyInterceptor的---afterCompletion()方法");
}
}
2.对自己写的拦截器进行注册,需要使用springmvc的标签。
<!--注册拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="ljqwstc.aop.interceptor.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
拦截器流程图:
多个拦截器处理流程图:
这种图可能会好理解一些:
afterComletion()方法执行的条件是preHandle()方法的执行并且返回true
如果执行了preHandle()并且返回的是true,及时后面还有很多拦截器或者程序抛了异常,afterComletion()还是会执行
有点类似finally 经常会做资源释放的操作。具体的源码可以看Dispatcher的doDispatch()方法
结语:以上这些就是在我学习SpringMVC中的笔记,可能比较粗略,但我写这篇博客也是为了我日后复习使用,随着工作的深入,我会不断对这边博客进行补充。