SpringMVC框架学习上篇

视频学习:
视频学习链接(点击跳转):
在这里插入图片描述
项目代码:
项目源代码(腾讯云):
链接:https://share.weiyun.com/mRoytxQc 密码:6dd54b

文章完整学习链接:
SpringMVC框架学习上篇
SpringMVC框架学习下篇

一.关于什么是MVC框架

  • 三层架构

三层架构(表现层(UI)、业务逻辑层(BLL)、数据访问层(DAL)),是系统架构设计模式,属于宏观的解决方案,由于原有业务的复杂度提升,客户端和服务器端的职能需要调整,从而实现负载均衡,使系统具有良好的伸缩性。三层架构对原有程序进行了分层,不同的层运行在不同的机器上,所以可以非常自然地支持分布式开发,系统的分布式部署,便于提升系统性能,增加系统功能

在这里插入图片描述

  • MVC架构

MVC(Model View Controller 模型-视图-控制器),是一种软件设计模式,属于微观的解决方案。由于原有业务的复杂度提升,对用户界面进行管理的程序的职责混乱导致代码难以维护。MVC 关注的重点在于表现层的代码组织方式,通过将对数据的操作 M 与对视图V的操作分离开,用C 逻辑作为二者的粘合剂来降低代码间的耦合度,使代码更容易维护

在这里插入图片描述

  • 三层架构和MVC架构的区别

本质上,MVC和三层架构没有可比性,是应用于不同领域的一种模式,三层架构和MVC设计模式侧重点不一样,三层是一种笼统的架构思想,没有限制具体的设计;而MVC就比较具体的说明它的设计方法 。

在这里插入图片描述

在这里插入图片描述

二.关于什么是SpringMVC框架

Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架。

SpringMVC执行原理图:
在这里插入图片描述

  • 发起请求到前端控制器(DispatcherServlet)
  • 前端控制器请求HandlerMapping查找 Handler,可以根据xml配置、注解进行查找
  • 处理器映射器HandlerMapping向前端控制器返回Handler
  • 前端控制器调用处理器适配器去执行Handler
  • 处理器适配器去执行Handler
  • Handler执行完成给适配器返回ModelAndView
  • 处理器适配器向前端控制器返回ModelAndView,ModelAndView是springmvc框架的一个底层对象,包括Model和view
  • 前端控制器请求视图解析器去进行视图解析,根据逻辑视图名解析成真正的视图(jsp)
  • 视图解析器向前端控制器返回View
  • 前端控制器进行视图渲染,视图渲染将模型数据(在ModelAndView对象中)填充到request域
  • 前端控制器向用户响应结果

1.编写第一个SpringMVC程序

项目结构:
在这里插入图片描述

先创建一个Maven的空项目,HelloSpringMVC:
File->New->Project
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在pom.xml中导入Maven依赖:

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>
    <!--Mybatis中资源导出失败解决之build配置-->
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

