一、快速入门
新建项目
导入依赖
在web.xml中添加前端控制器
构建项目结构
spring配置文件
编写controller类
注解解释
@Controller注解继承于spring代表将类交给ioc容器,在使用时需要在spring.xml中配置包扫描
@RequestMapping 用于建立请求 URL 和处理请求方法之间的对应关系
放在类上为一级目录,放在方法上为二级目录
* 属性:
1.value:用于指定请求的URL。它和path属性的作用是一样的
2.method:用来限定请求的方式
3.params:用来限定请求参数的条件
配置tomcat服务器
启动服务器在url后输入请求地址
二、springmvc执行流程
1. 用户发送请求至前端控制器DispatcherServlet。
2. DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3. 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),
生成处理器对象及处理器拦截器(如 果有则生成)一并返回给DispatcherServlet。
4. DispatcherServlet调用HandlerAdapter处理器适配器。
5. HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6. Controller执行完成返回ModelAndView。 模型 视图
7. HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8. DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9. ViewReslover解析后返回具体View。
10. DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11. DispatcherServlet将渲染后的视图响应响应用户。
组件详解
1. 前端控制器:DispatcherServlet :请求 响应 用户请求到达前端控制器,它就相当于 MVC 模式中的 C,DispatcherServlet 是整个流程 控制的中心,由它调用其它组件处理用户的请求,DispatcherServlet 的存在降低了组件之间的 耦合性。
2. 处理器映射器:HandlerMapping HandlerMapping 负责根据用户请求找到 Handler 即处理器,SpringMVC 提供了不同的映 射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
3. 处理器适配器:HandlerAdapter 通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对 更多类型的处理器进行执行。
4. 处理器:Handler【**开发者编写**】 它就是我们开发中要编写的具体业务控制器。由 DispatcherServlet 把用户请求转发到 Handler。由Handler 对具体的用户请求进行处理。
5. 视图解析器:ViewResolver View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解 析成物理视图名,即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结 果通过页面展示给用户。
6. 视图:View 【开发者编写】 SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jstlView、freemarkerView、 pdfView等。最常用的视图就是 jsp。一般情况下需要通过页面标签或页面模版技术将模型数据通过 页面展示给用户,需要由程序员根据业务需求开发具体的页面。
配置视图解析器
在spring-mvc.xml配置文件上加入以下代码
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
此时controller层变为
中文过滤器
为了防止在请求和响应过程中出现字符编码不匹配
我们要在web.xml配置文件中加入中文过滤器
<!--配置全局过滤的filter-->
<filter>
<filter-name>CharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
三、springmvc的请求
1.参数的请求类型
- 基本类型参数
- 对象类型参数
- 数组类型参数
- 集合类型参数
- json格式
2.基本类型参数
改造controller类加入形参
发送带参数的url
输出结果
3.对象类型参数
添加一个实体类User有两个属性username,password
改变controller方法
在首页面加入链接
启动服务器
由此可以看出springmvc自动将两个参数转换为了对象类型
4.数组类型参数
在初始页面中添加
在controller层添加方法
形式参数名与前端数组名保持一致才能封装成功
启动服务器
5.集合类型参数
在初始页面中添加
添加实体类,
添加controller方法
启动服务器
6.json类型参数
导入依赖包
<!--springmvc 解析xml文件-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
在springmvc配置文件中设置
<!--约束头-->
xmlns:mvc="http://www.springframework.org/schema/mvc"
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
<!--增强处理器适配器 支持json-->
<mvc:annotation-driven/>
controller层方法
利用接口工具向服务器发出json格式请求
7.自定义类型转换器
在前端传过来的数据与后端参数的数据类型不同时
编写类型转换工具类
在spring.xml中加入以下配置
<!--增强处理器适配器 支持json-->
<mvc:annotation-driven conversion-service="conversionService"/>
<!--自定义类型转换器-->
<bean id="conversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<bean class="com.dbzhu.utils.DateConverter"></bean>
</set>
</property>
</bean>
编写前端和controller
启动服务器
成功
8.相关注解
- @RequestParam
- 当请求的参数name名称与Controller的业务方法参数名称不一致时,就需要通过@RequestParam注解显示的绑定
<a href="${pageContext.request.contextPath}/user/findByPage?pageNo=2"> 分页查询 </a>
/*
@RequestParam() 注解
defaultValue 设置参数默认值
name 匹配页面传递参数的名称
required 设置是否必须传递参数,默认值为true;如果设置了默认值,值自动改为false
*/
@RequestMapping("/findByPage")
public String findByPage(@RequestParam(name = "pageNo", defaultValue = "1")
Integer pageNum, @RequestParam(defaultValue = "5") Integer pageSize) {
System.out.println(pageNum);
System.out.println(pageSize);
return "success";
}
- @RequestHeader
- 获取请求头的数据。
@RequestMapping("/requestHead")
public String requestHead(@RequestHeader("cookie") String cookie) {
System.out.println(cookie);
return "success";
}
- @CookieValue
- 获取cookie中的数据。
@RequestMapping("/cookieValue")
public String cookieValue(@CookieValue("JSESSIONID") String jesessionId) {
System.out.println(jesessionId);
return "success";
}
四、springmvc的响应
- 页面跳转
- 返回字符串逻辑视图
- void原始ServletAPI
- ModelAndView
- 返回数据
- 直接返回字符串数据
- 将对象或集合转为json返回
1.返回字符串逻辑视图(以上案例都是此种方法)
- 直接返回字符串:此种方式会将返回的字符串与视图解析器的前后缀拼接后跳转到指定页面
@RequestMapping("/returnString")
public String returnString() {
return "success";
}
2.原始ServletAPI
需要导入servlet依赖
<!--servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
//原始的请求与转发
@RequestMapping("/resp")
public void resp(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("正在跳转至resp.jsp页面");
//请求转发 同一请求
req.getRequestDispatcher("/WEB-INF/pages/resp.jsp").forward(req,resp);
//请求重定向,只能访问webapp下的 请求头为302 两个请求
// resp.sendRedirect("index.jsp");
}
返回字符串逻辑视图的请求转发和重定向
//mvc模式的请求与转发
@RequestMapping("/zc")
public String mvcZc(){
System.out.println("1111");
//请求转发
// return "forward:resp";
//请求重定向
return "redirect:/resp";
}
3.ModelAndView:数据 视图
- 可以往同一个请求存数据(转发)
- 跳转
// ModelAndView 类 既可以存数据又可以跳转,同一请求
@RequestMapping("/mv")
public ModelAndView mv(ModelAndView modelAndView){
System.out.println("ModelAndView 类 ");
//将数据username=tom发送给要传送的界面
modelAndView.addObject("username","tom");
modelAndView.setViewName("show");
return modelAndView;
}
4.@SessionAttributes
- 如果在多个请求之间共用数据,则可以在控制器类上标注一个 @SessionAttributes,配置需要在session中存放的数据范围,Spring MVC将存放在model中对应的数据暂存到 HttpSession 中。
- 注意:@SessionAttributes只能定义在类上
@SessionAttributes("username") //提高username的等级 是所有页面都能访问此属性
五 、静态资源访问的开启
当有静态资源需要加载时,比如jquery文件,通过谷歌开发者工具抓包发现,没有加载到jquery文件,原因是SpringMVC的前端控制器DispatcherServlet的url-pattern配置的是 /(缺省),代表对所有的静态资源都进行处理操作,这样就不会执行Tomcat内置的DefaultServlet处理,
<!--在springmvc配置文件中开启DefaultServlet处理静态资源-->
<mvc:default-servlet-handler/>
六、异步交互
1.@RequestBody
- 该注解用于Controller的方法的形参声明,当使用ajax提交并指定contentType为json形式时,通过HttpMessageConverter接口转换为对应的POJO对象。
2.@ResponBody
- 该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端。
七、 RESTful
- Restful是一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。主要用于客户端和服务器交互类的软件,基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制等。
- Restful风格的请求是使用“url+请求方式”表示一次请求目的的,HTTP 协议里面四个表示操作方式的动词如下:
- GET:读取(Read)
- POST:新建(Create)
- PUT:更新(Update)
- DELETE:删除(Delete)
通俗来说就是请求地址是一样的,但因请求方式不同,访问不同的界面
注解
@PathVariable
用来接收RESTful风格请求地址中占位符的值
@RestController
RESTful风格多用于前后端分离项目开发,前端通过ajax与服务器进行异步交互,我们处理器通常返回的是json数据所以使用@RestController来替代@Controller和@ResponseBody两个注解。
@RestController // controller + responsebody
public class RestfulController {
@RequestMapping("/user")
//@ResponseBody
public List<User> findAll(){
ArrayList<User> users = new ArrayList<>();
users.add(new User("自正刚","666666"));
users.add(new User("自正刚","666666"));
users.add(new User("自正刚","666666"));
users.add(new User("自正刚","666666"));
users.add(new User("自正刚","666666"));
return users;
}
@DeleteMapping("/user/{id}")
// @ResponseBody
public String delete(@PathVariable Integer id){
return "delete"+id;
}
@PutMapping("/user")
//@ResponseBody
public String update(@RequestBody User user){
return "update"+user;
}
@PostMapping("/user")
//@ResponseBody
public String add(@RequestBody User user){
return "add"+user;
}
}
八、文件上传
环境搭建
导入依赖
<!--文件上传-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
在spring.xml中添加文件上传解析器
<!--文件上传解析器-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设定文件上传的最大值为5MB,5*1024*1024 -->
<property name="maxUploadSize" value="5242880"></property>
<!-- 设定文件上传时写入内存的最大值,如果小于这个参数不会生成临时文件,默认为10240 -->
<property name="maxInMemorySize" value="40960"></property>
</bean>
单文件上传
编写前端页面
编写controller
多文件上传
- 前端的多个文件归为一组
- name的属性值一样
- 后端改为数组处理即可
<form action="${pageContext.request.contextPath}/filesUpload" method="post" enctype="multipart/form-data">
名称:<input type="text" name="username"> <br>
文件1:<input type="file" name="filePic"> <br>
文件2:<input type="file" name="filePic"> <br>
<input type="submit" value="多文件上传">
</form>
@RequestMapping("/filesUpload")
public String filesUpload(String username, MultipartFile[] filePic) throws
IOException {
System.out.println(username);
for (MultipartFile multipartFile : filePic) {
// 获取文件名
String originalFilename = multipartFile.getOriginalFilename();
// 保存到服务器
multipartFile.transferTo(new File("d:/upload/" + originalFilename));
}
return "success";
}
九、异常处理
1.异常处理的思路
- 在Java中,对于异常的处理一般有两种方式:
- 一种是当前方法捕获处理(try-catch),这种处理方式会造成业务代码和异常处理代码的耦合。
- 另一种是自己不处理,而是抛给调用者处理(throws),调用者再抛给它的调用者,也就是一直向上抛。
2.自定义异常处理器
创建异常处理类,并将其交给ioc容器,一旦出现异常直接利用modelandview跳转到error页面
编写测试类
启动服务器
3.web的处理异常机制
<!--处理500异常-->
<error-page>
<error-code>500</error-code>
<location>/500.jsp</location>
</error-page>
<!--处理404异常-->
<error-page>
<error-code>404</error-code>
<location>/404.jsp</location>
</error-page>
十、拦截器
1.拦截器(interceptor)的作用
- Spring MVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(InterceptorChain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体实现。
2.拦截器与过滤器的区别
3.自定义拦截器
创建拦截器类
public class MyInterceptor1 implements HandlerInterceptor {
// 在目标方法执行之前 拦截
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
System.out.println("preHendle1");
return true;
}
// 在目标方法执行之后,视图对象返回之前 执行
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
System.out.println("postHandle1");
}
// 在流程都执行完毕后 执行
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
System.out.println("afterCompletion1");
}
}
在spring.xml中添加拦截器配置
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--对哪些资源执行拦截操作-->
<mvc:mapping path="/**"/>
<bean class="com.dbzhu.interceptor.MyInterceptor1"/>
</mvc:interceptor>
</mvc:interceptors>
编写controller方法
启动服务器,输入url地址
4. 拦截器链
- 开发中拦截器可以单独使用,也可以同时使用多个拦截器形成一条拦截器链。开发步骤和单个拦截器是一样的,只不过注册的时候注册多个,注意这里注册的顺序就代表拦截器执行的顺序。同上,再编写一个MyHandlerInterceptor2操作,测试执行顺序: