第七章SpingMVC

news2024/11/28 12:34:39

1.MVC模式

视图(View)-对应组件:JSP或者HTML文件 控制器(Controller)-对应组件:Servlet 模型(Model) -对应组件:JavaBean

2.MVC模式具体说明

JSP:负责生成动态网页 Servlet:负责流程控制 JavaBean:负责业务逻辑处理

3.MVC执行过程

MVC执行过程: a.将url映射到java类或类里面的方法 b.封装请求数据 c.调用相关业务处理--->封装返回数据 d.将响应数据渲染到相关视图view(jsp、html、freemarker......)

4.SpringMVC概述

含义:是一个轻量级基于请求/响应模式的MVC框架

包含内容:Controller(控制器)-接收请求、调用业务处理、响应客户端

ModelAndView:模型和视图--封装和传递数据

View(视图)-数据展示(jsp、html、freemarker等)

特点:与Spring无缝集成,方便使用SpringIOC和AOP功能 支持异常处理、类型转换、数据验证、拦截器、本地化、国际化等功能 支持Restful风格及各种视图的支持

5.SpringMVC处理请求流程

6.SpringMVC环境搭建

6.1.导入依赖

<dependencies>
    <!--spring-context依赖-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.4.RELEASE</version>
    </dependency>
    <!--log4j日志记录-->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
</dependencies>

6.2.编写配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.mvc.controler"/>
    <!--启用注解驱动-mvc配置 -->
    <mvc:annotation-driven />
    <!--配置视图解析器 -->
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver"
        p:prefix="/WEB-INF/jsp/" p:suffix=".jsp"/>
</beans>

6.3.控制层代码

@Controller //此注解标示着 该类是一个可以处理请求的类 而不是一个普通的类
public class StudentController {
    //@RequestMapping是一个用来处理 请求地址映射 的注解
    @RequestMapping("/toIndex.do")
    public String toIndex(){ //去首页
        System.out.println("省略业务逻辑层和数据访问层");
        return "index"; //表示的是 一个逻辑视图名
    }
}

6.4.配置web.xml

<!--配置核心控制器|前端控制器-DispatcherServlet -->
<servlet>
    <servlet-name>smvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc-config.xml</param-value>
    </init-param>
</servlet>

<servlet-mapping>
        <servlet-name>smvc</servlet-name>
        <url-pattern>*.do</url-pattern>
</servlet-mapping>

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

6.5.测试

http://localhost:8080/P28_SpringMVC/toIndex.do

7.SpringMVC传参传值

7.1.创建返回类型

String、ModelAndView、void、Map、Model

7.2.控制层方法返回类型具体操作

控制层

@Controller //此注解标示着 该类是一个可以处理请求的类 而不是一个普通的类
public class StudentController {
    //@RequestMapping是一个用来处理 请求地址映射 的注解
    @RequestMapping("/toIndex.do")
    public String toIndex(){ //去首页
        System.out.println("省略业务逻辑层和数据访问层");
        return "index"; //表示的是 一个逻辑视图名
    }
    //去首页通过ModelAndView
    @RequestMapping("/toIndex1.do")
    public ModelAndView toIndex1(){
        //ModelAndView 1个参数 代表的是 逻辑视图名
        return new ModelAndView("index");
    }
    //去首页通过ModelAndView
    @RequestMapping("/toIndex2.do")
    public ModelAndView toIndex2(){
        //ModelAndView 3个参数 第1代表的是 逻辑视图名 第2个参数代表的是要传到页面的key 第3个参数代表的是要传到页面的value
        return new ModelAndView("index","msg","嘿");
    }
}

测试

http://localhost:8080/P28_SpringMVC/toIndex.do
http://localhost:8080/P28_SpringMVC/toIndex1.do
http://localhost:8080/P28_SpringMVC/toIndex2.do

7.3.控制层方法传参类型和方式

一个参数

//控制方法 参数类型 一个参数
@RequestMapping("/toIndex3.do")
public ModelAndView toIndex3(String sname){
    //String sname=request.getParameter("sname"); //以前servlet阶段
    System.out.println("sname:"+sname);
    return new ModelAndView("index","msg","嘿");
}

