1. Spring MVC

2. 三层架构

07. Spring MVC - 图1

3. MVC

MVC(Model View Controller) 设计创建Web应用程序表现层的模式

  • Model 模型 : 数据模型,用于封装数据
  • View 视图 : 页面视图,用于展示数据

    • jsp
    • html
  • Contoller 控制器 :处理用户交互的调度器,用于根据用户需求处理程序逻辑

    • Servlet

4. 项目构建 xml

导入坐标

  1. <!-- servlet3.1规范的坐标 -->
  2. <dependency>
  3. <groupId>javax.servlet</groupId>
  4. <artifactId>javax.servlet-api</artifactId>
  5. <version>3.1.0</version>
  6. <scope>provided</scope>
  7. </dependency>
  8. <!--jsp坐标-->
  9. <dependency>
  10. <groupId>javax.servlet.jsp</groupId>
  11. <artifactId>jsp-api</artifactId>
  12. <version>2.1</version>
  13. <scope>provided</scope>
  14. </dependency>
  15. <!--spring web的坐标-->
  16. <dependency>
  17. <groupId>org.springframework</groupId>
  18. <artifactId>spring-web</artifactId>
  19. <version>5.1.9.RELEASE</version>
  20. </dependency>
  21. <!--springmvc的坐标-->
  22. <dependency>
  23. <groupId>org.springframework</groupId>
  24. <artifactId>spring-webmvc</artifactId>
  25. <version>5.1.9.RELEASE</version>
  26. </dependency>

spring-mvc.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:context="http://www.springframework.org/schema/context"
  4. xmlns:mvc="http://www.springframework.org/schema/mvc"
  5. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  7. http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
  8. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
  9. <context:component-scan base-package="com.itheima">
  10. <!-- 包含以下注解则加载 -->
  11. <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
  12. </context:component-scan>
  13. <!--放行指定类型静态资源配置方式-->
  14. <!-- <mvc:resources mapping="/img/**" location="/img/"/>-->
  15. <!-- <mvc:resources mapping="/js/**" location="/js/"/>-->
  16. <!-- <mvc:resources mapping="/css/**" location="/css/"/>-->
  17. <!--SpringMVC提供的通用资源放行方式 释放所有静态资源-->
  18. <mvc:default-servlet-handler/>
  19. </beans>

