SpringMVC上

SpringMVC基本概念(一)三层架构与mvc

概念

  1. 什么是三层架构?

    描述: 项目的分层

    简介: 数据访问层(dao)、业务逻辑层(service)、表现层(web)

  2. 什么是mvc?

    Model 模型(模型的定义【entity】、模型的实现【dao、service】)

    View 视图 (html/jsp)

    Controller 控制器 (servlet/filter /springmvc/struts)

    描述: mvc是一种设计模式。表现层会用到的设计模式。
    在这里插入图片描述

SpringMVC基本概念(二)SpringMVC介绍

什么是SpringMVC?

  • SpringMVC 是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级 Web 框架, 属于 SpringFrameWork 的后续产品,已经融合在 Spring Web Flow 里面。

  • Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构,从而在使用 Spring 进行 WEB 开发时,可以选择使用 Spring的 Spring MVC 框架或集成其他 MVC 开发框架,如 Struts1(现在一般不用), Struts2 等。

  • SpringMVC 已经成为目前最主流的 MVC 框架之一, 从 Spring3.0 的发布, 就已全面超越 Struts2,成为最优秀的 MVC 框架。它通过一套注解,让一个简单的 Java 类成为处理请求的控制器,而无须实现任何接口。同时它还支持RESTful 编程风格的请求。

SpringMVC 在三层架构的位置

在这里插入图片描述

优势

  • 天生与Spring框架集成,如:(IOC,AOP)
  • 支持Restful风格
  • 进行更简洁的Web层开发
  • 支持灵活的URL到页面控制器的映射
  • 非常容易与其他视图技术集成,如:Velocity、FreeMarker等等。
  • 因为模型数据不存放在特定的API里,而是放在一个Model里(Map数据结构实现,因此很容易被其他框架使用)
  • 非常灵活的数据验证、格式化和数据绑定机制、能使用任何对象进行数据绑定,不必实现特定框架的API
  • 更加简单、强大的异常处理
  • 对静态资源的支持
  • 支持灵活的本地化、主题等解析

SpringMVC入门(一)分析

表现层职责:处理请求响应。

springmvc是表现层的框架。

springmvc是用来处理请求和响应。

实现步骤

  1. 创建项目:springmvc01。 添加依赖:spring-context、spring-webmvc
  2. 配置web.xml, 配置SpringMVC提供的:DispatcherServlet。
  3. 编写控制器类处理请求:HelloController
  4. 配置springMVC.xml
  5. 部署项目,启动项目,访问测试

SpringMVC入门(二)创建项目、添加依赖、配置web.xml

步骤

  1. 创建项目:springmvc01。 添加依赖:spring-context、spring-webmvc
  2. 配置web.xml, 配置SpringMVC提供的:DispatcherServlet。

实现

  1. 创建项目:springmvc01。 添加依赖:spring-context、spring-webmvc

    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
      <modelVersion>4.0.0</modelVersion>  
      <groupId>xxx.xxx</groupId>  
      <artifactId>springmvc01</artifactId>  
      <version>1.0-SNAPSHOT</version>  
      <packaging>war</packaging>
      <dependencies> 
        <!--spring核心支持包(IOC容器基础包)-->  
        <dependency> 
          <groupId>org.springframework</groupId>  
          <artifactId>spring-context</artifactId>  
          <version>5.1.8.RELEASE</version> 
        </dependency>  
        <!--springmvc支持包-->  
        <dependency> 
          <groupId>org.springframework</groupId>  
          <artifactId>spring-webmvc</artifactId>  
          <version>5.1.8.RELEASE</version> 
        </dependency> 
      </dependencies> 
    </project>
    
    
  2. 配置web.xml, 配置SpringMVC提供的:DispatcherServlet。

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns="http://java.sun.com/xml/ns/javaee"
    	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    	version="2.5">
    
    	<!--
    		配置SpringMVC的前端控制器:DispatcherServlet
    		 1. 如果要用springmvc的功能,必须让请求经过这个servlet
    		 2. 拦截所有.do为后缀的请求
    		    http://localhost:8080/hello		不拦截
    		    http://localhost:8080/hello.do  拦截, 符合DispatcherServlet拦截路径规则
    		 3. 通过init-param 加载类路径下的指定的spring容器配置文件
    		 4. 启动时候创建servlet
    		    load-on-startup  配置启动时候创建servlet,值范围是1-6,数字越小越先创建。
    	-->
    	<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:springMVC.xml</param-value>
    		</init-param>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    	<servlet-mapping>
    		<servlet-name>dispatcherServlet</servlet-name>
    		<url-pattern>*.do</url-pattern>
    	</servlet-mapping>
    </web-app>
    