多个参数

//控制方法 参数类型 2个参数(多个参数)
@RequestMapping("/toIndex4.do")
public ModelAndView toIndex4(String sname,Integer age){
    System.out.println("sname:"+sname+"\tage:"+age);
    return new ModelAndView("index","msg","嘿");
}

对象传参

注册页面

<body>
<form action="doReg.do" method="post">
    <p>姓名:<input type="text" name="sname" value=""/></p>
    <p>性别:<input type="text" name="sex" value=""/></p>
    <p>年龄:<input type="text" name="age" value=""/></p>
    <p><input type="submit" value="注册"/></p>
</form>
</body>

去注册页面:对应StudentController控制层

@RequestMapping("/toReg.do")
public String toRegPage(){ //去注册页面
    return "reg";
}

实体类

//学生类
public class Student {
    private Integer sno;
    private String pwd;
    private String sname;
    private String sex;
    private Integer gid;
    private Integer age;
    private String phone;
    private String address;

    // 省略getter和setter方法
}

控制层参数为对象:对应控制层StudentController 伪注册功能

//控制方法 参数类型 多个参数一般 用对象传参
@RequestMapping("/doReg.do")
public ModelAndView doReg(Student stu){ //注册功能
    System.out.println("sname:"+stu.getSname()+" sex:"+stu.getSex()+"age:"+stu.getAge());
    return new ModelAndView("login");
}

登录页面

<body>
<h3>欢迎来到登录页面</h3>
</body>

测试

http://localhost:8080/P28_SpringMVC/toReg.do

7.4.控制层向页面传值方式

说明方式:通过ModelAndView对象;通过Model对象;通过Map对象。

具体操作:

通过ModelAndView对象:对应StudentController中

//控制层 向页面传值方式1-通过ModelAndView 对象
@RequestMapping("/doReg1.do")
public ModelAndView doReg1(Student stu){ //注册功能
    System.out.println("名字:"+stu.getSname());
    return new ModelAndView("reg","stu",stu);
}

//控制层 向页面传值方式1-通过ModelAndView 对象
@RequestMapping("/doReg2.do")
public ModelAndView doReg2(Student stu){ //注册功能
    System.out.println("名字:"+stu.getSname());
    ModelAndView mv =new ModelAndView();
    mv.addObject("stu",stu); //将对象带到页面去-通过ModelAndView
    mv.setViewName("reg"); //逻辑视图名
    return mv;
}

通过Model对象:对应StudentController中

//控制层 向页面传值方式2-通过Model对象
@RequestMapping("/doReg3.do")
public ModelAndView doReg3(Student stu,Model model){ //注册功能
    System.out.println("model:"+model);
    ModelAndView mv =new ModelAndView();
    // mv.addObject("stu",stu); //把用户对象传到页面去
    model.addAttribute("stu",stu); //将对象带到页面去-通过Model
    mv.setViewName("reg"); //逻辑视图名
    return mv;
}

通过Map对象:对应StudentController中

//控制层 向页面传值方式3-通过Map对象
@RequestMapping("/doReg4.do")
public ModelAndView doReg4(Student stu,Map<String,Object> maps){ //注册功能
    System.out.println("maps:"+maps);
    ModelAndView mv =new ModelAndView();
    maps.put("stu",stu); //将对象带到页面去-通过Map
    mv.setViewName("reg"); //逻辑视图名
    return mv;
}

8.SpringMVC上传下载

8.1.S平日那个MVC上传功能

8.1.1.上传实现

导入依赖

<dependencies>
    <!--spring-context依赖-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.4.RELEASE</version>
    </dependency>
    <!--commons-fileupload-->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.4</version>
    </dependency>
</dependencies>

编写配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.mvc.controller"/>
    <!--启用注解驱动-mvc配置 -->
    <mvc:annotation-driven />
    <!--配置视图解析器 -->
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver"
        p:prefix="/WEB-INF/jsp/" p:suffix=".jsp"/>
    <!--支持文件上传的解析器 maxUploadSize上传的最大大小,单位是字节-->
    <bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
        p:maxUploadSize="802400" p:defaultEncoding="utf-8"/>