web.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  5. version="3.1">
  6. <!--乱码处理过滤器,与Servlet中使用的完全相同,差异之处在于处理器的类由Spring提供-->
  7. <filter>
  8. <filter-name>CharacterEncodingFilter</filter-name>
  9. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  10. <init-param>
  11. <param-name>encoding</param-name>
  12. <param-value>UTF-8</param-value>
  13. </init-param>
  14. </filter>
  15. <filter-mapping>
  16. <filter-name>CharacterEncodingFilter</filter-name>
  17. <url-pattern>/*</url-pattern>
  18. </filter-mapping>
  19. <!-- 扫描mvc配置文件 -->
  20. <servlet>
  21. <servlet-name>DispatcherServlet</servlet-name>
  22. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  23. <init-param>
  24. <param-name>contextConfigLocation</param-name>
  25. <param-value>classpath*:spring-mvc.xml</param-value>
  26. </init-param>
  27. </servlet>
  28. <servlet-mapping>
  29. <servlet-name>DispatcherServlet</servlet-name>
  30. <url-pattern>/</url-pattern>
  31. </servlet-mapping>
  32. </web-app>

5. 技术架构图

07. Spring MVC - 图2

6. 注解驱动

6.1. 扫描包含Controller注解的类

在springmvc 配置类中

  1. @ComponentScan(value = "com.itheima",includeFilters =
  2. @ComponentScan.Filter(type=FilterType.ANNOTATION,classes = {Controller.class})
  3. )

6.2. 注解配置指定放行的资源

实现WebMvcConfigurer接口 重写addResourceHandlers方法

  1. public class SpringMVCConfiguration implements WebMvcConfigurer{
  2. //注解配置放行指定资源格式
  3. @Override
  4. public void addResourceHandlers(ResourceHandlerRegistry registry) {
  5. registry.addResourceHandler("/img/**").addResourceLocations("/img/");
  6. registry.addResourceHandler("/js/**").addResourceLocations("/js/");
  7. registry.addResourceHandler("/css/**").addResourceLocations("/css/");
  8. }
  9. }

6.3. 注解配置放行所有静态资源

实现WebMvcConfigurer接口 重写configureDefaultServletHandling方法

  1. public class SpringMVCConfiguration implements WebMvcConfigurer{
  2. @Override
  3. public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
  4. configurer.enable();;
  5. }
  6. }

6.4. servlet扫描mvc配置文件

继承 AbstractDispatcherServletInitializer 类 重写里面的 createServletApplicationContext createRootApplicationContext 和 getServletMappings 方法

  1. import org.springframework.web.context.WebApplicationContext;
  2. import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
  3. import org.springframework.web.filter.CharacterEncodingFilter;
  4. import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
  5. import javax.servlet.DispatcherType;
  6. import javax.servlet.FilterRegistration;
  7. import javax.servlet.ServletContext;
  8. import javax.servlet.ServletException;
  9. import java.util.EnumSet;
  10. public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
  11. //创建Servlet容器时,使用注解的方式加载SPRINGMVC配置类中的信息,并加载成WEB专用的ApplicationContext对象
  12. //该对象放入了ServletContext范围,后期在整个WEB容器中可以随时获取调用
  13. @Override
  14. protected WebApplicationContext createServletApplicationContext() {
  15. AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
  16. //需要一个MVC配置类
  17. ctx.register(SpringMVCConfiguration.class);
  18. return ctx;
  19. }
  20. //注解配置映射地址方式,服务于SpringMVC的核心控制器DispatcherServlet
  21. @Override
  22. protected String[] getServletMappings() {
  23. return new String[]{"/"};
  24. }
  25. @Override
  26. protected WebApplicationContext createRootApplicationContext() {
  27. return null;
  28. }
  29. //乱码处理作为过滤器,在servlet容器启动时进行配置,相关内容参看Servlet零配置相关课程
  30. @Override
  31. public void onStartup(ServletContext servletContext) throws ServletException {
  32. super.onStartup(servletContext);
  33. CharacterEncodingFilter cef = new CharacterEncodingFilter();
  34. cef.setEncoding("UTF-8");
  35. FilterRegistration.Dynamic registration = servletContext.addFilter("characterEncodingFilter", cef);
  36. registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST,DispatcherType.FORWARD,DispatcherType.INCLUDE),false,"/*");
  37. }
  38. }

7. 请求

7.1. 请求参数

SpringMVC将传递的参数封装到处理器方法的形参中,达到快速访问参数的目的

只需在形参上与请求地址上的参数名字一致 即可获取到请求参数的值

  1. //请求参数 http://localhost/requestParam1?name=hello
  2. @RequestMapping("/requestParam1")
  3. public String requestParam1(String name){
  4. System.out.println(name);
  5. return "index.jsp";
  6. }

7.1.1. 普通类型

参数名与处理器方法形参名保持一致 否则无法获取对应的值

如果想要绑定具体的请求名 则需要使用 @RequestParam

  • @RequestParam

    • value 请求属性名
    • required 不允许为空 默认为true
    • defaultValue 为空时默认值
  1. //请求参数形参绑定名 http://localhost/requestParam2?username=hello&age=10
  2. @RequestMapping("/requestParam2")
  3. public String requestParam2(@RequestParam(value = "username",required = true,defaultValue = "zhangsan") String name, int age){
  4. System.out.println(name);
  5. System.out.println(age);
  6. return "index.jsp";
  7. }

7.1.2. POJO类型

如果形参为一个对象 则请求参数会将值 一一对应为对象中属性值

  1. //POJO类型参数 http://localhost/requestParam3?username=zhangsan&age=10
  2. @RequestMapping("/requestParam3")
  3. public String requestParam3(User user){
  4. System.out.println(user.toString());
  5. return "index.jsp";
  6. }

7.1.2.1. POJO类型与普通类型同时存在

将会被同时赋值 如果想进行区分 建议使用@RequestParam进行绑定

  1. //POJO类型参数与普通类型同时存在 http://localhost/requestParam4?name=zhangsan&age=10
  2. @RequestMapping("/requestParam4")
  3. public String requestParam4(User user,String age){
  4. System.out.println(user.toString());
  5. System.out.println(age);
  6. return "index.jsp";
  7. }

7.1.2.2. 复杂POJO类型 嵌套

如果POJO中嵌套POJO则 需要请求地址 需要按照层次结构要书写

  1. //复杂POJO类型 http://localhost/requestParam5?address.city=shanghai
  2. @RequestMapping("/requestParam5")
  3. public String requestParam5(User user){
  4. System.out.println(user.getAddress().getCity());
  5. return "index.jsp";
  6. }

7.1.2.3. 复杂POJO类型 集合

如果POJO中出现集合 保存简单数据 使用多个相同名称的参数为其进行赋值

  1. //复杂POJO类型 集合 http://localhost/requestParam6?nick=zhangsan&nick=lisi&nick=wangwu
  2. @RequestMapping("/requestParam6")
  3. public String requestParam6(User user){
  4. System.out.println(user);
  5. return "index.jsp";
  6. }

7.1.2.4. 复杂POJO类型 集合对象

集合对象 以索引形式的请求地址

  1. //复杂POJO类型 集合对象 http://localhost/requestParam7?addresses[0].province=bj&addresses[1].province=gd
  2. @RequestMapping("/requestParam7")
  3. public String requestParam7(User user){
  4. System.out.println(user.getAddresses());
  5. return "index.jsp";
  6. }

7.1.2.5. 复杂POJO类型 Map集合

Map集合 在请求地址中以 key的形式赋值

  1. //复杂POJO类型 集合对象 http://localhost/requestParam8?addressMap['home'].province=bj&addressMap['job'].province=gd
  2. @RequestMapping("/requestParam8")
  3. public String requestParam8(User user){
  4. System.out.println(user.getAddressMap());
  5. return "index.jsp";
  6. }

7.1.3. 数组类型

请求参数名与数组名一致 并请求参数数量大于1个

  1. //数组类型 http://localhost/requestParam9?nick=abc&nick=def
  2. @RequestMapping("/requestParam9")
  3. public String requestParam9(String[] nick) {
  4. System.out.println(nick[0] + " " + nick[1]);
  5. return "index.jsp";
  6. }

7.1.4. 集合类型

MVC默认将list作为对象处理 赋值前先创建对象 然后将nick作为对象的属性赋值 但list是接口 无法创建对象 和 有此属性值 所以报错

我们通过@RequestParam 将请求参数打包成数组

  1. //集合类型 http://localhost/requestParam10?nick=abc&nick=def
  2. @RequestMapping("/requestParam10")
  3. public String requestParam10(@RequestParam("nick") List<String> nick) {
  4. System.out.println(nick);
  5. return "index.jsp";
  6. }

7.2. 类型转换器

MVC对接受的数据进行自动类型转换 通过Converter接口实现

7.2.1. xml 日期类型格式转换

spring默认的日期格式为 2021/09/11 如果我们传递为2021-09-11则会报错 我们需要自定义日期格式转换

  1. <!-- 自定义转换格式-->
  2. <mvc:annotation-driven conversion-service="conversionService"/>
  3. <!-- 注册bean 让spring管理-->
  4. <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
  5. <property name="formatters">
  6. <set>
  7. <bean class="org.springframework.format.datetime.DateFormatter">
  8. <property name="pattern" value="yyyy-MM-dd"/>
  9. </bean>
  10. </set>
  11. </property>
  12. </bean>

7.2.2. 注解版 日期类型格式转换

  1. //日期类型 自定义格式转换 http://localhost/requestParam11?date=2021-09-11
  2. @RequestMapping("/requestParam11")
  3. public String requestParam11(@DateTimeFormat(pattern = "yyyy-MM-dd") Date date) {
  4. System.out.println(date);
  5. return "index.jsp";
  6. }

并开启mvc注解驱动

  1. <mvc:annotation-driven />

7.2.3. 自定义类型转换器

实现 Converter 接口 泛型1为原始数据类型 泛型2为返回的数据类型 并实现 convert 方法

  1. <!-- 自定义类型转换器-->
  2. <mvc:annotation-driven conversion-service="conversionService"/>
  3. <!-- 注册bean 让spring管理-->
  4. <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
  5. <property name="converters">
  6. <set>
  7. <bean class="com.itheima.converter.MyDateConverter">
  8. </bean>
  9. </set>
  10. </property>
  11. </bean>

处理类

  1. import org.springframework.core.convert.converter.Converter;
  2. import java.text.ParseException;
  3. import java.text.SimpleDateFormat;
  4. import java.util.Date;
  5. public class MyDateConverter implements Converter<String, Date> {
  6. @Override
  7. public Date convert(String s) {
  8. SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
  9. Date date = null;
  10. try {
  11. date = simpleDateFormat.parse(s);
  12. } catch (ParseException e) {
  13. e.printStackTrace();
  14. }
  15. return date;
  16. }
  17. }

7.3. 请求映射

  • @RequestMapping 设置在方法上则是方法体的请求映射 定义在类上则是整个类的访问前缀
  • value 请求路径
  • method = RequestMethod.GET 请求方式
  • params = “name” 请求地址必须传递此属性才能访问
  • headers = “content-type=text/*” 请求头条件
  • consumes = “text/*” 可以接受的请求正文类型
  • produces = “text/*” 可以生成的响应正文类型

8. 响应

8.1. 页面跳转方式

  • 转发(默认)
    1. @RequestMapping("/showPageAndData1")
    2. public String showPageAndData1(HttpServletRequest request){
    3. return "forward:success.jsp";
    4. }
  • 重定向
    1. @RequestMapping("/showPageAndData7")
    2. public String showPageAndData7(){
    3. return "redirect:index.jsp";
    4. }
  • 页面访问快捷设定 设置了快捷访问 后默认访问是设定的路径下制定的后缀文件 默认为转发跳转 无法重定向
    1. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    2. <property name="prefix" value="/WEB-INF/page/"/>
    3. <property name="suffix" value=".jsp"/>
    4. </bean>


如果方法体没有返回值 也配置了快捷方式 则自动跳转到指定的路径下 访问路径 + 后缀 的文件
07. Spring MVC - 图3

8.2. request传递数据

  1. @RequestMapping("/showPageAndData1")
  2. public String showPageAndData1(HttpServletRequest request){
  3. request.setAttribute("name","hello");
  4. return "success.jsp";
  5. }

8.3. Model 类型形参进行数据传递

  1. @RequestMapping("/showPageAndData2")
  2. public String showPageAndData2(Model model){
  3. model.addAttribute("name","hello");
  4. User user =new User();
  5. user.setAge(156);
  6. //可以传递对象
  7. model.addAttribute("user",user);
  8. return "success.jsp";
  9. }

8.4. ModelAndView 类型传递

  1. @RequestMapping("/showPageAndData3")
  2. public ModelAndView showPageAndData3(ModelAndView modelAndView){
  3. modelAndView.addObject("name","hello");
  4. User user =new User();
  5. user.setAge(156);
  6. //添加属性
  7. modelAndView.addObject("user",user);
  8. //跳转页面
  9. modelAndView.setViewName("success.jsp");
  10. return modelAndView;
  11. }

8.4.1. 重定向

  1. @RequestMapping("/showPageAndData5")
  2. public ModelAndView showPageAndData5(ModelAndView modelAndView){
  3. //重定向
  4. modelAndView.setViewName("redirect:index.jsp");
  5. return modelAndView;
  6. }
  7. @RequestMapping("/showPageAndData6")
  8. public ModelAndView showPageAndData6(ModelAndView modelAndView){
  9. //跳转
  10. modelAndView.setViewName("forward:index.jsp");
  11. return modelAndView;
  12. }

8.5. 返回JSON数据

响应方法体 返回的数据默认会直接跳转到 返回值对应的页面文件

我们可以在方法体上 加上 @ResponseBody 注解 来声明为一个响应体

  1. @RequestMapping("showData1")
  2. @ResponseBody
  3. public String showData1() throws JsonProcessingException {
  4. User user = new User();
  5. user.setAge(15);
  6. user.setName("zhangsan");
  7. ObjectMapper om = new ObjectMapper();
  8. return om.writeValueAsString(user);
  9. }
  • 返回一个对象或者集合 Jackson 已经帮我们做好了 自定义类型转换了 我们只需要在spring配置中开启注解驱动 即可
    1. <mvc:annotation-driven />


注解版 开启注解驱动 为 @EnableWebMvc

  1. @RequestMapping("showData2")
  2. @ResponseBody
  3. public User showData2() throws JsonProcessingException {
  4. User user = new User();
  5. user.setAge(15);
  6. user.setName("zhangsan");
  7. return user;
  8. }

9. Servlet相关接口

原始的 request response 和 session 提供给我们使用但是不太推荐使用原生的功能

07. Spring MVC - 图4

9.1. Head数据获取

  • @RequestHeader 获取头中指定的值
    1. @RequestMapping("/headApi")
    2. public String headApi(@RequestHeader("Accept-Language") String head){
    3. System.out.println(head);
    4. return "index.jsp";
    5. }

9.2. Cookie 数据获取

  • @CookieValue 获取cookie指定key的值
    1. @RequestMapping("/cookieApi")
    2. public String cookieApi(@CookieValue("_xsrf") String cookie){
    3. System.out.println(cookie);
    4. return "index.jsp";
    5. }

9.3. Session 数据获取和设置

  • 设置 只有在类注解上方标记的变量名称才会被放到session中

    • 07. Spring MVC - 图5
  • 获取

      1. @RequestMapping("/sessionApi")
      2. public String sessionApi(@SessionAttribute("name") String session){
      3. System.out.println(session);
      4. return "index.jsp";
      5. }

10. 发送异步请求

通过ajax发送的异步请求 是无法直接被赋值给形参的 需要在形参前面 加上 @RequestBody

  1. @RequestMapping("/ajax1")
  2. public String ajax1(@RequestBody String data) {
  3. System.out.println(data);
  4. return "index.jsp";
  5. }
  • JSON转POJO 会自动赋值给POJO中属性

      1. @RequestMapping("/ajax2")
      2. public String ajax2(@RequestBody User user) {
      3. System.out.println(user);
      4. return "index.jsp";
      5. }
  • 集合

      1. @RequestMapping("/ajax3")
      2. public String ajax3(@RequestBody List<User> user) {
      3. System.out.println(user);
      4. return "index.jsp";
      5. }

11. 异步请求响应

  • 返回字符串

      1. @RequestMapping("/ajax4")
      2. @ResponseBody
      3. public String ajax4() {
      4. return "hello";
      5. }
  • 返回对象

      1. @RequestMapping("/ajax5")
      2. @ResponseBody
      3. public User ajax5() {
      4. User user = new User();
      5. user.setName("hhh");
      6. user.setAge(13);
      7. return user;
      8. }
  • 返回集合

      1. @RequestMapping("/ajax6")
      2. @ResponseBody
      3. public List ajax6() {
      4. User user = new User();
      5. User user2 = new User();
      6. user.setName("hhh");
      7. user.setAge(13);
      8. user2.setName("qqqq");
      9. user2.setAge(17);
      10. ArrayList<User> arrayList = new ArrayList<>();
      11. arrayList.add(user);
      12. arrayList.add(user2);
      13. return arrayList;
      14. }

12. 跨域访问

当通过A域名下的操作访问 域名B下的资源时 称为跨域访问

我们可以通过设置头信息 开启跨域访问限制

但spring 帮我完成这个操作 我们只需要添加@CrossOrigin 就可以解决 定义在方法体或类上

  1. @RequestMapping("/cross")
  2. @ResponseBody
  3. @CrossOrigin
  4. public void cross() {
  5. }

13. 拦截器

拦截器(Interceptor) 是一种动态拦截方法调用的机制

  1. 在指定的方法调用前后执行预先设定后的代码
  2. 阻止原始方法的执行

核心原理:AOP思想

拦截器链:多个拦截器按照一定的顺序 对原始被调用功能进行增强

实现 HandlerInterceptor 接口 重写需要的方法

  1. public class MyInterceptor implements HandlerInterceptor {
  2. @Override
  3. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  4. System.out.println("前置运行");
  5. //如果为false 则直接拦截业务处理器不放行
  6. return true;
  7. }
  8. @Override
  9. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  10. System.out.println("后置运行");
  11. }
  12. @Override
  13. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  14. System.out.println("完成运行");
  15. }
  16. }
  1. <mvc:interceptors>
  2. <mvc:interceptor>
  3. <mvc:mapping path="/handleRun"/>
  4. <bean class="com.itheima.interceptor.MyInterceptor"/>
  5. </mvc:interceptor>
  6. </mvc:interceptors>

07. Spring MVC - 图6

13.1. 拦截器参数

  • request 请求对象
  • response 响应对象
  • handler 被调用的处理器对象,对反射中的method对象进行了包装
  • ModelAndView 可以读取或者修改 页面信息和对应数据
  • Exception 如果处理器执行中出现异常 如何处理

13.2. 多个拦截器

多个拦截器执行顺序与xml配置有关

但多个拦截器中的前置运行 后置运行 都会同时启用

按照链式 执行顺序

07. Spring MVC - 图7

13.3. 责任链模式

07. Spring MVC - 图8

14. 异常处理

类注解 @Component 绑定Bean为 并实现 HandlerExceptionResolver 接口 实现方法

此bean会拦截mvc上请求的异常

  1. @Component
  2. public class ExceptionResolver implements HandlerExceptionResolver {
  3. @Override
  4. public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
  5. System.out.println("发生异常了");
  6. ModelAndView modelAndView =new ModelAndView();
  7. if(e instanceof NullPointerException){
  8. //添加错误信息
  9. modelAndView.addObject("msg","空指针异常");
  10. }else if (e instanceof ArithmeticException){
  11. //添加错误信息
  12. modelAndView.addObject("msg","算术异常");
  13. }else {
  14. //添加错误信息
  15. modelAndView.addObject("msg","未知异常");
  16. }
  17. //转发页面
  18. modelAndView.setViewName("error.jsp");
  19. return modelAndView;
  20. }
  21. }

14.1. 注解版异常处理

  1. @Component
  2. @ControllerAdvice
  3. public class ExceptionAdivce {
  4. //异常 的类
  5. @ExceptionHandler(NullPointerException.class)
  6. @ResponseBody
  7. public String doNullException(Exception e){
  8. System.out.println("空指针异常");
  9. return "空指针异常";
  10. }
  11. //异常 的类
  12. @ExceptionHandler(ArithmeticException.class)
  13. @ResponseBody
  14. public String doArithmeticException(Exception e){
  15. System.out.println("算术异常");
  16. return "算术异常";
  17. }
  18. //异常 的类
  19. @ExceptionHandler(Exception.class)
  20. @ResponseBody
  21. public String doException(Exception e){
  22. System.out.println("all");
  23. return "all";
  24. }
  25. }

注意事项:

@ExceptionHandler 注解 会比 HandlerExceptionResolver 运行早

HandlerExceptionResolver 无法捕抓到参数异常 而注解可以捕抓到

15. 文件上传下载

坐标

  1. <!--文件上传下载-->
  2. <dependency>
  3. <groupId>commons-fileupload</groupId>
  4. <artifactId>commons-fileupload</artifactId>
  5. <version>1.4</version>
  6. </dependency>

07. Spring MVC - 图9

上传文件传递的name 要与 形参的名称一致

16. Restful

07. Spring MVC - 图10

07. Spring MVC - 图11

16.1. PathVariable

@PathVariable 为Restful 规范的请求路径 赋值给指定形参

并且在@RequestMapping 的 method 指定请求方式

  1. @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
  2. public String restLocation(@PathVariable Integer id){
  3. System.out.println(id);
  4. return "page.jsp";
  5. }

16.2. RestController

@RestController 结合了 @Controller和@ResponseBody 两个注解的功能

绑定为bean 并且 所有返回内容都不会解析为网页结构

16.3. XXXMapping

@GetMapping @PostMapping 请求等等

我们不用在@RequestMapping 中定义指定的请求方式 和 请求路径

只需在方法体加上指定请求方式的注解即

  1. @PostMapping("{id}")
  2. public String postrestLocation(@PathVariable Integer id){
  3. System.out.println(id);
  4. return "page.jsp";
  5. }

17. 表单验证框架

Hibernate框架

  1. <dependency>
  2. <groupId>org.hibernate</groupId>
  3. <artifactId>hibernate-validator</artifactId>
  4. <version>6.1.0.Final</version>
  5. </dependency>
  • @Valid 形参注解 开启此形参的验证
  • @Valid 属性注解 开启此对象或属性验证 对象校验在对象内部属性定义规则
  • @NotBlank(message = “提醒信息”) 属性验证规则 不能为null 并且长度必须大于0和不全为空格 则不能为空
  • @NotNull (message = “提醒信息”) 不能为null 可以为空
  • @NotEmpty(message = “”) 不能为空和null
  • @Max(value = “” , message =” “) 限定最大值
  • @Min(value = “” , message = “”) 最小值
  • @Range(max = ,min = ,message = ) 最大最小值
  1. @RequestMapping(value = "/addemployee2")
  2. //使用@Valid开启校验,使用@Validated也可以开启校验
  3. //Errors对象用于封装校验结果,如果不满足校验规则,对应的校验结果封装到该对象中,包含校验的属性名和校验不通过返回的消息
  4. public String addEmployee2(@Valid Employee employee, Errors errors, Model m){
  5. //判定Errors对象中是否存在未通过校验的字段
  6. if(errors.hasErrors()){
  7. //获取所有未通过校验规则的信息
  8. List<FieldError> fieldErrors = errors.getFieldErrors();
  9. System.out.println(fieldErrors.size());
  10. for(FieldError error : fieldErrors){
  11. System.out.println(error.getField());
  12. System.out.println(error.getDefaultMessage());
  13. //将校验结果信息添加到Model对象中,用于页面显示,后期实际开发中无需这样设定,返回json数据即可
  14. m.addAttribute(error.getField(),error.getDefaultMessage());
  15. }
  16. //当出现未通过校验的字段时,跳转页面到原始页面,进行数据回显
  17. return "addemployee.jsp";
  18. }
  19. return "success.jsp";
  20. }
  1. @NotBlank(message = "姓名不能为空")
  2. private String name;//员工姓名
  3. //一个属性可以添加多个校验器
  4. @NotNull(message = "请输入您的年龄")
  5. @Max(value = 60,message = "年龄最大值不允许超过60岁")
  6. @Min(value = 18,message = "年龄最小值不允许低于18岁")
  7. private Integer age;//员工年龄
  8. //实体类中的引用类型通过标注@Valid注解,设定开启当前引用类型字段中的属性参与校验
  9. @Valid
  10. private Address address;

17.1. 分组校验

如果不开启分组校验 则会校验当前全部开启校验的属性/对象

在属性/对象校验注解中 加上 groups 属性 并给予一个 用于标识的字节码文件

  1. //设定校验器,设置校验不通过对应的消息,设定所参与的校验组
  2. @NotBlank(message = "姓名不能为空",groups = {GroupA.class})
  3. private String name;//员工姓名

拦截校验器 开启校验注解要改为 @Validated 并加上标识字节码文件

  1. @RequestMapping(value = "/addemployee")
  2. public String addEmployee(@Validated({GroupA.class}) Employee employee, Errors errors, Model m){
  3. if(errors.hasErrors()){
  4. List<FieldError> fieldErrors = errors.getFieldErrors();
  5. System.out.println(fieldErrors.size());
  6. for(FieldError error : fieldErrors){
  7. System.out.println(error.getField());
  8. System.out.println(error.getDefaultMessage());
  9. m.addAttribute(error.getField(),error.getDefaultMessage());
  10. }
  11. return "addemployee.jsp";
  12. }
  13. return "success.jsp";
  14. }

18. SSM

Spring + SpringMVC + MyBatis