SpringMVC入门(三)控制器、springMVC.xml

步骤

  1. 编写控制器类处理请求:HelloController
  2. 配置springMVC.xml
  3. 部署项目,启动项目,访问测试

实现

  1. 编写控制器类处理请求:HelloController

    
    /**
     * SpringMVC中处理请求的控制器类,也可以叫做处理器(Handler)
     */
    @Controller // 创建对象,加入容器;注意:必须使用@Controller注解,才可以处理请求
    public class HelloController {
    
        /**
         * 请求地址:http://localhost:8080/hello.do
         * 后台方法:xxx.xxx.controller.hello.HelloController.hello()
         * 响应地址:http://localhost:8080/pages/success.jsp
         *         地址:/pages/success.jsp
         *         前缀:/pages/              【springMVC.xml中配置】
         *         文件名称:success           控制器方法返回
         *         后缀:.jsp                  【springMVC.xml中配置】
         * @RequestMapping作用:
         *      1. 根据请求地址,找到处理请求的方法。
         *      2. 建立请求地址与处理请求方法的映射关系
         */
        @RequestMapping("/hello.do")
        public String hello(){
            System.out.println("处理请求!");
            // 返回跳转路径页面名称,跳转路径的前缀、后缀在配置文件中配置
            return "success";
        }
    }
    
    
  2. 配置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:context="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">
    
        <!--1. 注解扫描-->
        <context:component-scan base-package="xxx.xxx"/>
    
        <!--2. 视图解析器-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <!--配置跳转路径的前缀-->
            <property name="prefix" value="/pages/"/>
            <!--配置跳转路径的后缀-->
            <property name="suffix" value=".jsp"/>
        </bean>
    
        <!--3. 开启注解驱动(自动创建springmvc的处理器映射器、处理器适配器)-->
        <mvc:annotation-driven/>
    </beans>
    
  3. 部署项目,启动项目,访问测试
    在这里插入图片描述
    在这里插入图片描述
    访问:
    在这里插入图片描述

SpringMVC入门(四)执行流程

流程图

Rational Rose 建模: 时序图
在这里插入图片描述

1Tomcat启动
   1.1 加载自身的web.xml
    
   1.2 加载项目的web.xml
    	1.2.1 创建DispatcherServlet
    	1.2.2 加载springMVC.xml配置文件,初始化spring的容器
    
2、请求
   2.1 访问地址:http://localhost:8080/hello.do
   2.2 DispatcherServlet拦截请求地址
   2.3 根据请求的url:/hello.do, 匹配所有的@RequestMappping注解,找到处理请求的方法
   2.4 执行方法,处理请求,获取方法返回值(跳转路径的一部分)
    
3、响应    
   3.1 视图解析器根据控制器处理请求方法的返回结果,结合视图解析器配置的前缀、后缀,渲染页面(准备)
   3.2DispatcherServlet处理响应,交给tomcat响应客户端请求。

SpringMVC入门(五)涉及组件分析

三大组件

SpringMVC三大组件:

  1. RequestMappingHandlerMapping 处理器映射器

    作用:根据请求url地址,找到控制器中处理请求的方法。HelloController.hello()

  2. RequestMappingHandlerAdapter 处理器适配器

    作用:根据处理器映射器解析的结果,找到处理请求的方法,执行方法。

  3. InternalResourceViewResolver 视图解析器

    作用:根据处理器适配器执行的结果,交给视图解析器处理准备(渲染)页面。