</beans>

添加上传表单:对应upDownLoad.jsp页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>上传下载页面</title>
</head>
<body>
<form action="doUpload.do" method="post" enctype="multipart/form-data">
    图片:<input type="file" name="file"/><input type="submit" value="上传"/>
</form>
</body>
</html>

编写控制层代码

@Controller //此注解标示着 该类是一个可以处理请求的类 而不是一个普通的类
public class FileController {
    //去上传的页面
    @RequestMapping("/toUpPage.do")
    public String toUpPage(){
        return "upDownLoad";
    }

    //文件上传
    @RequestMapping("/doUpload.do")
    public ModelAndView toUpload(MultipartFile file,HttpServletRequest request)throws Exception{
        //1、获取文件名
        String fname=file.getOriginalFilename();

        //2、对文件进行处理(比喻生成随机文件名)
        //a-获取文件的后缀名
        String ext=FilenameUtils.getExtension(fname);
        //b-生成随机文件名
        //String ranFName=System.currentTimeMillis()+"."+ext;
        String rfName=UUID.randomUUID()+"."+ext; //全球唯一识别码

        //3、获取存放文件的物理路径
        String savePath=request.getServletContext().getRealPath("upload");
        System.out.println("地址:"+savePath);

        //4、创建文件实例
        File f1=new File(savePath,rfName);

        //5、写入文件进行上传操作
        //FileUtils.copyInputStreamToFile(file.getInputStream(),f1);
        file.transferTo(f1);
        return new ModelAndView("upDownLoad");
    }
}

配置web.xml

<!--配置核心控制器|前端控制器-DispatcherServlet -->
<servlet>
    <servlet-name>smvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc-config.xml</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>smvc</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

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

测试

http://localhost:8080/P29_SpringMVC_uploaddown/toUpPage.do

项目结构图

8.1.2.上传功能的注意点

表单上:在表单上添加enctype="multipart/form-data"且上传按钮的type为file

<form action="doUpload.do" method="post" enctype="multipart/form-data">
    图片:<input type="file" name="file"/><input type="submit" value="上传"/>
</form>

核心配置文件:需要添加支持文件上传组件的解析器

<!--支持文件上传的解析器 maxUploadSize上传的最大大小,单位是字节-->
<bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
    p:maxUploadSize="802400" p:defaultEncoding="utf-8"/>

控制层方法上面:需要添加MultipartFile file参数并且file和表单的name保持一致

8.2.SpringMVC下载功能

8.2.1.下载实现

提供下载超链接

<h3>-------------下面是下载----------------</h3>
<h3><a href="downLoad.do?filename=01.jpg">点击下载</a></h3>
<h3><a href="downLoad.do?filename=老孙.jpg">点击中文文件名下载</a></h3>

控制层代码

//下载功能
@RequestMapping("/downLoad.do")
public void downLoad(String filename,HttpServletRequest req,HttpServletResponse res)throws Exception{
    //1、获得文件
    String file=req.getServletContext().getRealPath("/upload/"+filename);

    //2、通过文件构建一个输入流对象
    FileInputStream fis=new FileInputStream(file);
    //中文乱码问题-碰到中文文件名的下载 需要考虑-浏览器接收文件时 默认ISO-8859-1编码
    filename=new String(filename.getBytes("UTF-8"),"ISO-8859-1");

    //3、设置输出格式和内容
    res.setHeader("content-disposition","attchment;filename="+filename);//文档头
    res.setContentType("application/octet-stream"); //文件类型
    res.setContentLength(fis.available()); //文件大小

    //4、构建缓冲区
    byte[] by=new byte[2048]; //构建一个缓冲区

    //5、循环读写
    int len=0; //计数
    while((len=fis.read(by))!=-1){
        res.getOutputStream().write(by,0,len);
    }

    //6、刷新并关闭资源
    res.getOutputStream().flush(); //刷新
    res.getOutputStream().close();
    fis.close();
}

8.2.2.下载功能注意点

