SpringMVC学习笔记
一、SpringMVC基础入门,创建一个hello world程序
-
首先,导入springMVC 需要的jar包
<!--spring核心依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.12.RELEASE</version> </dependency> <!--web依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.2.12.RELEASE</version> </dependency> <!--springmvc依赖--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.12.RELEASE</version> </dependency>
-
在resource文件夹中配置springmvc.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:comtext="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"> <!--开启组件扫描--> <comtext:component-scan base-package="com.tangren.controller"/> <!--自动配置处理器映射器和适配器--> <mvc:annotation-driven/> <!--配置视图解析器--> <mvc:view-resolvers> <mvc:jsp prefix="/WEB-INF/jsp/" suffix=".jsp"/> </mvc:view-resolvers> </beans>
-
在web.xml中配置springmvc配置
<servlet> <servlet-name>springmvc</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> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
-
在web-inf文件夹下创建jsp用来存放jsp视图,创建一个hello.jsp文件并在body中添加hello world~~~~
-
在java文件夹下建立包和controller文件,HelloController.class文件如下
package com.tangren.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloController { /** * 跳转到hello页面的控制器 */ @RequestMapping("hello") public String hello(){ return "hello"; } }
-
启动服务器
二、SpringMVC常用注解
@Controller
负责注册一个bean 到spring 上下文中。
@RequestMapping
注解为控制器指定可以处理哪些 URL 请求。
@RequestBody
该注解用于读取Request请求的body部分数据,使用系统默认配置的HttpMessageConverter
进行解析,然后把相应的数据绑定到要返回的对象上 ,再把HttpMessageConverter
返回的对象数据绑定到 controller
中方法的参数上。
@ResponseBody
该注解用于将Controller
的方法返回的对象,通过适当的HttpMessageConverter
转换为指定格式后,写入到Response对象的body数据区。
@ModelAttribute
- 在方法定义上使用
@ModelAttribute
注解:Spring MVC 在调用目标处理方法前,会先逐个调用在方法级上标注了@ModelAttribute
的方法。 - 在方法的入参前使用
@ModelAttribute
注解:可以从隐含对象中获取隐含的模型数据中获取对象,再将请求参数–绑定到对象中,再传入入参将方法入参对象添加到模型中。
@RequestParam
在处理方法入参处使用 @RequestParam
可以把请求参 数传递给请求方法。
@PathVariable
绑定 URL 占位符到入参。
@ExceptionHandler
注解到方法上,出现异常时会执行该方法。
@ControllerAdvice
使一个Contoller成为全局的异常处理类,类中用@ExceptionHandle
r方法注解的方法可以处理所有Controller发生的异常。
三、redirect和forward的区别
1.转发在服务器端完成的;重定向是在客户端完成的
2.转发的速度快;重定向速度慢
3.转发的是同一次请求;重定向是两次不同请求
4.转发不会执行转发后的代码;重定向会执行重定向之后的代码
5.转发地址栏没有变化;重定向地址栏有变化
6.转发必须是在同一台服务器下完成;重定向可以在不同的服务器下完成
使用:
/**
* 请求转发到hello2
*/
@RequestMapping("forward")
public String forward(){
return "forward:hello2";
}
/**
* 重定向到hello2路径
*/
@RequestMapping("redirect")
public String redirect(){
return "redirect:hello2";
}
四、文件上传
-
导入依赖
<!--文件上传--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.2</version> </dependency>
-
在springMVC.xml中添加配置文件上传解析器
<!--文件上传,id必须是multipartResolver--> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--上传文件最大值--> <property name="maxUploadSize" value="102400000"/> <!--字符集编码--> <property name="defaultEncoding" value="UTF-8"/> </bean>
-
编写提交表单
<!--请求方式必须是post,并且指定enctype="multipart/form-data" --> <form action="upload" method="post" enctype="multipart/form-data"> <input type="file" name="file" placeholder="选择文件"> <input type="submit" value="提交"> </form>
-
在controller包中创建UploadController
/** * 文件上传 */ @Controller public class UploadController { @RequestMapping(value = "/upload") public String onload(MultipartFile file) throws IOException { if (file.isEmpty()){ System.out.println("文件为空!!!!!!"); } //获取原始文件名 String filename = file.getOriginalFilename(); //文件保存路径 File newfile = new File("F:\\test\\", filename); //判断文件路径是否存在,不存在创建 if (!newfile.exists()){ newfile.mkdirs(); } file.transferTo(newfile); return "hello2"; } }
五、异常处理
1.局部异常处理(只能处理当前controller)
@Controller
public class ExceptionController {
@ExceptionHandler
public ModelAndView exceptionHandler(Exception e){
ModelAndView mv = new ModelAndView("error");
mv.addObject("exception", e);
System.out.println("局部异常!");
return mv;
}
@RequestMapping("/error")
public String Error(){
int a= 5/0;
return "error";
}
}
2.全局异常处理
-
注解方式
@ControllerAdvice public class ExceptionAdvice { @ExceptionHandler public ModelAndView exceptionHandler(Exception e){ //返回error页面 ModelAndView mv = new ModelAndView("error"); mv.addObject("exception", e); System.out.println("全局异常处理!"); return mv; } }
-
接口方式
@Component public class HandlerException implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) { ModelAndView mv = new ModelAndView("error"); mv.addObject("exception",e); return mv; } }
六、自定义一个拦截器
1.实现HandlerInterceptor接口
public class TestInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//路径校验工具类
AntPathMatcher pathMatcher = new AntPathMatcher();
System.out.println("当前请求的路径:" + request.getServletPath());
//如果请求的路径为test就拦截
if (pathMatcher.match(request.getServletPath(), "/redirect")) {
System.out.println("请求被拦截!");
return false;
}
//false 拦截,true 放行
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("TestInterceptor.postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("TestInterceptor.afterCompletion");
}
}
2.在springmvc.xml中添加配置
<mvc:interceptors>
<mvc:interceptor>
<!--拦截的路径-->
<mvc:mapping path="/*"/>
<bean class="com.tangren.config.TestInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
单个拦截器执行流程:
不放行
preHandle------>返回 放行
preHandle------>handler中方法------>postHandle------>handler中方法返回ModelAndView------>afterCompletion
七、springmvc的工作原理
- 发起请求到前端控制器(DispatcherServlet)
- 前端控制器请求HandlerMapping(处理器映射器)查找 Handler (可以根据xml配置、注解进行查找)
- 处理器映射器HandlerMapping向前端控制器返回Handler
- 前端控制器调用处理器适配器去执行Handler
- 处理器适配器执行Handler
- Handler执行完成给适配器返回ModelAndView
- 处理器适配器向前端控制器返回ModelAndView
- 前端控制器请求视图解析器去进行视图解析
- 视图解析器向前端控制器返回View
- 前端控制器进行视图渲染
- 前端控制器向用户响应结果
八、接口传参
-
接受八种基本数据类型和字符串类型
@Controller
public class testController {
@Autowired
private BookService bookService;
/*
* @RequestMapping(value = "hello",produces="text/plain;charset=UTF-8") 解决返回的字符串是???的问题
* url?name=a&age=12&date=2020/12/12 //springmvc默认的日期格式 yyyy/MM/dd HH:mm:ss 修改日期需要使用 @DateTimeFormat(pattern = "yyyy-MM-dd")
*@RequestParam(name = "name") //指定接收传递的参数
* */
@RequestMapping(value = "hello", produces="text/plain;charset=UTF-8")
@ResponseBody
public String hello(String name, int age, Date date){
System.out.println("name = " + name);
System.out.println("age = " + age);
System.out.println("date = " + date);
return "成功了";
}
}
-
对象类型只要保证url传递的参数与接受对象的属性名一致,mvc会自动封装传递的值
-
数组类型与容器类型的传递(容器类型的不能直接接收参数,必须封装到对象中)
数组类型:只需要保持传递的属性名字是数组的name MVC会自动封装多个值到这个接受的数组中 name=value&name=value
List类型:springMVC不可以直接接受List类型,可以间接接受,将接受的集合放入对象中作为对象的属性 url?listName=value&listName=value
map类型:url?entry[key1]=value&entry[key2]=value
Q.E.D.