IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 深入理解学习SpringMVC-基础篇 -> 正文阅读

[Java知识库]深入理解学习SpringMVC-基础篇

SpringMVC

一、Springmvc介绍

1、什么是Springmvc?

在Spring基础上 开发的框架 springMVC框架,是控制器框架 c层框架(Struts2也是C层框架)

本质:替换Struts2框架充当控制器

为了使Spring可插入MVC架构,SpringFrameWork在Spring基础上开发SpringMVC框架,从而在使用Spring进行WEB开发时可以选择使用Spring的SpringMVC框架作为web开发的控制器框架

  • MVC开发模式
1M 模型层 实体+dao+Service
2V 视图层  WebApp根下的页面 HTml+Jsp
3C 控制层   Action/Controller Struts2/SpringMVC

2、SpringMvc好处

(1)SpringMvc基于Spring框架开发,能和Spring框架进行无缝整合
(2)SpringMvc的运行效率高于Struts2
    (Spring对象默认单例模式,但是Struts2是多例模式,节约了运行时间)
(3)SpringMvc支持注解开发,简单,快捷,注解式开发更高效

3、总结

Springmvc基于Spring开发的控制器框架

1、接收数据
2、调用业务
3、跳转页面

SpringMVC 轻量级,典型MVC框架 ,在整个MVC架构中充当控制器框架,相对于struts2框架,SpringMVC运行更快,其注解式开发更高效灵活

二、SpringMVC的组件解析

1、Struts2的执行流程

客户端请求:

1. 经过web.xml中的Struts2核心过滤器,将用户请求交给Struts22. 先经过Struts.xml的package下的namespance
3、再去找action中的name加载Class下的Action类通过反射或者Class中的方法
4、在Action方法中接收数据,调用业务,跳转页面
5、返回到Result,加载跳转的页面
6、再次经过过滤器返回到客户端,将对应的结果返回给对应的用户

2、SpringMVC的执行流程

客户端请求:

1、先经过Web.xml 拦截请求 将请求转发(DispatcherServlet)SpringMvc
2、处理器映射器(RequesMappingHandelMapping)解析请求路径
3、类上的RequestMapping(等价于Struts2中的namespace配置)
4、方法上的RequestMapping(等价于Struts2中的Action的name属性值)
5、接收前端的传过来的数据RequestMappingHandelAdapter 处理器适配器 负责接收解析数据
6InternalResourceViewResolver 视图解析器
   (解析返回值,当前跳转位置的前缀/和后缀.jsp)
   返回结果: 
       前缀:/
       后缀:.jsp
       结果: 前缀+返回的字符串+后缀

3、详细执行流程:

(1)用户发送请求至前端控制器DispatcherServlet。

(2)DispatcherServlet收到请求调用HandlerMapping处理器映射器。

(3)处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),
    生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
(4)DispatcherServlet调用HandlerAdapter处理器适配器。

(5)HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)(6)Controller执行完成返回ModelAndView。

(7)HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。

(8)DispatcherServlet将ModelAndView传给ViewReslover视图解析器。

(9)ViewReslover解析后返回具体View。

(10)DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。DispatcherServlet响应用户。

4、SpringMVC组件解析

(1)前端控制器:DispatcherServlet

????用户请求到达前端控制器,它就相当于 MVC 模式中的 C,DispatcherServlet 是整个流程控制的中心,由

????它调用其它组件处理用户的请求,DispatcherServlet 的存在降低了组件之间的耦合性。

(2)处理器映射器:HandlerMapping

????HandlerMapping 负责根据用户请求找到 Handler 即处理器,SpringMVC 提供了不同的映射器实现不同的

映射方式,例如:配置文件方式,实现接口方式,注解方式等。

(3)处理器适配器:HandlerAdapter

????通过 HandlerAdapter 对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理

器进行执行。

(4)处理器:Handler

????它就是我们开发中要编写的具体业务控制器。由 DispatcherServlet 把用户请求转发到 Handler。由

????Handler 对具体的用户请求进行处理。

(5)视图解析器:View Resolver [r?’z?lv?]