针对中文文件名的下载,注意中文乱码的问题

//中文乱码问题-碰到中文文件名的下载 需要考虑-浏览器接收文件时 默认ISO-8859-1编码
filename=new String(filename.getBytes("UTF-8"),"ISO-8859-1");

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/470837.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python resnet实例,残差网络医学分类,基于resnet医学图像分类任务;医学图像处理实战

一&#xff0c;数据集介绍&#xff1a; 数据预处理&#xff1a; 把数据处理成相同大小&#xff1a; 数据集&#xff1a; PathMNIST:结直肠癌组织学切片&#xff1b;ChestMNIST&#xff1a;胸部CT数据集&#xff0c;来源于NIH-ChestXray14 dataset&#xff1b;DermaMNIST&#…

【刷题之路Ⅱ】LeetCode 138. 复制带随机指针的链表

【刷题之路Ⅱ】LeetCode 138. 复制带随机指针的链表 一、题目描述二、解题难点分析方法——插入拷贝节点2、将拷贝节点插入到原节点的后面3、复制原节点的random到拷贝节点中4、将拷贝节点尾插到新链表中并恢复原链表的结构 一、题目描述 原题连接&#xff1a; 138. 复制带随机…

考研拓展:汇编基础

一.说明 本篇博客是基于考研之计算机组成原理中的程序机器级代码表示进行学习的&#xff0c;并不是从汇编语言这一门单独的课程来学习的&#xff0c;涉及的汇编语言知识多是帮助你学习考研之计算机组成原理中对应的考点。 二.相关寄存器 1.相关寄存器 X86处理器中有8个32位…

【三十天精通Vue 3】第二十天 Vue 3的性能优化详解

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: 三十天精通 Vue 3 文章目录 引言一、Vue3 性能优化的概念1.1 为什么需要性能优化1.2 性能优化…

基于dsp+fpga+AD+ENDAC的半导体运动台高速数据采集电路仿真设计(四)

整个调试验证与仿真分析分三个步骤&#xff1a;第一步是进行 PCB 检查及电气特性测试&#xff0c;主 要用来验证硬件设计是否正常工作&#xff1b;第二步进行各子模块功能测试&#xff0c;包括高速光纤串行 通信的稳定性与可靠性测试&#xff0c; A/D 及 D/A 转换特性测…

26从零开始学Java之如何对数组进行排序与二分查找?

作者&#xff1a;孙玉昌&#xff0c;昵称【一一哥】&#xff0c;另外【壹壹哥】也是我哦 千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者 前言 在上一篇文章中&#xff0c;壹哥给大家讲解了数组的扩容、缩容及拷贝方式。接下来在今天的文章中&…

深眸科技|深度学习、3D视觉融入机器视觉系统,实现生产数智化

随着“中国制造2025”战略加速落实&#xff0c;制造业生产线正在加紧向智能化、自动化和数字化转型之路迈进。而人工智能技术的兴起以及边缘算力持续提升的同时&#xff0c;机器视觉及其相关技术也在飞速发展&#xff0c;并不断渗透进工业领域&#xff0c;拓展应用场景的同时&a…

Apache Druid中Kafka配置远程代码执行漏洞(MPS-2023-6623)

漏洞描述 Apache Druid 是一个高性能的数据分析引擎。 Kafka Connect模块曾出现JNDI注入漏洞(CVE-2023-25194)&#xff0c;近期安全研究人员发现Apache Druid由于支持从 Kafka 加载数据的实现满足其利用条件&#xff0c;攻击者可通过修改 Kafka 连接配置属性进行 JNDI 注入攻…

软件架构中间件技术

中间件的定义 其实中间件是属于构件的一种。是一种独立的系统软件或服务程序&#xff0c;可以帮助分布式应用软件在不同技术之间共享资源。 我们把它定性为一类系统软件&#xff0c;比如我们常说的消息中间件&#xff0c;数据库中间件等等都是中间件的一种体现。一般情况都是…

减少 try catch ,可以这样干