详解

图1:
在这里插入图片描述
图2:
在这里插入图片描述
图3:
在这里插入图片描述

@RequestMapping注解使用

实现

/**
 * @RequestMapping
 * 0. 作用:建立请求地址与处理请求方法的映射关系。
 * 1. 位置
 *    作用于类上,  区分不同的模块,作为路径的一部分
 *    作用于方法上,表示方法的访问路径
 * 2. 常用的写法:
 *    @RequestMapping("/list.do")  OK
 *    @RequestMapping("/list")     OK  省略后缀 【推荐】
 *    @RequestMapping("list")      OK  省略/
 * 3. 注解属性
 *    value  指定请求的路径
 *    path   同value,表示请求路径
 *    method 指定支持的提交方式。如果不指定,支持所有类型的请求(get、post、put、delete..)
 *          method = RequestMethod.POST
 *              指定了请求方式,这里只支持post请求
 *              如果通过浏览器直接访问是get请求,报错:405 – Method Not Allowed
 *    name   指定路径名称,让当前路径更具有可描述性。
 *    params 指定请求路径必须带这里指定的参数名称以及参数值
 *           配置:params = "id=100"
 *           访问:http://localhost:8080/person/list.do?id=100   OK
 *           访问:http://localhost:8080/person/list.do?id=101   NOK 报错 400 + Bad Request
 *           访问:http://localhost:8080/person/list.do?id1=100  NOK 报错 400 + Bad Request
 *  4. 常见4XX错误
 *     404   路径地址错误
 *     405   请求方式服务器不支持
 *     400 + Bad Request  封装请求参数错误。 【经常遇到】
 *
 */
@Controller
@RequestMapping("/person")
public class RequestMappingController {

    /**
     * 请求地址:http://localhost:8080/person/list.do
     */
    @RequestMapping(
            value = "/list",
            method = RequestMethod.GET,
            name = "人员列表",
            params = "id=100"
    )
    //@RequestMapping("/list") // 最常用
    public String list(){
        return "success";
    }
}

请求参数绑定(一)简单类型作为参数

分析

地址:http://localhost:8080/user?id=100
后台封装请求参数:
public String save(Integer id){  // 方法形参名称与请求参数名称一致,这样就可以封装请求参数。

}


public String save(User user){  //User{int id}

}

演示

@Controller
@RequestMapping("/user")
public class UserController {

    /**
     * 请求参数绑定(一)简单类型作为参数
     *
     * 案例1:
     * 请求地址:http://localhost:8080/user/list.do?id=100&name=Jacky
     * 后台方法:public String list(Integer id,String name){}
     * 执行结果:100,Jacky
     * 封装数据:
     *         请求参数名称,与方法形参名称一致,就可以获取请求数据。
     *
     * 案例2:
     * 后台方法:public String list(Integer id,String name){}
     * 请求地址:
     *      http://localhost:8080/user/list.do?id=100&name=Jacky  结果:100,Jacky
     *      http://localhost:8080/user/list.do?id=100             结果:100,null
     *      http://localhost:8080/user/list.do                    结果:null,null
     *
     * 案例3:
     * 后台方法:public String list(int id,String name){}
     * 请求地址:
     *      http://localhost:8080/user/list.do?id=100   结果:100,null
     *      http://localhost:8080/user/list.do          结果:500 报错,因为int不能为NULL
     *
     * 总结:
     *     SpringMVC封装请求数据时候,控制器方法参数如果是基本类型,最好用其包装类型。
     */
    @RequestMapping("/list")
    public String list(Integer id,String name){
        System.out.println(id + "," + name);
        return "success";
    }
}

请求参数绑定(二)pojo类型作为参数

环境

引入lombok支持包
在这里插入图片描述

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>

实现

实体类的包:entity、beans、javabean、domain、po、pojo

