SpringMVC核心技术与简单使用

SpringMVC

1、SpringMVC的概述

  • 是一种基于Java实现的MVC设计模型的请求驱动类型的轻量级WEB框架
  • Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块
  • 使用 Spring 可插入的 MVC 架构,从而在使用Spring进行WEB开发时,可以选择使用Spring的SpringMVC框架或集成其他MVC开发框架

2、SpringMVC的入门程序

步骤(七步)

  • 第一步:创建WEB工程,引入开发的jar包

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
    
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
    
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </dependency>
    
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
    
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
    
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-client</artifactId>
            <version>1.19.4</version>
        </dependency>
    
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-core</artifactId>
            <version>1.19.4</version>
        </dependency>
    </dependencies>
    
  • 第二步:配置前端控制器(配置DispatcherServlet)

    • 在web.xml配置文件中配置前端控制器 DispatcherServlet

      <!--前端控制器  org.springframework.web.servlet.DispatcherServlet-->
      <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>/</url-pattern>
      </servlet-mapping>
      
  • 第三步:编写springmvc.xml的配置文件

    • 在 resources 目录下创建 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
              https://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
              http://www.springframework.org/schema/mvc/spring-mvc.xsd">
      
          <!-- 开启注解扫描 -->
          <context:component-scan base-package="com.itfzk.springmvc01"></context:component-scan>
      
          <!--视图解析器对象-->
          <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <!-- 前缀(路径) -->
              <property name="prefix" value="/WEB-INF/springmvc/"></property>
              <!-- 后缀 -->
              <property name="suffix" value=".jsp"></property>
          </bean>
          
          <!--开启 SpringMVC 注解的支持-->
          <mvc:annotation-driven />
      </beans>
      
  • 第四步:编写index.jsp

    <body>
        <!-- springmvc01 是 springmvcJava01.java 中 @RequestMapping(path = "/springmvc01") 注解中的 springmvc01 -->
        <a href="springmvc01">点击入门</a>
    </body>
    
  • 第五步:编写 Controller 控制器类 (springmvcJava01.java)

    @Controller
    public class springmvcJava01 {
        @RequestMapping(path = "/springmvc01")  //建立请求 URL 和处理请求方法之间的对应关系
        public String springmvc01(){
            // 返回的是以 springmvc01.xml 中的 InternalResourceViewResolver 前缀 + 返回值 + 后缀 组成的路径文件
            return "success";
        }
    }
    
  • 第六步:在 WEB-INF 目录下创建 springmvc文件夹,编写 success.jsp 的成功页面

    <body>
        <h3>入门成功</h3>
    </body>
    
  • 第七步:启动Tomcat服务器,进行测试

入门案例的执行过程分析

  • 入门案例的执行流程
    • 1、当启动Tomcat服务器的时候,因为配置了load-on-startup标签,所以会创建DispatcherServlet对象,就会加载springmvc.xml配置文件
    • 2、开启了注解扫描,那么 springmvcJava01 对象就会被创建
    • 3、从index.jsp发送请求,请求会先到达DispatcherServlet核心控制器,根据配置@RequestMapping注解找到执行的具体方法
    • 4、根据执行方法的返回值,再根据配置的视图解析器,去指定的目录下查找指定名称的JSP文件
    • 5、Tomcat服务器渲染页面,做出响应
  • 入门案例中的组件分析
    • 前端控制器(DispatcherServlet)
    • 处理器映射器(HandlerMapping)
    • 处理器(Handler)
    • 处理器适配器(HandlAdapter)
    • 视图解析器(View Resolver)
    • 视图(View)

3、@RequestMapping注解

  • 作用 :

    • 建立请求URL和处理方法之间的对应关系
  • 可用地方 :

    • 方法和类
      • 作用在类上:第一级的访问目录
      • 作用在方法上:第二级的访问目录
    • 细节 :
      • 路径可以不编写 / 表示应用的根目录开始
      • ${ pageContext.request.contextPath }也可以省略不写,但是路径上不能写 /
    • 属性 :
      • path :用于指定请求的URL
      • value :它和path属性的作用是一样的
      • method :用于指定请求的方式(GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE)
      • params :用于指定限制请求参数的条件。它支持简单的表达式
      • headers :用于指定限制请求消息头的条件

    jsp文件

    <body>
        <!-- springmvc01 是 springmvcJava01.java 中 @RequestMapping(path = "/springmvc01") 注解中的 springmvc01 -->
        <a href="fzk01/springmvc01">点击入门</a>
    </body>
    

    Controller类

    @Controller
    @RequestMapping(path = "/fzk01")  //可不写这个注解,如果写上,建立请求 URL 前面要加上 user(<a href="fzk01/springmvc01">)
    public class springmvcJava01 {
        @RequestMapping(path = "/springmvc01")  //建立请求 URL 和处理请求方法之间的对应关系
        public String springmvc01(){
            // 返回的是以 springmvc01.xml 中的 InternalResourceViewResolver 前缀 + 返回值 + 后缀 组成的路径文件
            return "springmvcJsp01";
        }
    }
    