????View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名,即具体的页面地址,再生成 View 视图对象,最后对 View 进行渲染将处理结果通过页面展示给用户。

(6)视图:View

SpringMVC 框架提供了很多的 View 视图类型的支持,包括:jstlView、freemarkerView、pdfView等。最常用的视图就是 jsp。一般情况下需要通过页面标签或页面模版技术将模型数据通过页面展示给用户,需要由程序员根据业务需求开发具体的页面

三、第一个SpringMvc项目

1、引入相关依赖

 <!--junit-->
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-core</artifactId>
          <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context-support</artifactId>
          <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-jdbc</artifactId>
          <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aop</artifactId>
          <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-beans</artifactId>
          <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-expression</artifactId>
          <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-aspects</artifactId>
          <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-tx</artifactId>
          <version>4.3.2.RELEASE</version>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-web</artifactId>
          <version>4.3.2.RELEASE</version>
      </dependency>
      <!--springmvc核心依赖-->
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-webmvc</artifactId>
          <version>4.3.2.RELEASE</version>
      </dependency>
      <!--servlet-api-->
      <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>servlet-api</artifactId>
          <version>2.5</version>
          <scope>provided</scope>

2、编写springmvc配置文件(applicationContext.xml)

  <!--开启注解扫描:component:组件[k?m?po?n?nt]-->
    <context:component-scan base-package="com.tjcu"></context:component-scan>
    <!--注册处理器映射器-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
    <!--注册处理器适配器-->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>
    <!--注册视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--prefix:[?pri?f?ks] 前缀-->
        <property name="prefix" value="/"></property>
        <!--suffix: [?s?f?ks] 后缀-->
        <property name="suffix" value=".jsp"></property>
    </bean>

3、配置springmvc的核心Servlet

  <!--负责转发请求-->
    <servlet>
        <servlet-name>mvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--指定mvc的配置文件位置和名字-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>mvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
  • 注意 : 这里还要加载spring配置,通过在servlet写init-param标签,还是contextConfigLocation属性,value用来加载springmvc配置文件

  • Servlet默认单例,在第一个请求的时候创建,如果不想要写<init-param>,可以把配置文件放在Web-INF下,并命名为mvc-servlet.xml

4、创建控制器

//负责控制层组件对象创建
@Controller("userController")
//类上的控制器映射器,相当于Struts2中的namespace
@RequestMapping("user")
public class UserController{
    //方法上的控制器映射器,相当于Struts中的name
    @RequestMapping("queryAll")
    public String queryAll(){
        System.out.println("查询到了很多数据");
        //解析结果:前缀+返回值+后缀
        return "index";
    }
  • @Controller: 该注解用来类上标识这是一个控制器组件类并创建这个类实例

  • @RequestMapping:

???? 修饰范围: 用在方法或者类上

???? 注解作用: 用来指定类以及类中方法的请求路径

???? 注解详解:

????用在类上相当于struts2中namespace在访问类中方法必须先加入这个路径

????用在方法上相当于action标签的name属性用来表示访问这个方法的路径

5.部署项目,启动项目测试

访问路径: http://localhost:8080/SpringMvc/user/queryAll

6、SpringMVC的开发步骤总结

????①导入SpringMVC相关坐标(spring,servlet-api,spring-mvc等)

????②配置SpringMVC核心控制器DispathcerServlet

????③创建Controller类和视图页面

????④使用注解配置Controller类中业务方法的映射地址

????⑤配置SpringMVC核心文件 springmvc.xml(三大核心组件)

????⑥客户端发起请求测试

四、SpringMVC中跳转方式

1、跳转方式

说明:跳转有两种=方式,一种forward ,一种**redirect ** [?ri?d??rekt ]。

(1)Servlet跳转方式【底层】

#forward跳转,
一次请求,地址栏不变,可以使用request作用域传递数据,

#redirect跳转多次,
地址栏改变,不能使用作用域

(2)Struts2中的跳转方式(区分跳转的目标资源类型)

#Action--->jsp
  forward[默认] type="dispatcher"
  redirect      type="redirect"

#Action--->Action
   forward    type="chain"
   redirect   type="redirectAction"

(3)springmvc跳转方式

# 1.Controller 跳转到JSP
   forward跳转到页面: 默认就是forward跳转
                     语法:return "业务逻辑名"
                     例子:return "showUer"---->/showUser.jsp
                     