POJO: 简单的Java对象 (Plain Ordinary Java Object)

步骤:

  1. 定义User对象,封装请求数据
  2. UserController添加update()方法,参数是User
  3. 定义Address地址对象,User中添加Address对象属性,如何封装?
  4. User中添加集合属性,如何封装?

实现:

  1. 定义User对象,封装请求数据

    @Data
    public class User {
        private Integer id;
        private String name;
    }
    
  2. UserController添加update()方法,参数是User

        /**
         * 请求参数绑定(二)pojo类型作为参数
         * 请求地址: http://localhost:8080/user/query.do?id=100&name=Jacky
         * 后台方法: public String query(User user){}
         * 小结:
         *      请求参数名称要与对象属性名称一致,就可以往对象中封装数据。
         *
         * 需求2:User对象中又包含有address对象属性。
         * 请求地址: http://localhost:8080/user/query.do?id=100&address.city=gz&address.province=gd
         */
        @RequestMapping("/query")
        public String query(User user){
            System.out.println(user);
            return "success";
        }
    
  3. 定义Address地址对象;User中添加Address对象属性,如何封装?

    @Data
    public class Address {
        private String province;
        private String city;
    }
    
    @Data
    public class User {
        private Integer id;
        private String name;
        // 用户的地址对象
        private Address address;
    }
    
  4. User中添加集合属性,如何封装?

    @Data
    public class User {
     private Integer id;
        private String name;
        // 用户的地址对象
        private Address address;
     // 对象中的集合属性
        private List<Address> addresses;
        private Map<String,Address> map;
    }
    
    index.jsp
    
    <%--
      Created by IntelliJ IDEA.
      User: 61073
      Date: 2020/8/9
      Time: 11:46
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>测试封装请求数据:封装集合数据</title>
    </head>
    <body>
        <form action="/user/query.do" method="post">
            用户名称:<input type="text" name="name">        <br>
            省份:<input type="text" name="address.province">        <br>
            城市:<input type="text" name="address.city">        <br><br>
    
            省份list:<input type="text" name="addresses[0].province">   <br>
            城市list:<input type="text" name="addresses[0].city">        <br>
    
    
            省份map:<input type="text" name="map['one'].province">        <br>
            城市map:<input type="text" name="map['one'].city">            <br> <br>
    
            <input type="submit" value="封装集合数据的测试">
        </form>
    </body>
    </html>
    
    

    测试结果:
    在这里插入图片描述
    在这里插入图片描述

请求参数绑定(三)请求参数乱码

实现

Spring提供了统一的编码过滤器,解决提交数据中文乱码问题。

在web.xml中配置编码过滤器:CharacterEncodingFilter

	<!--配置SpringMVC提供的编码过滤器,解决请求数据中文乱码问题。-->
	<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. get提交,默认无问题,前提:tomcat7以上版本。
  2. post 默认会出现乱码
  3. 配置CharacterEncodingFilter, 可以解决所有中文数据乱码问题。

请求参数绑定(四)@RequestParam实现参数绑定

@RequestParam

  1. 应用场景:当请求参数名称与方法形参不一致时候使用
  2. 建立请求参数与方法形参的映射关系

实现

    /**
     * 请求参数绑定(四)@RequestParam实现参数绑定
     * 请求地址:http://localhost:8080/user/search.do?username=Jack
     * @RequestParam
     *  1. 当请求参数名称与方法形参名称不一致使用使用;
     *  2. 属性
     *     value  对应请求参数名称
     *     required 必须要传递该参数,否则报错.
     *     defaultValue 给参数默认值。
     */
    @RequestMapping("/search")
    public String search(@RequestParam(value = "username",required = true,defaultValue = "匿名") String uname){
        System.out.println("uname = " + uname);
        return "success";
    }
  • @RequestParam与@RequestMapping区别:
    • @RequestParam 封装请求参数
    • @RequestMapping 指定请求路径

请求参数绑定(五)自定义类型转换器