4、请求参数的绑定

请求参数的绑定支持的数据类型

基本数据类型和字符串类型
  • 提交表单的name和参数的名称是相同的

  • 区分大小写

    jsp文件

    <body>
        <!-- 请求参数绑定 : 基本数据类型和字符串类型 -->
        <a href="fzk02/springmvc02?username=fzk&password=123">提交</a>
    </body>
    

    Controller类

    @Controller
    @RequestMapping(path = "/fzk02")
    public class springmvcJava02 {
        /**
         * 请求参数绑定 : 基本数据类型和字符串类型
         */
        @RequestMapping(path = "/springmvc02")
        public String springmvc02(String username, String password){
            System.out.println("执行。。。");
            System.out.println("用户名:" + username);
            System.out.println("密码:" + password);
            return "springmvcJsp01";
        }
    }
    
实体类型(JavaBean)
  • 提交表单的name和JavaBean中的属性名称需要一致

  • 如果一个JavaBean类中包含其他的引用类型,那么表单的name属性需要编写成:对象.属性

    Javabean类(User.java、Account.java)

    //User.java
    public class User implements Serializable {
        private String username;
        private String password;
        private Account account;
    
        public Account getAccount() {
            return account;
        }
    
        public void setAccount(Account account) {
            this.account = account;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "username='" + username + '\'' +
                    ", password='" + password + '\'' +
                    ", account=" + account +
                    '}';
        }
    }
    
    
    //Account.java
    public class Account implements Serializable {
        private String accountName;
        private String accountPrice;
    
        public String getAccountName() {
            return accountName;
        }
    
        public void setAccountName(String accountName) {
            this.accountName = accountName;
        }
    
        public String getAccountPrice() {
            return accountPrice;
        }
    
        public void setAccountPrice(String accountPrice) {
            this.accountPrice = accountPrice;
        }
    
        @Override
        public String toString() {
            return "Account{" +
                    "accountName='" + accountName + '\'' +
                    ", accountPrice='" + accountPrice + '\'' +
                    '}';
        }
    }
    

    jsp文件

    <body>
        <!-- 请求参数绑定 :实体类型( JavaBean ) -->
        <form action="fzk02/springmvcJavaBeanPlus" method="post">
            用户名:<input type="text" name="username" />  <br/>
            密码:<input type="text" name="password" /> <br/>
            账户名称:<input type="text" name="account.accountName"/><br/>
            账户价格:<input type="text" name="account.accountPrice"/><br/>
            <input type="submit" value="提交">
        </form>
    </body>
    

    Controller类

    @Controller
    @RequestMapping(path = "/fzk02")
    public class springmvcJava02 {
       /**
         * 请求参数绑定 :实体类型( JavaBean )
         */
        @RequestMapping(path = "/springmvcJavaBeanPlus")
        public String springmvcJavaBeanPlus(User user){
            System.out.println(user);
            return "springmvcJsp01";
        }
    }
    