   redirect跳转到页面:使用SpringMVC提供rediret:关键字进行重定向页面跳转
                 语法:return "redirect:/index.jsp"
                 注意:使用redirect跳转页面不会经过视图解析器
                 
# 2.Controller跳转到Controller

   forward跳转到Controller:
   使用SpringMvc提供的关键字forward
   语法:forward:/跳转类上@requestMapping的值/跳转类中方法@RequestMapping的值
   例子:return "forward:test:/";  
   
   redirect跳转到Controller:使用SpringMvc提供的关键字redirect
   语法:redirect:/跳转类上@requestMapping的值/跳转类中方法@RequestMapping的值
  • forward跳转到页面(.jsp)示意图:

  • redirect跳转到页面(.jsp)示意图:

  • forward方法: Controller层跳转到另外一个控制层(controller)示意图:

  • 如果跳本类的一个控制器(controller)方法示意图:

  • redirect方法: Controller层跳转到另外一个控制层(controller)示意图:

2、跳转方法总结

五、SpringMVC中参数接收

接收参数语法说明:springmvc中使用控制器方法参数来收集客户端的请求参数,因此在接收请求参数时直接在需要控制器方法声明即可,springmvc可以自动根据指定类型完成类型的转换操作

1、接收零散类型的参数

如:八种基本类型+String+日期类型

  • Controller中的业务方法的参数名称要与请求参数的name一致,参数值会自动映射匹配。并且能自动做类型

转换;

  • 自动的类型转换是指从String向其他类型 的转换

(1)前端传递参数

#get方式传递参数
http://localhost:8080/SpringMvc/user/register?
      name=王恒杰&password=234&sex=true&birthday=1999/12/03&salary=20000
      
#post方式传递参数
<form action="${pageContext.request.contextPath}/user/register" method="posst">
  姓名:<input type="text" name="name"><br/>
  密码:<input type="password" name="password"><br/>
  性别:<input type="text" name="sex"><br/>
  生日:<input type="text" name="birthday"><br/>
  工资:<input type="text" name="salary"><br/>
    <input type="submit" value="提交"><br/>
</form>

(2)后台Controller接收数据

//负责控制层组件对象创建
@Controller("userController")
//类上的控制器映射器,相当于Struts2中的namespace
@RequestMapping("user")
public class UserController {
    @RequestMapping("register")
    public String register(String name, String password, Boolean sex, Date birthday, Double salary) {
        System.out.println("注册成功");
        System.out.println("姓名" + name);
        System.out.println("密码" + password);
        System.out.println("性别" + sex);
        System.out.println("生日" + birthday);
        System.out.println("工资" + salary);
        return "index";
    }

  • 注意:springmvc在接收日期类型参数时日期格式必须为yyyy/MM/dd HH:mm:ss

2、接收对象类型参数

(1)前端传递参数

<form action="${pageContext.request.contextPath}/user/register" method="get">
  姓名:<input type="text" name="name"><br/>
  密码:<input type="password" name="password"><br/>
  性别:<input type="text" name="sex"><br/>
  生日:<input type="text" name="birthday"><br/>
  工资:<input type="text" name="salary"><br/>
    <input type="submit" value="提交"><br/>
</form>
  • 注意: 在接收对象类型参数时和struts2接收不同,springmvc直接根据传递参数名与对象中属性名一致自动封装对象

(2)后台Controller接收数据

