框架学习-SpringMVC

SpringMVC简介

开发步骤

  • 导入spring-webmvc的依赖坐标
  • 配置Spring的前端控制器DispatcherServlet(相当于一个执行公共行为的Servlet)
  • 创建Controller类和视图页面
  • 使用注解RequestMapping配置类中业务方法的映射地址
  • 配置spring-mvc.xml配置文件,并在web.xml中加载要读取的spring-mvc配置文件
  • 测试

SpringMVC执行流程图(粗略)

在这里插入图片描述


SpringMVC 组件解析

代码实现

web.xml

<!--配置Spring的前端控制器-->
<servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--加载要读取的spring-mvc配置文件-->
    <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>

UserController.java

@Controller
public class UserController {
    @RequestMapping("/quick")
    public String save(){
        System.out.println("Controller save running ....");
        return "success.jsp";//success.jsp放在webapp目录下
    }
}

spring-mvc.xml

	<!--开启Controller的组件扫描-->
    <context:component-scan base-package="com.itheima.controller"/>

SpringMVC执行流程(代码层面)

在这里插入图片描述

SpringMVC执行流程(底层部件)

在这里插入图片描述

注解解析

  • RequestMapping:
    • 作用:用于建立请求URL和请求处理方法方法之间的关系
    • 位置:
      • 类上:请求URL的一级目录,此处不写的话,就相当于应用的根目录
      • 方法上:请求URL的第二级访问目录,会和方法上的value拼接起来组成访问虚拟路径
    • 属性:
      • value 代表请求的url
      • method 指定请求的方式,枚举类型
      • params 用于指定请求参数的条件,支持简单的表达式要求,请求参数必须符合该参数要求
@Controller
@RequestMapping("/user")
public class UserController {
    //方法上的RequestMapping的value会和方法上的value拼接起来组成访问虚拟路径
    // value 代表请求的url
    // method 指定请求的方式,枚举类型
    // params 用于指定请求参数的条件,支持简单的表达式要求,请求参数必须符合该参数要求
    @RequestMapping(value = "/quick", method = RequestMethod.GET, params = {"username"})
    public String save(){
        System.out.println("Controller save running ....");
        // 加"/"表示在当前web应用,即webapp下寻找资源,即找当前 http://localhost:3306/user/ 下的success.jsp,不加"/"表是相对路径
        return "/success.jsp";
    }
}

XML配置解析

  • 视图解析器
    SpringMVC有默认组件配置,默认组件都是 DispatcherServlet.properties 配置文件中配置的,该配置文件地址org.springframework.web.servlet.DispatcherServlet.properties,该文件中配置了默认的视图解析器 org.springframework.web.servlet.view.InternalResourceViewResolver
    我们可以在spring-mvc.xml中配置 InternalResourceViewResolver 来修改和查看默认配置,如:
<!--配置内部视图资源解析器-->
   <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
       <property name="prefix" value="/jsp/"/>
       <property name="suffix" value=".jsp"/>
   </bean>
REDIRECT_URL_PREFIX = "redirect:"; 重定向前缀
FORWARD_URL_PREFIX = "forward:"; 转发前缀(默认)
prefix = ""; 视图名称前缀
suffix = ""; 视图名称后缀

SpringMVC数据响应

页面跳转

  • 返回字符串形式
    就是前面的可以自定义前后缀的拼接字符串返回的方式
  • 返回ModelAndView

在参数上写ModelAndView让SpringMVC帮我们注入

@RequestMapping("/quick3")
public ModelAndView save3(ModelAndView mad){
   //设置模型数据
   mad.addObject("username", "Powers");
   //设置视图名称
   mad.setViewName("success");
   return mad;
}

只设置模型数据,直接返回视图名字

@RequestMapping("/quick4")
public String save4(Model model){
    //设置模型数据
    model.addAttribute("username", "violet");
    return "success";
}

回写数据

  • 返回字符串
    要加上@ResponseBody注解,即返回String类型
  • 返回对象或集合
    也要家上@ResponseBody注解,返回的是String类型的json字符串
    SpringMVC自动将对象转换为json格式字符串,指定jackson进行对象或集合的转换
    要导入jackson-core,jackson-databind 和jackson-annotations的依赖

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>

上面的配置可以使用mvc的注解驱动代替,默认集成jackson进行对象或者集合的json转换

<mvc:annotation-driven/>

Controller

@RequestMapping("/quick7")
@ResponseBody
public User save7() throws JsonProcessingException {
    User user = new User("lisi", 19);
    return user;
}

SpringMVC获得请求参数

获得基本类型参数

@RequestMapping("/quick8")
@ResponseBody
public void save8(String username, int age) {
    System.out.println(username);
    System.out.println(age);
}

