springMVC

springMVC概述

三层架构

  • 表现层:负责数据展示
  • 业务层:负责业务处理
  • 数据层:负责数据操作
    在这里插入图片描述

概念

  1. Spring MVC 是Spring提供的一个实现了Web MVC设计模式的轻量级Web框架。
  2. MVC(Model View Controller),一种用于设计创建Web应用程序表现层的模式
    • Model(模型):数据模型,用于封装数据
    • View(视图):页面视图,用于展示数据
    • Controller(Handle 处理器):处理用户交互的调度器,用于根据用户需求处理程序逻辑

spring MVC步骤

新建javaEE项目

在这里插入图片描述

导入maven依赖

pom.xml文件

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.xinzhi</groupId>
    <artifactId>springMVC</artifactId>
    <version>1.0-SNAPSHOT</version>
    <name>springMVC</name>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.target>11</maven.compiler.target>
        <maven.compiler.source>11</maven.compiler.source>
        <junit.version>5.9.2</junit.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>jakarta.servlet</groupId>
            <artifactId>jakarta.servlet-api</artifactId>
            <version>5.0.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>


        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

        <!-- servlet3.1规范的坐标 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <!--jsp坐标-->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>
        <!--spring的坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
        <!--spring web的坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
        <!--springmvc的坐标-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.9.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.3.2</version>
            </plugin>
        </plugins>
    </build>
</project>

创建controller包

创建UserController类

@Controller
public class UserController {
    @RequestMapping("/save")
    public String say(){
        System.out.println("你好");
        return "a.jsp";
    }
}

在resources下创建spring-mvc.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
    ">

    <context:component-scan base-package="com.xinzhi"/>
</beans>

编写web.xml文件,配置前端控制器

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
         version="5.0">

    <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*:spring-mvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

在webapp下创建a.jsp和b.jsp文件

配置tomcat(选择9.0.80版本)

启动测试

工作流程分析

  • 服务器启动
    1. 加载web.xml中DispatcherServlet
    2. 读取spring-mvc.xml中的配置,加载所有com.xinzhi包中所有标记为bean的类
    3. 读取bean中方法上方标注@RequestMapping的内容
  • 处理请求
    1. DispatcherServlet配置拦截所有请求 /
    2. 使用请求路径与所有加载的@RequestMapping的内容进行比对
    3. 执行对应的方法
    4. 根据方法的返回值在webapp目录中查找对应的页面并展示
  • web三大组件有 处理器映射,处理器适配器, 视图解析器
    1. dispatcherServlet 前置控制器,负责接收并处理所有的web请求,根据handlerMapping(处理器映射)找到具体的Controller(处理器),由controller完成具体的处理逻辑。
    2. HandlerMapping(处理器映射器):负责处理web请求和具体的Controller之间的映射关系匹配。
    3. HandlerAdapter(处理器适配器) 通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。 主要处理方法参数、相关注解、数据绑定、消息转换、返回值、调用视图解析器等等。
    4. Controller(处理器):DispatherServlet的次级控制器,web请求的具体处理者。DispatherServlet获得handlerMapping的返回结果后,调用controller的处理方法处理当前的业务请求,处理完成后返回ModelAndView对象。
    5. ViewResolver( 视图解析器):用来处理视图名与具体的view实例之间的映射对应关系。根据ModelAndView中的视图名查找相应的View实现类,然后将查找的结果返回给DispatcherServlet,DispatcherServlet最终会将ModelAndView中的模型数据交给返回的View处理最终的视图渲染工作。
      在这里插入图片描述

Springmvc架构原理解析

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

请求参数的绑定

  1. 默认类型:
    直接放在参数上就可以使用的数据,HttpServletRequest
  2. 简单类型:
    直接将简单类型的数据放在方法里,如果前端参数和后端参数名字一样,自动匹配;
    名字不一样:@RequsetParam(“前端的值”) 就可以将前端的值和后端参数映射
  3. 对象类型:
    前端的参数要和对象的属性名称必须一致,会自动封装。
  4. 对象嵌套:
    参数和对象的属性名称一致,前端参数对象子属性必须(子对象.属性)
  5. 自定义数据的绑定
    • 编写转换器类,作用是将前端的数据类型转换成后端的数据类型,继承converter
    • 配置文件中,添加转化器驱动
  6. 数组类型:
    前端数组中是简单类型的数据,那么前端数组中的name要和后端数组名称一致
  7. 集合类型:
    后端接受的对象是含有List<对象>属性的,那么前端的name值格式要和后端list属性名称一致,而且用索引的格式 list[0].属性(list集合里对象的属性名称)

拦截器

创建interceptor包,创建MyInterceptor类并实现HandlerInterceptor接口

/**
 *  三个方法的运行顺序为    preHandle -> postHandle -> afterCompletion
 *  如果preHandle返回值为false,三个方法仅运行preHandle
 */
public class MyInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("前置运行");
        //返回值为false将拦截原始处理器的运行
        //如果配置多拦截器,返回值为false将终止当前拦截器后面配置的拦截器的运行
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("后置运行");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("完成运行");
    }
}

在spring-mvc.xml配置文件中配置拦截器

<beans
xmlns:mvc="http://www.springframework.org/schema/mvc"
		   http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc.xsd>
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/login"/>
            <bean class="com.xinzhi.interceptor.MyInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>  

拦截器配置项

