之前web学习的Servlet之间有共有行为,和私有行为。
我们要抽取共有行为。只写很小一部分的私有行为。
1.导入SpringMVC的包
2.配置Servlet
3.编写Controller
4.将Controller使用注解配置到Spring容器中。
5.配置spirng-mvc.xml文件,配置组件扫描(扫描注解。)
1.SpirngMVC快速入门
1.导入坐标,保证版本一致。
spring-context,spring-web,spring-webmvc这些版本都要一致
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
2.web.xml里配置前端核心控制器
DispatcherServlet
这里,每次请求都走这个共有servlet进行共有操作。
<!--配置SpringMVC的前端控制器-->
<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:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
3.整一个Controller页面。、
加了@RequestMapping注解,可以在项目路径后输入quick,访问到整个方法。
4.整一个spring-mvc.xml
加上context空间。
在web.xml,里告诉spring-mvc.xml的路径。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.alibaba.com/schema/stat"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.alibaba.com/schema/stat http://www.alibaba.com/schema/stat.xsd">
<!--Controller的组件扫描-->
<context:component-scan base-package="com.itheima">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--配置内部资源视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- /jsp/success.jsp -->
<property name="prefix" value="/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
访问路径,图3煳了的是DispatcherServlet。
2.SpringMVC的组件解析(底层实现)。
2.1 springMVC注解解析。
2.1.1 requestMapping使用
method属性后设成post,那么请求quick,就必须得post。
如果类外面又加一层@RequestMapping,那么地址前得加 /user
这样知道是user模块的controller里的方法。
启动之后,就会访问user下的success.jsp,文件。但user下面没有
所以改成。这样就去webapp下找这个文件。
param属性。
url后面必须加参数。
2.1.2 springMVC的组件扫描
springMVC只扫描controller层。各扫各的。
只扫com.itheima,下的controller注解。
expresssion,是@controller注解的全包名。
<!--Controller的组件扫描-->
<context:component-scan base-package="com.itheima">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
也可以这么写
2.2 mvc命名空间解析
2.3 SpringMVC XML配置解析
视图解析器有自带的。
forward转发,默认的,可以去掉。跳转页面,浏览器里地址可以不变。
这里如果想重定向,加redirect。
如果把jsp文件都放在一个jsp文件下。那么,每次我们还要加个 /jsp
我们可以自己配置内部资源解析器。在spring-mvc.xml中
<!--配置内部资源视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- /jsp/success.jsp -->
<property name="prefix" value="/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
这样我们可以不用写前缀和后缀。
写成这样即可。
3.数据响应
3.1 页面跳转
相较于web,不用getDisparcher。
3.1.1返回字符串形式
重定向,不能有web-inf,因为这个文件夹受到保护。
3.1.2 返回ModelAndView对象。
这里访问quick2,就可以访问success页面。
setViewName,也延续了前后缀的设置。
设置了键值对,可以在jsp界面直接获取。
方法1:
方法2:
这种方式也可以,SpringMvc在解析这个方法的时候发现这个参数,需要框架提供,
SpringMvc就提供一个ModelAndView对象,注入了。
方法3:
model和view拆开了。springmvc,传入一个model对象。
方法4:
3.2 回写数据(有json的回写)
3.2.1直接返回字符串
方法1(有点笨了解一下就行):
方法2(重点掌握):
加@ResponseBody,不然return会被当成视图跳转。
方法3:返回Json字符串。
先导入3个包
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
给对象写转成json格式字符串返回。
转换的工具有没有被springMVC封装呢?
有,需要我们配置一下,告诉它。
3.2.2 返回对象或集合
期望SpringMVC给转成json格式字符串。
我们返回的这个对象发给这个适配器。但它没有转换的功能。
我们配置这个的时候,对它内部的,这个方法参数进行覆盖,告诉它用json转换。内部要的list集合数据,里面装的是bean对象。我们给它注入参数。
然后在spring-mvc.xml里配置。
<!--配置处理器映射器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
</list>
</property>
</bean>
然后我们的user就被解析成了json。
3.2.3 返回对象或集合(升级版)
3.2.2中的配置比较繁琐,用这个。
这里需要mvc的命名空间。
xmlns:mvc="http://www.springframework.org/schema/mvc"
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
3.3 获取客户端请求数据
3.3.1获得基本类型参数
controller中方法的参数名称和请求参数的name一致,参数值会自动映射匹配。
3.3.2 获得pojo类型参数
spirngMVC自动把user的属性值,封到对象里。
方法参数写对象就行。
3.3.3 获得数组类型参数
3.3.4 静态资源的访问
我们在前面用了这个js文件,在项目里。有这个文件,我们启动的时候却报错。
抓个包看看,一共3个请求。
原因:前端控制器的配置。缺省。
经过DispacherServlet,帮助我们匹配。
把js文件,当成@RequestMapping的value进行匹配。所以就匹配不上。
解决办法:
方法1:
方法2:
3.3.5 获得集合类型参数
对前端传来的json对象。
在前台用userList收集user对象,挨个push。
然后把userList转换成json发给url。即我们要调用的方法。
这里用${page.Context.request.contextPath}是JSP取得绝对路径的方法.
比如我的项目名称是demo1在浏览器中输入为http://localhost:8080/demo1/a.jsp ${pageContext.request.contextPath}或<%=request.getContextPath()%>取出来的就是/demo1。
3.3.6 请求数据乱码问题
问题:
解决:
在web.xml里 。配置上,编码过滤器。
3.3.7 参数绑定的注解
比如说前台传的参数key为name,后台的业务方法的参数为username。
required为true的时候,如果没提交过来name对应的参数,那就会404 bad request。
required为false的时候,如果没提交过来name对应的参数,会赋一个null,但不会报错。
defaultValue值设为 itcast字符串时,如果没提交过来name对应的参数,默认用itcast字符串赋值。
3.3.8 获得Restful风格的参数
用一个占位符{name},解析出url里的值。然后用@PathVariable注解解析这个路径,把值传给value。
{name}括号里的name,与value的值必须对应。
3.3.9 自定义类型转换器。
spring默认的参数类型转换器。
客户端那边传来的字符串数据"13" ,可以转成int型,13,进行参数设置。(MVC框架自动转化)
传过来的键值对,都是字符串,这里进行了参数转换。
、
但有的数据,不能自动转换类型,这个时候就需要,自定义转换器。
用2018-12-21,这种格式就错。
自定义转换器的开发步骤:
步骤1:
详解:这里指定了日期的格式。
步骤2:
FactoryBean而言,这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似
注入转换器。
步骤3:
然后就解析出来日期了。
3.4 获取Servlet相关API(获取请求数据)
比如我们方法中想要这三个参数,MVC框架会帮我们
可以看包名,可以发现这三个对象是tomcat,帮助原生产生的。
3.5 获取HTTP协议数据(获取请求参数)
3.5.1 获得请求头
required为true的时候,如果没有携带请求头,那就会404 bad request。
required为false的时候,如果没有携带请求头,会赋一个null,但不会报错。
3.5.2 获得cookie
3.6 文件上传(获取请求参数)
点提交就提交过去了。
怎么接受呢?
3.6.1 文件上传原理
这些正文内容都在HTTP,请求体内。
request的getXXX方法时,获得的是url编码方式的表单提交。正文里是键值对,下图红色字体。
现在用的是多部份表单形式,所以这些API都失效。数据对应。
3.6.2 单文件上传步骤
导入这俩依赖,用来解析正文数据。
在Spring-mvc配置文件里,上传解析器。
文件名和方法里对上,Spring会把这个文件封装成对象。
然后接收,保存。在c盘,一般保存在服务器或别的网站。
保存成功。
3.3.6 多文件上传
4.SpirngMVC拦截器
4.1 拦截器入门
现在springMVC.xml里配置拦截器。注入我们要写的拦截器。
覆盖这个接口里的三个方法。、
如果preHandle里,返回false,后面的可以都不用执行。
如果我们在浏览器里访问这个方法。
输出结果。显示出方法的执行顺序。
方法里返回的Model AndView没有被解析渲染,被拦截器里的postHandle接收,进行处理。
多个拦截器,配置在SpringMVC.xml里,配置的顺序执行。
执行顺序:先执行完所有拦截器的方法1(这个顺序,按照SpringMVC.xml里配置的顺序)
再执行controller。
然后再执行所有拦截器里的方法2,这个顺序,按照SpringMVC.xml里配置的顺序。
4.2 用户登录权限控制案例
4.2.1 拦截器写法
验证用户是否已经登录。看看session里是否有user对象。
如果有user,prehandle直接放行。
如果没有user,返回false,重定向到登录页面。
配置的时候登录页面放行。
4.2.2 controller写法
然后实现Login里的方法。
输入错误的用户名和密码。
如果DAO层报异常,就在service层抓住这个异常转化成null,然后在controller层进行操作。
正常SpringMVC是有自己的异常处理机制,下一章学习。
5.springMVC异常处理机制。
如果在业务层try-catch异常。那么这部分代码和业务成耦合到一起。
还要处理自定义的异常。
5.1 异常处理的两种方式
5.1.1mvc定义好的处理器
解析:如果抛出key里的异常,就跳向error.jsp页面。如果没有匹到,那就走上面的默认异常视图。
在springMVC.xml里配置。
5.2 自定义异常处理
自己定义一个异常处理类,实现HandlerExceptionResolver接口。
重写里面的方法。
可以对里面的异常进行判断,a异常进行A操作。
b异常进行B操作。
setViewName方法,找到error页面。
springMVC.xml里配置。