集合数据类型(List、map集合等)
  • JSP页面编写方式:list[0].属性

  • Javabean类(User.java、Account.java)

    //User.java
    public class User implements Serializable {
        private String username;
        private String password;
        private List<Account> listAccount;
        private Map<String, Account> mapAccount;
    
        public List<Account> getListAccount() {
            return listAccount;
        }
    
        public void setListAccount(List<Account> listAccount) {
            this.listAccount = listAccount;
        }
    
        public Map<String, Account> getMapAccount() {
            return mapAccount;
        }
    
        public void setMapAccount(Map<String, Account> mapAccount) {
            this.mapAccount = mapAccount;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "username='" + username + '\'' +
                    ", password='" + password + '\'' +
                    ", listAccount=" + listAccount +
                    ", mapAccount=" + mapAccount +
                    '}';
        }
    }
    
    
    //Account.java
    public class Account implements Serializable {
        private String accountName;
        private String accountPrice;
    
        public String getAccountName() {
            return accountName;
        }
    
        public void setAccountName(String accountName) {
            this.accountName = accountName;
        }
    
        public String getAccountPrice() {
            return accountPrice;
        }
    
        public void setAccountPrice(String accountPrice) {
            this.accountPrice = accountPrice;
        }
    
        @Override
        public String toString() {
            return "Account{" +
                    "accountName='" + accountName + '\'' +
                    ", accountPrice='" + accountPrice + '\'' +
                    '}';
        }
    }
    

    jsp文件

    <body>
        <!-- 请求参数绑定 :集合数据类型(List、map集合等) -->
        <h3>请求参数绑定 :集合数据类型(List、map集合等)</h3>
        <form action="fzk02/springmvcJavaBeanListAndMap" method="post">
            用户名:<input type="text" name="username" />  <br/>
            密码:<input type="text" name="password" /> <br/>
            账户名称:<input type="text" name="listAccount[0].accountName"/><br/>
            账户价格:<input type="text" name="listAccount[0].accountPrice"/><br/>
            账户名称:<input type="text" name="listAccount[1].accountName"/><br/>
            账户价格:<input type="text" name="listAccount[1].accountPrice"/><br/>
            账户名称:<input type="text" name="mapAccount['one'].accountName"/><br/>
            账户价格:<input type="text" name="mapAccount['one'].accountPrice"/><br/>
            账户名称:<input type="text" name="mapAccount['two'].accountName"/><br/>
            账户价格:<input type="text" name="mapAccount['two'].accountPrice"/><br/>
            <input type="submit" value="提交">
        </form>
    </body>
    

    Controller类

    @Controller
    @RequestMapping(path = "/fzk02")
    public class springmvcJava02 {
        /**
         * 请求参数绑定 :集合数据类型(List、map集合等)
         */
        @RequestMapping(path = "/springmvcJavaBeanListAndMap")
        public String springmvcJavaBeanListAndMap(User user){
            System.out.println(user);
            return "springmvcJsp01";
        }
    }
    

请求参数中文乱码的解决

  • 在web.xml中配置Spring提供的过滤器类 CharacterEncodingFilter

    <!--配置解决中文乱码的过滤器-->
    <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>
    

自定义类型转换器

  • 表单提交的任何数据类型全部都是字符串类型,但是后台定义Integer类型,数据也可以封装上,说明Spring框架内部会默认进行数据类型转换

  • 如果想自定义数据类型转换,可以实现Converter的接口

  • 自定义类型转换(String --> Date)

    • 第一步:编写自定义数据类型转换类,实现Converter的接口

      public class StringToDateConverter implements Converter<String, Date> {
          @Override
          public Date convert(String source) {
              if(source == null){
                  throw new RuntimeException("请输入时间");
              }
              SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
              try {
                  return simpleDateFormat.parse(source);
              } catch (ParseException e) {
                  throw new RuntimeException("数据类型转换失败");
              }
          }
      }
      
      
    • 注册自定义类型转换器,在springmvc.xml配置文件中编写配置

      <!-- 配置自定义类型转换器 -->
      <bean id="conversionServiceFactoryBean" class="org.springframework.context.support.ConversionServiceFactoryBean">
          <property name="converters">
              <set>
                  <bean class="com.itfzk.utils.StringToDateConverter"></bean>
              </set>
          </property>
      </bean>
      <!--开启 SpringMVC 注解的支持-->
      <mvc:annotation-driven conversion-service="conversionServiceFactoryBean" />
      

在控制器中使用原生的ServletAPI对象

  • 只需要在控制器的方法参数定义HttpServletRequest和HttpServletResponse对象

    jsp文件

    <body>
        <!-- 获取 Servlet原生的 API -->
        <a href="fzk02/springmvcGetServletAPI">提交</a>
    </body>
    

    Controller类

    @Controller
    @RequestMapping(path = "/fzk02")
    public class springmvcJava02 {
        /**
         * 获取 Servlet原生的 API
         */
        @RequestMapping(path = "/springmvcGetServletAPI")
        public String springmvcServletAPI(HttpServletRequest request, HttpServletResponse response){
            System.out.println("request:" + request);
            HttpSession session = request.getSession();
            System.out.println("session:" + session);
            ServletContext servletContext = session.getServletContext();
            System.out.println("servletContext:" + servletContext);
            System.out.println("response:" + response);
            return "springmvcJsp01";
        }
    }
    