实现步骤

第一步:测试能否把请求的字符串参数自动转换为Date日期类型

    /**
     * 请求参数绑定(五)自定义类型转换器
     * 请求地址:http://localhost:8080/user/save.do?birth=1998-09-09
     * 后台方法:public String save(Date birth){}
     * 执行测试:
     *   页面:HTTP Status 400 – Bad Request
     *   日志: Failed to convert value of type 'java.lang.String' to required type 'java.util.Date';
     * 解决?
     *   自定义类型转换器,实现String-->Date
     *     1、写一个类,实现Converter转换器接口
     *     2、springMVC.xml配置转换器工厂
     */
    @RequestMapping("/save")
    public String save(Date birth){
        System.out.println(birth);
        return "success";
    }

第二步:测试,是否报错
在这里插入图片描述
第三步:解决错误,自定义类型转换器

写一个类,实现Converter接口


/**
 *  自定义类型转换器,实现String-->Date
 */
@Component // 创建对象,加入容器 (注意:包扫描要扫描到此注解)
public class StringToDateConverter implements Converter<String,Date>{
    @Override
    public Date convert(String source) {
        try {
            // 校验 (调用工具类的判断为空的方法)
            if (StringUtils.isEmpty(source)){
                return null;
            }

            // 转换
            return new SimpleDateFormat("yyyy-MM-dd").parse(source);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }
}

配置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:context="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">

    <!--1. 注解扫描-->
    <context:component-scan base-package="xxx.xxx"/>

    <!--2. 视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--配置跳转路径的前缀-->
        <property name="prefix" value="/pages/"/>
        <!--配置跳转路径的后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--3. 开启注解驱动(自动创建springmvc的处理器映射器、处理器适配器)-->
    <mvc:annotation-driven conversion-service="conversionServiceFactory"/>

    <!--4. 配置转换器的工厂-->
    <bean id="conversionServiceFactory"
          class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <!--注入自定义的转换器类(引用容器中指定名称的bean)-->
                <ref bean="stringToDateConverter"/>
            </set>
        </property>
    </bean>
</beans>

请求参数绑定(六)servletApi对象作为方法参数

第一步:添加依赖

    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>

第二步:编写控制器类

编写控制器类,servletApi作为方法参数


@Controller
public class ServletApiController {

    /**
     * ServletApi作为方法参数
     * 请求地址:http://localhost:8080/servletApi.do?id=100
     */
    @RequestMapping("/servletApi")
    public void servletApi(Integer id, HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("SpringMVC封装的请求数据:" + id);
        System.out.println("通过request对象获取请求数据:" + request.getParameter("id"));

        // 重定向
        //response.sendRedirect("http://localhost:8080/pages/success.jsp");
        response.sendRedirect("/pages/success.jsp");
    }
}

什么情况下需要使用ServletApi?
|-- 举例:文件下载,必须要用到resposne对象,设置下载响应头..
|-- 获取访问者的ip地址。request.getRemoteAddr()

消息头、消息体相关的注解

获取请求信息

获取请求信息:

  • @RequestHeader 获取请求头

  • @CookieValue 获取cookie值

  • @RequestBody 获取请求体(post提交)

示例

@Controller
public class RequestController {

    /**
     * @RequestHeader  获取请求头的值
     */
    @RequestMapping("/requestHeader")
    public String requestHeader(@RequestHeader("host") String host){
        System.out.println("host = " + host);
        return "success";
    }


    /**
     * @CookieValue  获取指定key的cookie的值
     */
    @RequestMapping("/CookieValue")
    public String cookieValue(@CookieValue("JSESSIONID") String jsessionid){
        System.out.println("cookie中JSESSIONID这个key对应的值是:" + jsessionid);
        return "success";
    }

    /**
     * @RequestBody 获取请求体
     */
    @RequestMapping("/requestBody")
    public String requestBody(@RequestBody String requestBody){
        // name=jack&age=28
        System.out.println(requestBody);
        return "success";
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值