SpringMvc最全笔记--今日分享

本文深入探讨了SpringMVC框架的工作原理,包括MVC架构的各组成部分:模型(Model)、视图(View)和控制器(Controller)的角色与职责。详细讲解了SpringMVC的执行流程,从DispatcherServlet的作用到处理器映射、适配,再到视图解析的过程。同时,介绍了如何配置SpringMVC,实现RESTful风格的API设计,以及如何处理文件上传和下载。此外,还涉及了解决乱码问题和转发与重定向的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MVC 架构

模型(dao,service)

数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据Dao) 和 服务层(行为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。

视图 (jsp)

负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。

控制器(Servlet)

接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。也就是说控制器做了个调度员的工作。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bC7l2cMG-1589413718209)(D:\前锋教育\自创学习资料\image\2020-05-13_120219.png)]

Sping MVC

执行过程:

1.DispatcherServlet表示前端控制器,是整个SpringMVC的控制中心。用户发出请求,DispatcherServlet接受请求并拦截请求。

2.HandlerMapping为处理器映射。DispatcherServlet调用HandlerMapping HandlerMapping根据请求查找Handler

3.HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。

4.HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等。

5.HandlerAdapter表示处理器适配,其按照特定的规则去执行Handler。

6.Handler让具体的Controller执行。

7.Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView。

8.HandlerAdapter将视图逻辑或模型传递给DispatcherServlet。

9.DispatcherServlet调用视图解析器(View Resolver)来解析HandlerAdapter 传递的逻辑视图名。(拼接)

10.视图解析器将解析的逻辑视图传给DispatcherServlet。

11.DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图。

12.最终视图呈现给用户。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nV4yThDb-1589413718215)(D:\前锋教育\自创学习资料\image\2020-05-13_120649.png)]

处理静态过滤与导入jar包

<groupId>org.example</groupId>
<artifactId>spring—mvc_study</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
    <module>springMVC01</module>
</modules>
<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.6.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
</dependencies>
<!--在build中设置resources,来防止我们资源导出失败的问题-->
<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>

配置lib,打包用!

在这里插入图片描述

配置

实现接口Controller定义控制器

缺点是:一个控制器中只有一个方法,如果要多个方法则需要定义多个Controller;定义的方式比较麻烦;

        <!--配置DispatchServlet,MVC核心,前端控器器-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--通过初始化参数指定SpringMVC配置文件的位置,进行关联-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:</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>
<!--处理器映射器-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--处理器适配器-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--视图解析器-->
    <!--视图解析器:DispatcherServlet给他的ModelAndView-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
public class Handler implements Controller {

    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //ModelAndView 模型和视图
        ModelAndView mv = new ModelAndView();

        //封装对象,放在ModelAndView中。Model
        mv.addObject("msg","HelloSpringMVC!");
        //封装要跳转的视图,放在ModelAndView中
        mv.setViewName("hello"); //: /WEB-INF/jsp/hello.jsp
        return mv;
    }
}
注解配置:

@Controller注解类型用于声明Spring类的实例是一个控制器

  • spring配置
<!-- 自动扫描指定的包,下面所有注解类交给IOC容器管理 -->
<context:component-scan base-package="com.Long.Controller"/>
<!--视图解析器-->
<!--视图解析器:DispatcherServlet给他的ModelAndView-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="InternalResourceViewResolver">
    <!--前缀-->
    <property name="prefix" value="/WEB-INF/jsp/"/>
    <!--后缀-->
    <property name="suffix" value=".jsp"/>
</bean>
  • web配置DispatchServlet前端控器器
    <!--配置DispatchServlet,MVC核心,前端控器器-->
<servlet>
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--通过初始化参数指定SpringMVC配置文件的位置,进行关联-->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:</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>
  • 注解实现controller控制器
@Controller
public class Handler {
//    @RequestMapping("/t2")
    @GetMapping("/hello")
    public String index(Model model){
        //Spring MVC会自动实例化一个Model对象用于向视图中传值
        model.addAttribute("msg", "ControllerTest2");
        return "hello";
    }
    @RequestMapping("/t2")
    public String index1(Model model){
        //Spring MVC会自动实例化一个Model对象用于向视图中传值
        model.addAttribute("msg", "ControllerTest2");
        return "test";
    }
}

RestFul 风格

概念

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

功能

资源:互联网所有的事物都可以被抽象为资源

资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。

分别对应 添加、 删除、修改、查询。

//映射访问路径
@RequestMapping("/commit/{p1}/{p2}")
public String index(@PathVariable int p1, @PathVariable int p2, Model model){

    int result = p1+p2;
    //Spring MVC会自动实例化一个Model对象用于向视图中传值
    model.addAttribute("msg", "结果:"+result);
    //返回视图位置
    return "commit";
}
<form action="/commit/1/10" method="post">
    <input type="submit">
</form>

转发与重定向

区别
  1. 转发是在服务器端完成的,重定向是在客户端发生的;
  2. 转发的速度快,重定向速度慢;
  3. 转发是同一次请求,重定向是两次请求;
  4. 转发地址栏没有变化,重定向地址栏有变化;
  5. 转发必须是在同一台服务器下完成,重定向可以在不同的服务器下完成。

乱码问题

<!--过滤器解决乱码问题-->
    <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>

文件上传与下载

SpringMVC上下文中默认没有装配MultipartResolver,因此默认情况下其不能处理文件上传工作。如果想使用Spring的文件上传功能,则需要在上下文中配置MultipartResolver。