输入:localhost:8080/user/quick8?username=zhangsan&age=18 来传递参数

使用@PathVariable在url中传递参数

前端页面跳转地址:location.href = "${pageContext.request.contextPath}/user/del/" + userId;

@RequestMapping("/del/{userId}")
public String del(@PathVariable Long userId) {
    userService.del(userId);
    return "redirect:/user/list";
}

获得POJO类型参数

springmvc自动将进行数据类型转换,将String类型的age 转换为int,前提是
实体类POJO要和请求参数name一致

@RequestMapping("/quick9")
@ResponseBody
//springmvc自动将进行数据类型转换,将String类型的age 转换为int
public void save9(User user) {
    System.out.println(user);
}

输入:localhost:8080/user/quick9?username=zhangsan&age=18 来传递POJO类型参数

获得集合类型参数

要自己写一个类(ViewObject)将集合作为实例字段

@RequestMapping("/quick11")
@ResponseBody
public void save11(ViewObject viewObject) {
    System.out.println(viewObject);
}

同时在前端使用一个form表单将集合数据传入

<form method="post" action="${pageContext.request.contextPath}/user/quick11">
    <input type="text" name="userList[0].username"><br>
    <input type="text" name="userList[0].age"><br>
    <input type="text" name="userList[1].username"><br>
    <input type="text" name="userList[1].age"><br>
    <input type="submit" value="提交"><br>
</form>

可以简化不写类包装集合,直接获得集合类型参数,在方法上写集合
并标注@RequestBody注解


@RequestMapping("/quick12")
@ResponseBody
public void save12(@RequestBody List<User> userList) {
    System.out.println(userList);
}

但此时需要使用ajax异步请求发送请求参数

<script src="${pageContext.request.contextPath}/js/jquery-3.3.1.js"></script>
<script>
    var userList = new Array();
    userList.push({username:"zhangsan", age:18});
    userList.push({username:"lisi", age:100});

    $.ajax({
        type:"POST",
        url:"${pageContext.request.contextPath}/user/quick12",
        data:JSON.stringify(userList),
        contentType:"application/json;charset=utf-8"
    });
</script>

同时需要在 spring-mvc.xml 中配置,静态资源的访问,这样才能使用 jQuery 静态资源

<!--开发资源的访问-->
<!--mapping代表访问时的url地址, location代表真实目录-->
<!--<mvc:resources mapping="/js/**" location="/js/"/>-->
<mvc:default-servlet-handler/>

参数绑定@RequestParam

value是指定请求参数的新名字,指定之后旧名字就不可用
required是指定该参数是否必须包括,默认true
defaultValue是未指定请求参数的值时,默认传入的值

@RequestMapping("/quick13")
@ResponseBody
public void save13(@RequestParam(value = "name", required = false, defaultValue = "Powerstot") String username) {
    System.out.println(username);
}

SpringMVC文件上传

表单上传客户端三要素

  • 表单项:type = "file"
  • 表单提交方式是 post
  • 表单enctype属性是多部份表单形式,enctype = "multipart/form-data"

文件上传原理

  • form表单修改为 多部份表单时,request.getParameter()将失效
  • 当form表单默认为enctype = "application/x-www-form-urlencoded"url编码时,form表单的正文内容是键值对形式key=value&key=value
  • 当form表单为enctype = "Mutilpart/form-data"时,请求正文变成多部分形式:
    在这里插入图片描述

单文件上传步骤

  • 将form表单修改为enctype = "Mutilpart/form-data",同时添加input type = "file"
    该项input的name值必须要和Controller中的MultipartFile名称一致
  • 导入 commons-fileuploadcommons-io jar包
  • spring-mvc.xml中配置文件上传解析器
 <!--配置文件上传解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!--默认编码-->
    <property name="defaultEncoding" value="UTF-8"/>
    <!--文件上传总大小-->
    <property name="maxUploadSize" value="50000"/>
</bean>
  • 编写文件上传代码
//上传单文件
@RequestMapping("/quick14")
@ResponseBody
public void save14(String username, MultipartFile uploadFile) throws IOException {
    System.out.println(username);
    //将文件保存到本地
    String originalFilename = uploadFile.getOriginalFilename();
    uploadFile.transferTo(new File("D:\\Development\\" + originalFilename));
}
//上传多文件
@RequestMapping("/quick15")
@ResponseBody
public void save15(String username, MultipartFile[] uploadFiles) throws IOException {
    System.out.println(username);
    //遍历文件数组将文件分别存储到本地
    for (MultipartFile multipartFile : uploadFiles) {
        String originalFilename = multipartFile.getOriginalFilename();
        multipartFile.transferTo(new File("D:\\Development\\" + originalFilename));
    }
}