5、常用的注解

@RequestParam

  • 作用:

    • 把请求中指定名称的参数给控制器中的形参赋值。
  • 属性:

    • value:请求参数中的名称
    • required:请求参数中是否必须提供此参数。默认值: true。 表示必须提供,如果不提供将报错。
  • 代码

    jsp

    <!-- RequestParam注解-->
    <a href="fzk03/springmvcRequestParam?name=fzk">提交</a>
    

    Controller类

    @Controller
    @RequestMapping(path = "/fzk03")
    public class springmvcJava03 {
        @RequestMapping(path = "/springmvcRequestParam")
        public String springmvcRequestParam(@RequestParam(value = "name") String username){
            System.out.println(username);
            return "springmvcJsp01";
        }
    }
    

@RequestBody

  • 作用

    • 用于获取请求体内容。直接使用得到是key=value&key=value… .结构的数据。(username=fzk&password=123)
      get请求方式不适用。
  • 属性:

    • required:请求参数中是否必须提供此参数。默认值: true。 表示必须提供,如果不提供将报错。
  • 代码

    jsp

    <!-- RequestBody注解 -->
    <form action="fzk03/springmvcRequestBody" method="post">
        用户名:<input type="text" name="username" />  <br/>
        密码:<input type="text" name="password" /> <br/>
        <input type="submit" value="提交">
    </form>
    

    Controller类

    @Controller
    @RequestMapping(path = "/fzk03")
    public class springmvcJava03 {
        @RequestMapping(path = "/springmvcRequestBody")
        public String springmvcRequestBody(@RequestBody String body){
            System.out.println(body);
            return "springmvcJsp01";
        }
    }
    

@PathVariable

  • 作用

    • 用于绑定 url 中的占位符。例如:请求 url 中 /springmvcPathVariable/{id}, 这个 {id} 就是 url 占位符
  • 属性:

    • value:用于指定url中占位符名称
    • required:请求参数中是否必须提供此占位符。默认值: true。
  • 代码

    jsp

    <!-- PathVariable注解-->
    <a href="fzk03/springmvcPathVariable/10">提交</a>
    

    Controller类

    @Controller
    @RequestMapping(path = "/fzk03")
    public class springmvcJava03 {
        @RequestMapping(path = "/springmvcPathVariable/{id}")
        public String springmvcPathVariable(@PathVariable(value = "id") String id){
            System.out.println(id);
            return "springmvcJsp01";
        }
    }
    

@RequestHeader

  • 作用

    • 获取指定请求头的值
  • 属性:

    • value: 请求头的名称
    • required:请求参数中是否必须提供此消息头。默认值: true。
  • 代码

    jsp

    <!-- RequestHeader注解-->
    <a href="fzk03/springmvcRequestHeader">提交</a>
    

    Controller类

    @Controller
    @RequestMapping(path = "/fzk03")
    public class springmvcJava03 {
        @RequestMapping(path = "/springmvcRequestHeader")
        public String springmvcRequestHeader(@RequestHeader(value = "Accept") String str){
            System.out.println(str);
            return "springmvcJsp01";
        }
    }
    

@CookieValue

  • 作用

    • 用于获取指定cookie的名称的值
  • 属性:

    • value: cookie的名称
    • required:是否必须有此cookie。默认值: true。
  • 代码

    jsp

    <!-- CookieValue注解-->
    <a href="fzk03/springmvcCookieValue">提交</a>
    

    Controller类

    @Controller
    @RequestMapping(path = "/fzk03")
    public class springmvcJava03 {
        @RequestMapping(path = "/springmvcCookieValue")
        public String springmvcCookieValue(@CookieValue(value = "JSESSIONID") String cookieValue){
            System.out.println(cookieValue);
            return "springmvcJsp01";
        }
    }
    

@ModelAttribute

  • 作用
    • 用于修饰方法和参数。
    • 出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可以修饰有具体返回的方法。
    • 出现在参数上,获取指定的数据给参数赋值。
  • 属性
    • value: 用于获取数据的key。key 可以是POJO的属性名称,也可以是map结构的key
  • 应用场景
    • 当表单提交数据不是完整的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据。