前端表单要求:为了能上传文件,必须将表单的method设置为POST,并将enctype设置为multipart/form-data。只有在这样的情况下,浏览器才会把用户选择的文件以二进制数据发送给服务器

对表单中的 enctype 属性做个详细的说明:

  • application/x-www=form-urlencoded:默认方式,只处理表单域中的 value 属性值,采用这种编码方式的表单会将表单域中的值处理成 URL 编码方式。
  • multipart/form-data:这种编码方式会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数中,不会对字符编码。
  • text/plain:除了把空格转换为 “+” 号外,其他字符都不做编码处理,这种方式适用直接通过表单发送邮件。
<form action="" enctype="multipart/form-data" method="post">
   <input type="file" name="file"/>
   <input type="submit">
</form>
文件上传:

1、导入文件上传的jar包,commons-fileupload

<!--文件上传-->
<dependency>
   <groupId>commons-fileupload</groupId>
   <artifactId>commons-fileupload</artifactId>
   <version>1.3.3</version>
</dependency>
<!--servlet-api导入高版本的-->
<dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>javax.servlet-api</artifactId>
   <version>4.0.1</version>
</dependency>

2、配置bean:multipartResolver

<!--文件上传配置-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
   <!-- 请求的编码格式,必须和jSP的pageEncoding属性一致,以便正确读取表单的内容,默认为ISO-8859-1 -->
   <property name="defaultEncoding" value="utf-8"/>
   <!-- 上传文件大小上限,单位为字节(10485760=10M) -->
   <property name="maxUploadSize" value="10485760"/>
   <property name="maxInMemorySize" value="40960"/>
</bean>

3、编写前端页面

<form action="/upload" enctype="multipart/form-data" method="post">
 <input type="file" name="file"/>
 <input type="submit" value="upload">
</form>

4、Controller(上传)

方式一:

//@RequestParam("file") 将name=file控件得到的文件封装成CommonsMultipartFile 对象
//批量上传CommonsMultipartFile则为数组即可
@RequestMapping("/upload2")
public String fileUpload(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {
    //获取文件名 : file.getOriginalFilename();
    String filename = file.getOriginalFilename();
    //如果文件名为空,直接回到首页!
    if ("".equals(filename)){
        return "redirect:/index.jsp";
    }
    System.out.println("上传文件名 : " + filename);
    //上传路径保存设置
    String path = request.getSession().getServletContext().getRealPath("/upload");
    //如果路径不存在,创建一个
    File realPath = new File(path);
    if (!realPath.exists()) {
        realPath.mkdir();
    }
    System.out.println("上传文件保存地址:" + realPath);
    InputStream is = file.getInputStream(); //文件输入流
    OutputStream os = new FileOutputStream(new File(realPath, filename)); //文件输出流

    //读取写出
    int len = 0;
    byte[] buffer = new byte[1024];
    while ((len = is.read(buffer)) != -1) {
        os.write(buffer, 0, len);
        os.flush();
    }
    os.close();
    is.close();
    return "redirect:/index.jsp";
}

方式二:

@RequestMapping("/upload")
public String  fileUpload2(@RequestParam("file") CommonsMultipartFile file, HttpServletRequest request) throws IOException {

    //上传路径保存设置
    String path = request.getSession().getServletContext().getRealPath("/upload");
    File realPath = new File(path);
    if (!realPath.exists()){
        realPath.mkdir();
    }
    //上传文件地址
    System.out.println("上传文件保存地址:"+realPath);

    //通过CommonsMultipartFile的方法直接写文件(注意这个时候)
    file.transferTo(new File(realPath +"/"+ file.getOriginalFilename()));

    return "redirect:/index.jsp";
}
文件下载:

1、设置 response 响应头

2、读取文件 – InputStream

3、写出文件 – OutputStream

4、执行操作

5、关闭流 (先开后关)

@RequestMapping(value="/download")
public String downloads(HttpServletResponse response , HttpServletRequest request) throws Exception{
    //要下载的图片地址
    String  path = request.getSession().getServletContext().getRealPath("/upload");
    String  fileName = "2.jpg";

    //1、设置response 响应头
    response.reset(); //设置页面不缓存,清空buffer
    response.setCharacterEncoding("UTF-8"); //字符编码
    response.setContentType("multipart/form-data"); //二进制传输数据
    //设置响应头
    response.setHeader("Content-Disposition",
            "attachment;fileName="+ URLEncoder.encode(fileName, "UTF-8"));

    File file = new File(path,fileName);
    //2、 读取文件--输入流
    InputStream input=new FileInputStream(file);
    //3、 写出文件--输出流
    OutputStream out = response.getOutputStream();

    byte[] buff =new byte[1024];
    int index=0;
    //4、执行 写出操作
    while((index= input.read(buff))!= -1){
        out.write(buff, 0, index);
        out.flush();
    }
    //5、 关闭流,释放资源
    out.close();
    input.close();
    return null;
}
UTF-8"));

    File file = new File(path,fileName);
    //2、 读取文件--输入流
    InputStream input=new FileInputStream(file);
    //3、 写出文件--输出流
    OutputStream out = response.getOutputStream();

    byte[] buff =new byte[1024];
    int index=0;
    //4、执行 写出操作
    while((index= input.read(buff))!= -1){
        out.write(buff, 0, index);
        out.flush();
    }
    //5、 关闭流,释放资源
    out.close();
    input.close();
    return null;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Steve_hanhaiLong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值