  • 实体类
public class User implements Serializable {
    private static final Long serialVersionUID=1L;
    private String name;
    private String password;
    private String sex;
    private String birthday;
    private String Salary;
  • 控制器中接收前端数据
//负责控制层组件对象创建
@Controller("userController")
//类上的控制器映射器,相当于Struts2中的namespace
@RequestMapping("user")
public class UserController{
    @RequestMapping("register")
    public String register(User user){
        System.out.println("注册成功");
        System.out.println("姓名"+user.getName());
        System.out.println("密码"+user.getPassword());
        System.out.println("性别"+user.getSex());
        System.out.println("生日"+user.getBirthday());
        System.out.println("工资"+user.getSalary());
        return "redirect:/index.jsp";
    }

3、接收数组类型参数

(1)前端传递参数

(2)后台Controller接收数据

//负责控制层组件对象创建
@Controller("userController")
//类上的控制器映射器,相当于Struts2中的namespace
@RequestMapping("user")
public class UserController{
    @RequestMapping("register")
    public String register(User user, String[] hobby){
        System.out.println("注册成功");
        System.out.println("姓名:"+user.getName());
        System.out.println("密码:"+user.getPassword());
        System.out.println("性别:"+user.getSex());
        System.out.println("生日:"+user.getBirthday());
        System.out.println("工资:"+user.getSalary());
        System.out.println("爱好:");
        for (String s : hobby) {
            System.out.println(s);
        }
        return "redirect:/index.jsp";
    }

4、SpringMVC接收参数中文乱码解决方案

(1)在使用post方式接收请求参数时出现中文乱码接收数据问题解决

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

(2)在使用set方式中文乱码问题

改tomcat的server.xml配置文件大概在50多行加上URIEncoding="UTF-8"

# 1.针对于GET方式中文乱码解决方案:
<Connector connectionTimeout="20000"
             port="8080" 
             protocol="HTTP/1.1" 
            redirectPort="8443" URIEncoding="UTF-8"/>

  • 成功设置之后,接收到的数据就不会乱码了!

5、接收集合类型参数

说明:springmvc不支持直接将接收集合声明为控制器方法参数进行接收,如果要接收集合类型参数必须使用对象封装要接收接收类型才可以

(1)前端传递参数

<form action="${pageContext.request.contextPath}/user/register" method="post">
    姓名:<input type="text" name="name"><br/>
    密码:<input type="password" name="password"><br/>
    性别:<input type="text" name="sex"><br/>
    生日:<input type="text" name="birthday"><br/>
    工资:<input type="text" name="salary"><br/>
    <span> 爱好:</span>
    吃饭:<input type="checkbox" name="hobby" value="吃饭">
    睡觉:<input type="checkbox" name="hobby" value="睡觉">
    爱杨福君:<input type="checkbox" name="hobby" value="爱杨福君">
    抽烟:<input type="checkbox" name="hobby" value="抽烟">
    喝酒:<input type="checkbox" name="hobby" value="喝酒">
    烫头发:<input type="checkbox" name="hobby" value=" 烫头发">
    <br/>
    <span> 擅长技术:</span><br>
    <input type="checkbox" name="lists" value="python">python<br>
    <input type="checkbox" name="lists" value="java">java<br>
    <input type="checkbox" name="lists" value="c++"> c++<br>
    <input type="checkbox" name="lists" value="linux">linux<br>
    <input type="checkbox" name="lists" value="计算机网络">计算机网络<br>
    <input type="checkbox" name="lists" value="go">go<br>
    <br/>
    <input type="submit" value="提交"><br/>
</form>

(2)后台Controller接口

// 1.封装接收集合类型对象---->在spring mvc中用来接收集合类型参数
class Collection{
    private List<String> lists;

    public List<String> getLists() {
        return lists;
    }

    public void setLists(List<String> lists) {
        this.lists = lists;
    }
}

// 2.控制器中接收集合类型参数
//负责控制层组件对象创建
@Controller("userController")
//类上的控制器映射器,相当于Struts2中的namespace
@RequestMapping("user")
public class UserController{
    @RequestMapping("register")
    public String register(User user, String[] hobby,Collection collection){
        System.out.println("注册成功");
        System.out.println("姓名:"+user.getName());
        System.out.println("密码:"+user.getPassword());
        System.out.println("性别:"+user.getSex());
        System.out.println("生日:"+user.getBirthday());
        System.out.println("工资:"+user.getSalary());

        System.out.println("爱好:");
        for (String s : hobby) {
            System.out.print(s);
        }

        //换行
        System.out.println();

        System.out.println("个人技能");
        for (String list : collection.getLists()) {
            System.out.print(list+" ,");
        }
        return "redirect:/index.jsp";
    }

(3)使用Lambda优化接收集合和数组数据