方法一:有返回值

jsp

<!-- ModelAttribute注解 -->
<form action="fzk03/springmvcModelAttribute" method="post">
    用户名:<input type="text" name="username" />  <br/>
    密码:<input type="text" name="password" /> <br/>
    <input type="submit" value="提交">
</form>

Controller类

@Controller
@RequestMapping(path = "/fzk03")
public class springmvcJava03 {
    @RequestMapping(path = "/springmvcModelAttribute")
    public String springmvcModelAttribute(User user){
        System.out.println(user);
        return "springmvcJsp01";
    }
    //模拟数据库
    @ModelAttribute
    public User testModelAttribute(User user){
        return user;
    }
}
方法二:没有返回值

jsp

<!-- ModelAttribute注解 -->
<form action="fzk03/springmvcModelAttribute" method="post">
    用户名:<input type="text" name="username" />  <br/>
    密码:<input type="text" name="password" /> <br/>
    <input type="submit" value="提交">
</form>

Controller类

@Controller
@RequestMapping(path = "/fzk03")
public class springmvcJava03 {
    @RequestMapping(path = "/springmvcModelAttribute")
    public String springmvcModelAttribute(@ModelAttribute(value = "abc") User user){
        System.out.println(user);
        return "springmvcJsp01";
    }
    //模拟数据库
    @ModelAttribute
    public void testModelAttribute(User user, Map<String, User> map){
        map.put("abc", user);
    }
}

@SessionAttributes

  • 作用

    • 用于多次执行控制器方法间的参数共享
  • 属性

    • value : 用于指定存入的属性名称
    • type: 用于指定存入的数据类型
  • 代码

    jsp

    <!-- SessionAttributes注解-->
    <!-- 存入数据 -->
    <a href="fzk03/springmvcSessionAttributes">set</a>
    <!-- 获取数据 -->
    <a href="fzk03/springmvcGetSessionAttributes">get</a>
    

    Controller类

    @Controller
    @RequestMapping(path = "/fzk03")
    @SessionAttributes(value = "fzk", types = String.class)  //存入的属性名称,数据类型
    public class springmvcJava03 {
        //存入数据
        @RequestMapping(path = "/springmvcSessionAttributes")
        public String springmvcSessionAttributes(Model model){
            model.addAttribute("fzk", "123");
            return "springmvcJsp01";
        }
        //获取数据
        @RequestMapping(path = "/springmvcGetSessionAttributes")
        public String springmvcGetSessionAttributes(Model model){
            Object fzk = model.getAttribute("fzk");
            System.out.println(fzk);
            return "springmvcJsp01";
        }
    }
    

6、响应数据和结果视图

返回值分类

返回字符串
  • Controller方法返回字符串可以指定逻辑视图的名称,根据视图解析器为物理视图的地址

    @Controller
    @RequestMapping(path = "/fzk04")
    public class springmvcJava04 {
        /**
         * 返回值:字符串(String)
         */
        @RequestMapping(path = "/springmvcString")
        public String springmvcString(Model model){
            //模拟数据库查询 User对象
            User user = new User();
            user.setUsername("fzk");
            user.setPassword("123");
            //model 对象
            model.addAttribute("user", user);
            return "springmvcJsp01";
        }
    }
    

    springmvcJsp01.jsp

    ${user.username}
    ${user.password}
    
返回值是void (转发,重定向,直接相应)
  • 可以使用请求转发或者重定向跳转到指定的页面

    Controller类

    @Controller
    @RequestMapping(path = "/fzk04")
    public class springmvcJava04 {
        /**
         * 返回值:void
         */
        @RequestMapping(path = "/springmvcVoid")
        public void springmvcVoid(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            User user = new User();
            user.setUsername("fzk");
            user.setPassword("123");
            //1、转发
            request.getRequestDispatcher("/WEB-INF/springmvc/springmvcJsp01.jsp").forward(request, response);
            //2、重定向
            response.sendRedirect(request.getContextPath() + "/fzk03.jsp");
            //3、直接响应
            response.getWriter().print("fzk");
        }
    }
    