<mvc:interceptors>
    <!--开启具体的拦截器的使用,可以配置多个-->
    <mvc:interceptor>
        <!--设置拦截器的拦截路径,支持*通配-->
        <!--/**         表示拦截所有映射-->
        <!--/*          表示拦截所有/开头的映射-->
        <!--/user/*     表示拦截所有/user/开头的映射-->
        <!--/user/add*  表示拦截所有/user/开头,且具体映射名称以add开头的映射-->
        <!--/user/*All  表示拦截所有/user/开头,且具体映射名称以All结尾的映射-->
        <mvc:mapping path="/*"/>
        <mvc:mapping path="/**"/>
        <mvc:mapping path="/handleRun*"/>
        <!--设置拦截排除的路径,配置/**或/*,达到快速配置的目的-->
        <mvc:exclude-mapping path="/b*"/>
        <!--指定具体的拦截器类-->
        <bean class="MyInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

拦截器的使用场景

  1. 日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。
  2. 权限检查:如登录检测,进入处理器检测是否登录,如果没有直接返回到登录页面;
  3. 性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);

拦截器登录案例

public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 检查用户是否已登录
        if (!isUserLoggedIn(request)) {
            // 未登录,重定向到登录页面
            response.sendRedirect("/login");
            return false;
        }
        // 已登录,继续请求处理
        return true;
    }

    private boolean isUserLoggedIn(HttpServletRequest request) {
        // 在这里实现用户登录状态的检查逻辑
        // 如果用户已登录,返回true;否则返回false
        // 可以根据具体业务需求来实现用户登录状态的判断
        // 例如,可以检查Session中是否包含登录用户的信息
        // 或者检查请求头中是否包含有效的身份验证令牌等
        // 这里只是一个示例,具体实现根据实际情况进行调整
        return request.getSession().getAttribute("user") != null;
    }
}

在spring-mvc.xml配置文件中,我们可以指定拦截器的拦截路径和排除路径。

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/**"/> <!-- 拦截所有请求 -->
        <mvc:exclude-mapping path="/login"/> <!-- 排除登录请求 -->
        <bean class="com.example.interceptor.LoginInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

文件上传

导入maven依赖

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>

前端页面

<!DOCTYPE html>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title>文件上传</title>

	<script type="text/javascript" src="./js/jquery-1.11.3.min.js"></script>

</head>
<body>

	<form action="http://localhost:8080/upload" method="post" enctype="multipart/form-data">
		上传文件:&nbsp;&nbsp;<input type="button" value="添加文件" onclick="add()"/>
		<div id="file" style="margin-top: 10px;" value="文件上传区域">

		</div>
		<input id="submit" type="submit" value="上传" style="display: none;margin-top: 10px;"/>
	</form>
</body>

<script>
    function add(){
        var innerdiv = "<div>";
        innerdiv += "<input type='file' name='uploadfile'>" +
            "<input type='button' value='删除' οnclick='remove(this)'>";
        innerdiv +="</div>";
        $("#file").append(innerdiv);
        $("#submit").css("display","block");
    }
    function remove(obj) {
        $(obj).parent().remove();
        if($("#file div").length ==0){
            $("#submit").css("display","none");
        }
    }
</script>
</html>

在spring-mvc.xml配置文件中,配置多媒体解析器

<bean id="multipartResolver"
      class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>

在controller包下,创建处理文件上传下载请求的FileUploadController类

@Controller
/**
 * 文件上传控制器类
 */
public class FileUploadController{
    /**
     * 处理文件上传请求
     * @param uploadfile 上传的文件数组
     * @return 返回上传结果
     */
    @RequestMapping(value = "/upload",method = RequestMethod.POST)
    @ResponseBody
    private String uploadFile(MultipartFile[] uploadfile){
        for (MultipartFile file : uploadfile) {
            String filename = file.getOriginalFilename();
            filename= UUID.randomUUID()+"_"+filename;
            String dirPath="D:/file/";
            File filePath=new File(dirPath);
            if (!filePath.exists()){
                filePath.mkdir();
            }
            try {
                file.transferTo(new File(dirPath+filename));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return "success";
    }

    /**
     * 处理文件下载请求
     * @param request 请求对象
     * @param filename 文件名
     * @return 返回文件下载的响应实体
     */
    @RequestMapping("/download")
    public ResponseEntity<byte[]> download(HttpServletRequest request,String filename){
        String path="D:/file/";
        File file=new File(path+filename);
        HttpHeaders headers=new HttpHeaders();
        headers.setContentDispositionFormData("attachment",filename);
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        try {
            return new ResponseEntity<>(FileUtils.readFileToByteArray(file),headers, HttpStatus.OK);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }




    /**
     * 不同浏览器的版本兼容
     * @param request
     * @param filename
     * @return
     */
    private String getFilename(HttpServletRequest request,String filename) {
        //判断是不是IE内核的关键字
        String[] IEBrowerKeyWords = {"MSIE","Trident","Edge"};
        String keywords = request.getHeader("User-Agent");
        for (String keyWord : IEBrowerKeyWords) {
            if(keywords.contains(keyWord)){  //判断是否为IE浏览器
                try {
                    return URLEncoder.encode(filename,"UTF-8");
                } catch (UnsupportedEncodingException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        // 其他浏览器编码格式ISO-8859-1
        try {
            return new String(filename.getBytes("UTF-8"),"ISO-8859-1");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值