SpirngMVC拦截器

作用

  • 拦截器(interceptor)类似于 web 开发过程中的 Filter,用于对处理器进行预处理后处理
  • 拦截器按照一定顺序链接成链,被称为 拦截器链, 访问被拦截的方法或字段时,拦截器链中的拦截器就会按定义的顺序被执行
  • 拦截器 也是 AOP 思想的具体实现

拦截器(Interceptor)和过滤器(Filter)的区别

区别过滤器Filter拦截器Interceptor
使用范围servlet规范的一部分,Java Web工程都可使用SpringMVC框架自己的功能
拦截范围在url-pattern中配置了 /* 之后,可以对所有资源进行拦截只拦截访问的控制器方法,如果访问的是jsp,html,css或者js是不会进行拦截的

拦截器使用步骤

  • 创建拦截器并实现 HanderInterceptor接口
public class MyInterceptor1 implements HandlerInterceptor {
    //方法执行前
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle");
        String param = request.getParameter("param");
        if ("yes".equals(param)) {
            return true;
        } else {
            request.getRequestDispatcher("/error.jsp").forward(request,response);
            return false;
        }
    }
    //方法执行后,视图返回前
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    	//一般在postHandle对模型进行修改操作
        modelAndView.addObject("name", "Powerstot");
        System.out.println("postHandle");
    }
    //视图返回之后
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterHandle");
    }
}
  • web.xml中配置拦截器(可以配置多个拦截器,按照定义的顺序执行)
<!--配置拦截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <!--要拦截的路径-->
        <mvc:mapping path="/**"/>
        <bean class="com.itheima.interceptor.MyInterceptor1"/>
    </mvc:interceptor>
</mvc:interceptors>

<mvc:mapping path="/**"/>SpringMVC的path配置为
/**表示拦截所有文件夹及其子文件夹
/*表示拦截当前文件夹内文件,不包含子文件夹
/表示web的根目录

拦截器方法详解

  • preHandle返回true代表放行,false不放行,是最常用的方法。
    当返回true时,继续调用下一个拦截器的 preHandle 或 目标方法
    当返回false时,则后续的 InterceptorController 都不会再执行
  • postHandle:只有preHandle返回true才执行。在请求方法执行之后,DispatcherServlet 进行视图渲染之前执行
  • afterCompletion:只有preHandle返回true才执行。在整个请求结束之后,也就是DispatcherServlet渲染了对应的视图之后才执行

SpringMVC异常处理

异常处理的思路

DAO,Service,Controller出现异常都通过 throws Exception 向上抛出,最后由前端控制器交由异常处理器处理
在这里插入图片描述

简单异常处理器SimpleMappingExceptionResolver

SpringMVC已经定义好了该类型转换器,使用时直接进行对应视图和异常的映射即可

spring-mvc.xml中

<!--简单异常处理器-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <!--默认异常错误视图-->
    <property name="defaultErrorView" value="error"/>
    <property name="exceptionMappings">
        <map>
            <!--key:异常类型  value:错误视图,这里已经配置了视图资源解析器修改前后缀-->
            <entry key="java.lang.ClassCastException" value="error1"/>
            <entry key="java.lang.ArithmeticException" value="error2"/>
        </map>
    </property>
</bean>

自定义异常处理器

  • 创建异常处理器类实现 HandlerExceptionResolver接口中的方法
    通过判断传入的异常对象的种类,进行逻辑的编写,并返回 ModelAndView 对象
  • 配置异常处理器(将异常处理器放到Spring容器当中即可)
  • 编写异常页面

补充

在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 主要是可以通过一些简单的配置注解,让 Java 类成为处理请求的控制器,而无需实现任何接口,替代了原先 web 中的 Servlet,使用 Controller 作为替代
  • 主要是通过 前端控制器 DispatcherServlet 对指定的路径进行处理,根据请求 分发到不同的 Controller 中,从而执行不同的业务,并且处理返回的 ModelAndView,对页面进行渲染,返回响应
  • 主要通过@RequestMapping注解,可以实现页面跳转,回写数据等操作,还可以通过@ResponseBody实现数据的直接回显
  • 文件上传主要是通过传递 多部份表单 multipart 的数据
  • MVC的拦截器 Interceptor 主要是利用了AOP思想,不会对静态资源进行拦截
  • MVC的异常处理,原则是将所有异常向上抛出,最后由异常处理器统一处理,异常处理器中配置 异常 和 对应视图的 映射

参考

2020年IDEA版黑马Java :BV1WZ4y1H7du

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值