软件开发过程中&#xff0c;不可避免的是需要处理各种异常&#xff0c;就我自己来说&#xff0c;至少有一半以上的时间都是在处理各种异常情况&#xff0c;所以代码中就会出现大量的try {...} catch {...} finally {...}代码块&#xff0c;不仅有大量的冗余代码&#xff0c;而且…

d3.js学习笔记①创建html文档

本人之前从未学过HTML、CSS、JavaScript&#xff0c;然而我导是做前端的&#xff0c;要求我必须在三周内掌握d3.js&#xff0c;我只能从0学起并以此记录自己的学习过程。 首先对这三种语言有一个初步的认识&#xff1a;HTML是用于搭建网页框架&#xff0c;CSS是美化网页的&…

软件设计师考试——计算机网络、系统安全分析和设计部分

计算机网路 七层模型 OSI/RM七层模型 网络技术标准与协议 TCP协议 DHCP协议 DNS协议 计算机网络的分类——拓扑结构 按分布范围&#xff1a; 局域网城域网广域网因特网 按拓扑结构&#xff1a; 总线型星型环型 网络规划与设计 逻辑网络设计 物理网络设计 分层设计 IP地址…

VirboxLM-免服务版授权码,快速实现一机一码

一、产品介绍 ​ 授权码是由深盾科技开发的一款软件保护及授权管理产品 ​&#xff0c;一方面要保护软件代码不被逆向&#xff0c;另一方面要控制软件的授权使用。软件用户只需要输入授权码&#xff08;由数字和字母组成的一串字符&#xff09;&#xff0c;激活授权码后即可使…

这年头,谁还在「贩卖」生活方式?

【潮汐商业评论/原创】 “我已经很久没有追寻过品牌购物了”Anna如是说。 如今的Anna对商品的选择往往会考虑性价比以及简洁的外观&#xff0c;去品牌化、简单已经成为其新的生活方式。 日本作者三浦展在《第四消费时代》一书中提到&#xff0c;在第三消费社会&#xff0c;新…

Java版本企业工程项目管理系统平台源码(三控:进度组织、质量安全、预算资金成本、二平台:招采、设计管理)

工程项目管理软件&#xff08;工程项目管理系统&#xff09;对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营&#xff0c;全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#…

Android 获取奔溃crash的日志(adb logcat或者dropbox)

1.通过adb logcat 来获取&#xff1a; 使用场景&#xff1a;测试或者开发小伙伴 抓取。 先执行adb logcat -c 清理缓存日志 接着&#xff0c;抓取当前时间段开始的日志: adb logcat -v time >D:/crash.log 也可以抓取指定进程的日志&#xff1a; adb logcat -v time | fi…

利用POSIX多线程API函数进行多线程开发

本书文字内容源自 <<linux C/C服务器开发实践>> 支持正版图书&#xff0c;测试代码根据测试目的&#xff0c;可自行修改测试。 前言 在用POSIX多线程API函数进行开发之前&#xff0c;我们首先要熟悉这些API函数。常见的与线程有关的基本API函数见下表 使用这些A…

亚马逊云科技综合解决方案助力美的智能化,成本节省30%

很多人都有和客服打交道的体验&#xff0c;而这种体验大概率不佳&#xff0c;人工客服迟迟不应&#xff0c;解答问题也不精准&#xff0c;糟糕的客服体验对于面向消费者的企业来说亦是一大难题&#xff0c;严重者甚至会导致客户流失、评价滑坡等后果&#xff0c;作为知名科技电…

FileInputStream.read和FileChannel.read的区别

FileChannel怎么来的 FileChannel channel new FileInputStream("").getChannel() FileChannel的read()方法 channel.read(byteBuffer) 实现类FileChannelImpl 首先映入眼帘的就是非常熟悉的synchronized关键字&#xff0c; private final Object positionLock ne…

宏基因组组装 | 就现在!做出改变!!

微生态研究的核心难点是什么&#xff01; 基因组组装&#xff01; 从宏基因组数据中组装获得细菌的完整基因组&#xff08;complete MAGs&#xff09;是微生物组研究的长期目标&#xff0c;但基于NGS的宏基因组测序和组装方法是无法实现完整的细菌基因组组装的。即便是红极一…