返回值是ModelAndView对象
  • ModelAndView对象是Spring提供的一个对象,可以用来调整具体的JSP视图

    Controller类

    @Controller
    @RequestMapping(path = "/fzk04")
    public class springmvcJava04 {
        @RequestMapping(path = "/springmvcModelAndView")
        public ModelAndView springmvcModelAndView(){
            //模拟数据库查询 User对象
            User user = new User();
            user.setUsername("fzk");
            user.setPassword("123");
            //创建 ModelAndView对象
            ModelAndView mv = new ModelAndView();
            //把 User对象存储到 mv 中,也会把 user 对象存入到 request对象
            mv.addObject("user", user);
            //使用视图解析器跳转到该页面
            mv.setViewName("springmvcJsp01");
            return mv;
        }
    }
    

    springmvcJsp01.jsp

    ${user.username}
    ${user.password}
    

SpringMVC框架提供的转发和重定向

forward请求转发
  • 使用:“forward:转发的JSP路径”

  • 不走视图解析器了,所以需要编写完整的路径

    Controller类

    @Controller
    public class springmvcJava04 {
        @RequestMapping(path = "/test8")
        public String test11() {
            //转发
            return "forward:WEB-INF/springmvc/success.jsp";
        }
    }
    
redirect重定向
@Controller
public class springmvcJava04 {
    @RequestMapping(path = "/test11")
    public String test11() {
        //重定向
        return "redirect:index.jsp";
    }
}

静态资源不过滤

  • DispatcherServlet会拦截到所有的资源,导致一个问题就是静态资源(img、css、js)也会被拦截到

  • 设置静态资源不过滤

    • mvc:resources标签配置不过滤

      • mapping:以 /css 开头的所有请求路径,如 /css/a 或者 /css/a/b
      • location:webapp目录下的包下的所有文件
    • 在springmvc.xml配置文件添加如下配置

      <!-- 前端控制器,设置静态资源不过滤 -->
      <mvc:resources mapping="/css/" location="/css/**"></mvc:resources>
      <mvc:resources mapping="/js/" location="/js/**"></mvc:resources>
      <mvc:resources mapping="/image/" location="/image/**"></mvc:resources>
      

7、SpringMVC实现文件上传

  • JSP文件格式:
    • 1、form表单
      • enctype:
        • 取值必须是:multipart/ form-data(默认值是:application/x-www- form-urlencoded)
        • enctype:是表单请求正文的类型
    • 2、method 属性取值必须是Post
    • 3、提供一个文件选择域<input type=“file” name="…" />

普通文件上传

导入文件上传的jar包

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>

编写文件上传的JSP页面

<!-- 普通文件上传 -->
<form action="fzk05/springmvcFileUpload" method="post" enctype="multipart/form-data">
    选择文件:<input type="file" name="fileupload"/><br>
    <input type="submit" value="提交"/>
</form>

编写文件上传的Controller控制器

@Controller
@RequestMapping(path = "/fzk05")
public class springmvcJava05 {
    /**
     * 普通文件上传
     */
    @RequestMapping(path = "/springmvcFileUpload")
    public String springmvcFileUpload(HttpServletRequest request) throws Exception {
        //获取上传的位置
        String realPath = request.getSession().getServletContext().getRealPath("/fileupload/");
        File file = new File(realPath);
        //不存在该文件位置
        if(!file.exists()){
            file.mkdirs();  //创建该位置
        }
        //解析 request 对象,获取上传文件项
        DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
        ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
        //解析 request
        List<FileItem> fileItems = servletFileUpload.parseRequest(request);
        //遍历
        for(FileItem fileItem : fileItems){
            //普通表单项
            if (fileItem.isFormField()){
               
            }else {  //上传的文件项
                //获取表单项的名称
                String fileItemName = fileItem.getName();
                //把文件名设为唯一值
                String uuid = UUID.randomUUID().toString();
                fileItemName = uuid + "_" + fileItemName;
                //文件的上传
                fileItem.write(new File(realPath, fileItemName));
                //删除临时文件
                fileItem.delete();
            }
        }
        return "success";
    }
}

SpringMVC文件上传

  • SpringMVC框架提供了MultipartFile对象,该对象表示上传的文件
    • 要求:变量名称必须和表单file标签的name属性名称相同
      • MultipartFile upload 中的 upload 与 JSP 中的 <input type=“file” name=“upload” /> name属性名称相同

编写文件上传的Controller控制器