添加项目的框架支持:
在这里插入图片描述
在这里插入图片描述
项目中就会多了红框框的几个文件:
在这里插入图片描述
在resources中新增一个SpringConfig(springmvc-servlet.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>


    <!-- 视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>

    <bean id="/hello" class="controller.HelloController" />
</beans>

在Java文件中新增一个controller文件,并在controller文件中新增HelloController类并实现Controller接口(这个操作和下面的bean是一一对应的)
在这里插入图片描述
先在java文件下创建一个controller文件
在这里插入图片描述
然后再创建一个HelloController类
在这里插入图片描述
让HelloController类实现Controller接口(选择mvc这个包)
在这里插入图片描述
实现该接口下的handleRequest方法
在这里插入图片描述
在该方法中编写如下代码
在这里插入图片描述
在WEB-INF文件下新建一个JSP文件
在这里插入图片描述
在jsp文件新增一个hello.jsp(注意一定是hello.jsp)
因为这里的hello和下面是一一对应的:
在这里插入图片描述
在hello.jsp中编写如下代码:
在这里插入图片描述
然后对web.xml进行配置,配置信息如下

<!--    注册DispatcherServlet-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--        关联配置文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>
<!--        启动级别-->
        <load-on-startup>1</load-on-startup>
    </servlet>


<!--    /匹配所有,不包括jso-->
<!--    /*匹配,包括jsp-->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

然后启动Tomcat:
在这里插入图片描述
选择+号:
在这里插入图片描述
并选择Local:
在这里插入图片描述
在这里插入图片描述

然后选择Artifact
在这里插入图片描述
在这里插入图片描述
在WEB_INF中创建一个lib并且将依赖导入
在这里插入图片描述

输入lib并将项目的依赖加入到这个文件中去:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
点击apply然后点击ok
在这里插入图片描述

然后运行项目即可:
在这里插入图片描述
在这里插入图片描述
在地址栏输入/hello然后回车

在这里插入图片描述
在这里插入图片描述

2.使用注解实现SpringMVC程序

首先在springmvc-servlet.xml配置文件中导入头文件(context)
在这里插入图片描述

 	   xmlns:context="http://www.springframework.org/schema/context"
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd

相关配置:

    <!-- 自动扫描包,让指定包下的注解生效,由IOC容器统一管理-->
    <context:component-scan base-package="controller"/>

在这里插入图片描述

在Java包中创建HelloController2类
在这里插入图片描述
运行一下:
在这里插入图片描述

三.RestFul 风格

Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

传统方式操作资源和使用RestFul 操作资源

  • 传统方式操作资源 :通过不同的参数来实现不同的效果!方法单一,post 和 get
  • 使用RESTful操作资源 :可以通过不同的请求方式来实现不同的效果!如下:请求地址一样,但是功能可以不同!

1.实例1

需求:
访问这种形式(http://127.0.0.1/item/1/2)的路径(传统方式:http://127.0.0.1/item?num1=1&num2=2)

创建HelloController3类,代码如下:
在这里插入图片描述
运行效果:
在这里插入图片描述

2.实例2

需求:
对于同一个请求根据请求的方式(GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE等)有多种处理方法。
有二种方式实现方式:

  • 方式一通过定义@RequestMapping的method设置请求方式
    @RequestMapping(value = "/item/{num1}/{num2}",method = {
    
    RequestMethod.GET})
    public String hello(Model model, @PathVariable int num1, @PathVariable int num2){
    
    
        //封装数据
        model.addAttribute("msg", num1+"+"+num2+"="+(num1+num2));

        return "hello";
    }

请求方式如下图:
在这里插入图片描述

  • 方式二直接使用对应请求方式的Mapping
    @PostMapping("/item/{num1}/{num2}")
    public String hello2(Model model, @PathVariable int num1, @PathVariable int num2){
    
    
        //封装数据
        model.addAttribute("msg", num1+"+"+num2+"="+(num1+num2));

        return "hello";
    }

注解有以下几种:
@GetMapping get请求
@PostMapping Post请求
@PutMapping put请求
@DeleteMapping Delete请求
@PatchMapping Patch请求

四.转发和重定向

在前面我们通过视图解析器自动拼链接(跳转链接)实现跳转(通过转发方式)
在这里插入图片描述
下图就是当访问/hello的时候转发到/WEB-INF/jsp/hello.jsp路径(这里的hello就是下图方法返回的字符串)
在这里插入图片描述
字符串redirect:/hello实现重定向,不加默认为转发,当然如果加上forward:/hello也表示转发。
在这里插入图片描述

在这里插入图片描述
当然可以不用视图解析器也可以直接实现转发和重定向(不推荐这样使用)
先把视图解析器注释了
在这里插入图片描述
其实就是把路径限定死,不用视图解析器进行拼接
在这里插入图片描述
在这里插入图片描述
但是如果用重定向访问hello.jsp会出错(因为在WEB-INF里的内容重定向是无法访问的)
在这里插入图片描述
在这里插入图片描述

五.数据处理

  • 提交的域名称和处理方法的参数名一致

在HelloController2类中新增一个tohello方法
在这里插入图片描述
运行效果:
在这里插入图片描述

  • 提交的域名称和处理方法的参数名不一致(使用@RequestParam设置名称)
    在这里插入图片描述

运行效果:
在这里插入图片描述
在这里插入图片描述

  • 提交的数据是一个对象

在pom.xml中导入lombok的依赖

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
            <scope>provided</scope>
        </dependency>

创建一个pojo包,在该包下创建一个User类
在这里插入图片描述
HelloController2类中创建tohello2方法
在这里插入图片描述
运行效果:
在这里插入图片描述
备注:前端传递的参数要和User类的字段名一致,如果不一致会返回默认值(未初始化的全局变量的值为对应数据类型的默认值)
在这里插入图片描述

六.数据显示

  • 通过ModelAndView
    在HelloController类中我们就是通过ModeAndView返回数据给前端的
    在这里插入图片描述

  • 通过Model(使用的最多)
    在HelloController2,HelloController3类中对于数据的返回我们都是通过Mode进行返回的,跳转的路径通过return进行返回。
    在这里插入图片描述
    查看Model的源代码我们可以发现Model其实是一个接口
    在这里插入图片描述

  • 通过ModelMap
    在HelloController2类中编写一个tohello3的方法
    在这里插入图片描述
    运行效果:
    在这里插入图片描述
    看看ModelMap的源代码:
    ModelMap类中仅仅只有几个设置参数的方法,由于继承LinkedHashMap类,所有它可以使用LinkedHashMap类的所有方法。
    在这里插入图片描述

七.乱码问题

  • 使用SpringMVC提供的过滤器处理乱码

在index.jsp中增加一个表单
在这里插入图片描述
新增一个Encoding类用来处理用户提交表单的操作
在这里插入图片描述
运行效果:
在这里插入图片描述
点击提交查询,出现乱码!
在这里插入图片描述
以前乱码问题通过过滤器解决 , 而SpringMVC给我们提供了一个过滤器 , 可以在web.xml中配置即可。

<filter>
   <filter-name>encoding</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>encoding</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

运行效果(一定要重启Tomcat服务器):
在输入框中输入张三然后点击提交查询,乱码问题得以解决!
在这里插入图片描述
在这里插入图片描述
为了避免一些极端情况我们可以通过修改tomcat配置文件的编码和自定义过滤器的方式来解决:

  • 修改tomcat配置文件中的编码
    在tmomcat服务器的conf目录下右击server.xml通过记事本打开,然后设置<Connector 标签的URIEncoding=“utf-8”。
    在这里插入图片描述
    在这里插入图片描述
  • 自定义过滤器

创建过滤器类GenericEncodingFilter

package controller;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;

/**
 * 解决get和post请求 全部乱码的过滤器
 */
public class GenericEncodingFilter implements Filter {
    
    

    @Override
    public void destroy() {
    
    
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    
    
        //处理response的字符编码
        HttpServletResponse myResponse=(HttpServletResponse) response;
        myResponse.setContentType("text/html;charset=UTF-8");

        // 转型为与协议相关对象
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        // 对request包装增强
        HttpServletRequest myrequest = new MyRequest(httpServletRequest);
        chain.doFilter(myrequest, response);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    
    
    }

}

//自定义request对象,HttpServletRequest的包装类
class MyRequest extends HttpServletRequestWrapper {
    
    

    private HttpServletRequest request;
    //是否编码的标记
    private boolean hasEncode;
    //定义一个可以传入HttpServletRequest对象的构造函数,以便对其进行装饰
    public MyRequest(HttpServletRequest request) {
    
    
        super(request);// super必须写
        this.request = request;
    }

    // 对需要增强方法 进行覆盖
    @Override
    public Map getParameterMap() {
    
    
        // 先获得请求方式
        String method = request.getMethod();
        if (method.equalsIgnoreCase("post")) {
    
    
            // post请求
            try {
    
    
                // 处理post乱码
                request.setCharacterEncoding("utf-8");
                return request.getParameterMap();
            } catch (UnsupportedEncodingException e) {
    
    
                e.printStackTrace();
            }
        } else if (method.equalsIgnoreCase("get")) {
    
    
            // get请求
            Map<String, String[]> parameterMap = request.getParameterMap();
            if (!hasEncode) {
    
     // 确保get手动编码逻辑只运行一次
                for (String parameterName : parameterMap.keySet()) {
    
    
                    String[] values = parameterMap.get(parameterName);
                    if (values != null) {
    
    
                        for (int i = 0; i < values.length; i++) {
    
    
                            try {
    
    
                                // 处理get乱码
                                values[i] = new String(values[i]
                                        .getBytes("ISO-8859-1"), "utf-8");
                            } catch (UnsupportedEncodingException e) {
    
    
                                e.printStackTrace();
                            }
                        }
                    }
                }
                hasEncode = true;
            }
            return parameterMap;
        }
        return super.getParameterMap();
    }

    //取一个值
    @Override
    public String getParameter(String name) {
    
    
        Map<String, String[]> parameterMap = getParameterMap();
        String[] values = parameterMap.get(name);
        if (values == null) {
    
    
            return null;
        }
        return values[0]; // 取回参数的第一个值
    }

    //取所有值
    @Override
    public String[] getParameterValues(String name) {
    
    
        Map<String, String[]> parameterMap = getParameterMap();
        String[] values = parameterMap.get(name);
        return values;
    }
}

然后在Web.xml中使用自定义过滤器

    <!--使用自定义过滤器-->
    <filter>
        <filter-name>encoding</filter-name>
        <filter-class>controller.GenericEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

运行一下:
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_42753193/article/details/123206218
今日推荐