  • 报错原因:使用Lambda需要JDK8版本及以上

  • 优化后ontroller接收数据代码

class Collection{
    private List<String> lists;

    public List<String> getLists() {
        return lists;
    }

    public void setLists(List<String> lists) {
        this.lists = lists;
    }
}

//负责控制层组件对象创建
@Controller("userController")
//类上的控制器映射器,相当于Struts2中的namespace
@RequestMapping("user")
public class UserController{
    @RequestMapping("register")
    public String register(User user, String[] hobby,Collection collection){
        System.out.println("注册成功");
        System.out.println("姓名:"+user.getName());
        System.out.println("密码:"+user.getPassword());
        System.out.println("性别:"+user.getSex());
        System.out.println("生日:"+user.getBirthday());
        System.out.println("工资:"+user.getSalary());

        //优化版本,使用Lambda表达式接收集合和数组
        System.out.println("爱好:");
        Arrays.asList(hobby).forEach(item -> System.out.println(item));

        //换行
        System.out.println();

        System.out.println("个人技能");
        collection.getLists().forEach(name-> System.out.println(name));
        return "redirect:/index.jsp";
    }

}

六、SpringMVC中数据传递机制

1.数据传递机制

# 1.数据怎么存
      Servlet 作用域         Struts2  作用域        SpringMVC 作用域
# 2.数据怎么取
      Servlet EL表达式      Struts2  EL表达式      SpringMVC EL表达式
# 3.数据怎么展示    
      Servlet JSTL标签      Struts2  JSTl标签     SpringMVC  JSTl标签

2.使用forward跳转传递数据

# 1.使用servlet中原始的request作用域传递数据
    request.setAttribute("key",value);
   

# 2.使用是springmvc中封装的Model和ModelMap对象(底层对request作用域封装)
    model.addAttribute(key,value);
    modelMap.addAttribute(key,value);

(1)使用servlet中原始的request作用域传递数据

#如何获取springmvc控制器方法中获取request对象,response对象? 

 注意:直接将request,response对象作为控制器方法参数声明即可获取 
  • controller层使用request传递数据
   //方法上的控制器映射器,相当于Struts中的name
    @RequestMapping("queryAll")
    public String queryAll(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("SpringMvc使用Request数据");
        request.setAttribute("name","王恒杰");
        //解析结果:前缀+返回值+后缀
        return "index";
    }
  • 客户端使用EL接收数据
<%@page  pageEncoding="UTF-8" isELIgnored="false" %>
<html>
<body>
<h2>用户数据进行展示</h2>
SpringMVC使用request传递的数据,jsp使用EL接收数据:${requestScope.name}
</body>
</html>

(2)使用Model对象保存数据

3.使用Redirect跳转传递数据

# 1.使用地址栏进行数据传递
   url?name=zhangsan&age=21

# 2.使用session作用域
  session.setAttribute(key,value);
  session.getAttribute(key);
   //方法上的控制器映射器,相当于Struts中的name
    @RequestMapping("queryAll")
    public String queryAll(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("SpringMvc使用Request数据");
        request.setAttribute("name","王恒杰");
        //解析结果:前缀+返回值+后缀
        return "index";
    }
  • 客户端使用EL接收数据
<%@page  pageEncoding="UTF-8" isELIgnored="false" %>
<html>
<body>
<h2>用户数据进行展示</h2>
SpringMVC使用request传递的数据,jsp使用EL接收数据:${requestScope.name}
</body>
</html>

在这里插入图片描述

(2)使用Model对象保存数据

在这里插入图片描述

3.使用Redirect跳转传递数据

# 1.使用地址栏进行数据传递
   url?name=zhangsan&age=21

# 2.使用session作用域
  session.setAttribute(key,value);
  session.getAttribute(key);
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-11-19 17:30:07  更:2021-11-19 17:30:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:11:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码