@Controller
@RequestMapping(path = "/fzk05")
public class springmvcJava05 {
    /**
     * SpringMVC 文件上传
     * 在 springmvc01.xml 中配置文件解析器
     * 使用 MultipartFile 对象
     * 要保证 MultipartFile upload 中的 upload 与 JSP 中的 <input type="file" name="upload" /> name属性名称相同
     */
    @RequestMapping(path = "/springmvcSpringMVCFileUpload")
    public String springmvcSpringMVCFileUpload(HttpServletRequest request, MultipartFile upload) throws Exception {
        //获取上传的位置
        String realPath = request.getSession().getServletContext().getRealPath("/fileupload/");
        File file = new File(realPath);
        //不存在该文件位置
        if(!file.exists()){
            file.mkdirs();  //创建该位置
        }
        //解析 request 对象,获取上传文件项,在 springmvc01.xml 中配置文件解析器
        //获取文件的名称
        String fileItemName = upload.getOriginalFilename();
        //把文件名设为唯一值
        String uuid = UUID.randomUUID().toString();
        fileItemName = uuid + "_" + fileItemName;
        //文件的上传
        upload.transferTo(new File(realPath, fileItemName));
        return "success";
    }
}

配置文件解析器对象

<!-- 配置文件解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="10485760"></property> <!-- value = 10M -->
</bean>

SpringMVC跨服务器文件上传

导入开发需要的jar包

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-client</artifactId>
    <version>1.19.4</version>
</dependency>
<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-core</artifactId>
    <version>1.19.4</version>
</dependency>

编写文件上传的JSP页面

<!-- 跨服务器文件上传 -->
<h3>跨服务器文件上传</h3>
<form action="fzk05/springmvcWebFileUpload" method="post" enctype="multipart/form-data">
    选择文件:<input type="file" name="upload" /><br>
    <input type="submit" value="提交"/>
</form>

编写文件上传的Controller控制器

@Controller
@RequestMapping(path = "/fzk05")
public class springmvcJava05 {
    /**
     * 跨服务器文件上传
     */
    @RequestMapping(path = "/springmvcWebFileUpload")
    public String springmvcWebFileUpload(HttpServletRequest request, MultipartFile upload) throws Exception {
        //定义上传文件服务器的路径
        String path = "http://localhost:9999/springmvcFileupload/fileupload/";
        //解析 request 对象,获取上传文件项,在 springmvc01.xml 中配置文件解析器
        //获取文件的名称
        String fileItemName = upload.getOriginalFilename();
        //把文件名设为唯一值
        String uuid = UUID.randomUUID().toString();
        fileItemName = uuid + "_" + fileItemName;
        //创建客户端对象
        Client client = Client.create();
        //与图片服务器连接
        WebResource webResource = client.resource(path + fileItemName);
        //文件的上传
        webResource.put(upload.getBytes());
        return "success";
    }
}

配置文件解析器对象

<!-- 配置文件解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="10485760"></property> <!-- value = 10M -->
</bean>

8、SpringMVC的异常处理

  • Controller调用service,service调用dao,异常都是向上抛出的,最终有DispatcherServlet找异常处理器进
    行异常的处理
  • 抛出异常及异常处理器
    在这里插入图片描述

Controller类

@Controller
@RequestMapping(path = "fzk06")
public class springmvcJava06 {
    @RequestMapping(path = "springmvcSysException")
    public String springmvcSysException() throws Exception {
        System.out.println("springmvcSysException");
        try {
            //模拟异常
            int i = 10 / 0;
        } catch (Exception e) {
            //打印异常消息
            e.printStackTrace();
            //抛出自定义异常
            throw new SysException("查询信息出错");
        }
        return "success";
    }
}

自定义异常类

public class SysException extends Exception {
    private String message;

    public SysException(String message) {
        this.message = message;
    }

    @Override
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

自定义异常处理器

public class SysExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        //获取异常对象
        SysException e;
        if(ex instanceof SysException){
            e = (SysException) ex;
        }else{
            e = new SysException("系统正在维护");
        }
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("error", e.getMessage());
        modelAndView.setViewName("error");
        return modelAndView;
    }
}

配置异常处理器

<!-- 配置异常处理器 -->
<bean id="sysExceptionResolver" class="com.itfzk.exception.SysExceptionResolver"></bean>

9、SpringMVC框架中的拦截器

拦截器的概述

  • SpringMVC框架中的拦截器用于对处理器进行预处理和后处理的技术。
  • 可以定义拦截器链,连接器链就是将拦截器按着一定的顺序结成一条链,在访问被拦截的方法时,拦截器链中的拦截器会按着定义的顺序执行。
  • 拦截器和过滤器的功能比较类似,有区别
    • 过滤器是Servlet规范的一部分,任何框架都可以使用过滤器技术。
    • 拦截器是SpringMVC框架独有的。
    • 过滤器配置了/*,可以拦截任何资源。
    • 拦截器只会对控制器中的方法进行拦截。
  • 拦截器也是AOP思想的一种实现方式
  • 想要自定义拦截器,需要实现HandlerInterceptor接口

自定义拦截器步骤

  • 第一步:创建类,实现HandlerInterceptor接口,重写需要的方法

    public class MyInterceptor01 implements HandlerInterceptor {
        /**
         * 预处理方法(运行 Controller 前执行)
         * @return  true:放行, false:不放行
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle111");
            //转发到其他页面后之前的页面将不再执行(配合 return false 使用)
    //        request.getRequestDispatcher("/WEB-INF/springmvc/error.jsp").forward(request, response);
            return true;
        }
    
        /**
         * 后处理方法(运行 Controller 后执行)
         */
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle111");
        }
    
        /**
         * 最后执行方法(JSP 页面显示了再执行)
         */
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("afterCompletion111");
        }
    }
    
  • 第二步:在springmvc.xml中配置拦截器类

    <!-- 配置拦截器 -->
    <mvc:interceptors>
        <!-- 配置拦截器 -->
        <mvc:interceptor>
            <!-- 要拦截的方法 -->
            <mvc:mapping path="/fzk07/*"/>
            <!-- 不拦截的方法
                <mvc:exclude-mapping path=""/>
                -->
            <!-- 拦截后的操作 -->
            <bean class="com.itfzk.interceptor.MyInterceptor01"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
    

HandlerInterceptor接口中的方法

  • preHandle方法是controller方法执行前拦截的方法
    • 可以使用request或者response跳转到指定的页面
    • return true放行,执行下一个拦截器,如果没有拦截器,执行controller中的方法。
    • return false不放行,不会执行controller中的方法。
  • postHandle是controller方法执行后执行的方法,在JSP视图执行前。
    • 可以使用request或者response跳转到指定的页面
    • 如果指定了跳转的页面,那么controller方法跳转的页面将不会显示。
  • afterCompletion方法是在JSP执行后执行
    • request或者response不能再跳转页面了

配置多个拦截器

  • 第一步:编写两个拦截器的类

    //第一个拦截器
    public class MyInterceptor01 implements HandlerInterceptor {
        /**
         * 预处理方法(运行 Controller 前执行)
         * @return  true:放行, false:不放行
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle111");
            //转发到其他页面后之前的页面将不再执行(配合 return false 使用)
    //        request.getRequestDispatcher("/WEB-INF/springmvc/error.jsp").forward(request, response);
            return true;
        }
    
        /**
         * 后处理方法(运行 Controller 后执行)
         */
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle111");
        }
    
        /**
         * 最后执行方法(JSP 页面显示了再执行)
         */
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("afterCompletion111");
        }
    }
    
    
    //第二个拦截器
    public class MyInterceptor02 implements HandlerInterceptor {
        /**
         * 预处理方法(运行 Controller 前执行)
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle222");
            return true;
        }
    
        /**
         * 后处理方法(运行 Controller 后执行)
         */
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle222");
        }
    
        /**
         * 最后执行方法(JSP 页面显示了再执行)
         */
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("afterCompletion222");
        }
    }
    
  • 第二步:在springmvc.xml中配置拦截器类

    <!-- 配置拦截器 -->
    <mvc:interceptors>
        <!-- 配置拦截器 -->
        <mvc:interceptor>
            <!-- 要拦截的方法 -->
            <mvc:mapping path="/fzk07/*"/>
            <!-- 不拦截的方法
                <mvc:exclude-mapping path=""/>
                -->
            <!-- 拦截后的操作 -->
            <bean class="com.itfzk.interceptor.MyInterceptor01"></bean>
        </mvc:interceptor>
    
        <!-- 配置第二个拦截器 -->
        <mvc:interceptor>
            <!-- 要拦截的方法 -->
            <mvc:mapping path="/**"/>
            <!-- 不拦截的方法
                <mvc:exclude-mapping path=""/>
                -->
            <!-- 拦截后的操作 -->
            <bean class="com.itfzk.interceptor.MyInterceptor02"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值