我是靠谱客的博主 懵懂香烟,最近开发中收集的这篇文章主要介绍jsp基础语法整理,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

WEB-INF目录结构:

http://localhost:8080/项目名(默认访问index.jsp==http://localhost:8080/项目名/index.jsp

 

Ps1:如果index.jsp改成其他名字.jsp或者index.html,再浏览http://localhost:8080/项目名,则404

Ps2:如果想其他名字设为默认的首页,则在web-inf文件夹中配置项目部署文件web.xml

@添加标签

<welcome-file-list><!-- 设置默认首页 -->

<welcome-file>/文件名.jsp(或文件名.html)</welcome-file>

<welcome-file-list>

修改完web.xml,需要重启Tomcat

 

1.WEB-INFJavaWEB应用的安全目录。所谓安全就是客服端无法访问,只有服务端可以访问的目录。

2.web.xml,项目部署文件。

3.classes文件夹,用以放置*.class文件。

4.lib文件夹,用于存放需要的jar包。

eg

修改首页

web.xml文件中添加

<welcome-file-list>

<welcome-file>

设定的首页文件名

<welcome-file>

<welcome-fiel-list>

 

 

eclipse创建JavaWeb程序:

New>Project>Web>Dynamic Web Project

1,填写JavaWeb程序名称

2,配置tomcat服务器及路径

 

修改Tomcat服务器默认端口:
修改conf/server.xml文件
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />

 

JSPJava平台,安全性高,适合开发大型的、企业级的Web应用程序。
Asp.net.Net平台,简单易学。但是安全性及跨平台性差。
PHP:简单、高效、成本低、开发周期短,特别适合中小型企业的Web应用开发。
(LAMPLinux + Apache + MySQL + PHP)

 

 

jsp指令
include指令
:将一个外部文件嵌入到当前的jsp文件中,同时解析这个页面中的jsp语句。
taglib指令使用标签库定义新的自定义标签,在jsp页面中启动定制行为。

 

JSP注释
1<!-- html注释-->//客户端可见
2.<%-- jsp注释 --%> //客户端不可见
3.jsp脚本中使用java注释 //客户端不可见
//单行注释
/**/多行注释

 

 

Jsp基础语法

——Jsp脚本
JSP页面中执行的java代码

语法:<% 合法的java代码片段; %>
如:<% out.println("ninhao");

out.println("<br>");%>

 

 

——JSP声明:

JSP页面中定义变量或者方法,可以被JSP表达式或者JSP脚本调用
语法:<%!Java代码%>
如:变量声明<%! int a=2009;%>
函数声明<%! public String hello(){return "hello";}%>

 

 

——JSP表达式:

<%= 符合java语法的不完整的java语句(结尾不带分号) %>
如:<%= 1+2+3 %>
<%= getDate()%>

注意:<%! java代码%>用于声明变量和方法;
  jsp表达式用于使用声明中定义的变量或表达式

 

 

JSP --> Servlet,当用户第一次访问当前JSP页面时,或者在用户访问之后,JSP页面发生了变化,用户再次访问时,JSP引擎会根据JSP页面生成一个Servlet,进而编译成字节码文件。
2. 编译之后,执行jspInit()方法进行初始化,该方法在当前JSP的生命周期中只会执行一次。生成的文件在work里,【每次修改会重新编译,生成新的字节码文件】
3. 执行jspService()用于处理用户请求,对于每一个请求,JSP引擎会创建一个新的线程来处理该请求【JSP多线程:降低资源需求,提高系统并发量及响应时间,但注意同步问题】。

由于该Servlet常驻于内存里,所以响应速度非常快

第一次请求一个jsp页面时,首先被执行的方法是构造方法
就是转换为class文件后,他会创建一个Servlet的实例,然后调用Servlet的构造方法,再调用jspInit()方法
​(1)JSP引擎先把该JSP文件转换成一个Java源文件(Servlet),在转换时如果发现JSP文件有任何语法错误,转换过程将中断,并向服务端和客户端输出出错信息。
2)如果转换成功,JSP引擎用javac把该Java源文件编译成相应的class文件。
3)创建一个该Servlet(JSP页面的转换结果)的实例,该Servlet的jspInit()方法被执行,jspInit()方法在Servlet的生命周期中只被执行一次。

       jspUnit:初始化代码;
       jspService:执行代码;
       jspDestory:销毁代码。

 

 

例题:打印九九乘法表

第一种利用表达式

第二种利用脚本

 

 

 

JSP内置对象

Web容器创建的一组对象,【不使用new关键字】就可以使用的内置对象。例如:out

(老九门):
上三门:request、response、session;
中三门:out、application、page;
下三门:pageContext、exception、config

 

out对象
补充:缓冲区 buffer,内存中的一块用来保存临时数据的区域
out对象是JspWriter类的实例,是向客户端输出内容常用的对象。
常用方法如下:
a. void println() 向客户端打印字符串
b. void clear() 清除缓存区的内容,如果在 flush 之后调用会抛出异常
c. void clearBuffer() 清除缓存区的内容,在 flush 之后调用不会抛出异常
d. void flush() 将缓冲区内容输出到客户端
e. int getBufferSize() 返回缓冲区的大小(字节数为单位),如不设置缓冲区则为0
f. int getRemaining() 返回缓冲区还剩余多少可用
g. boolean isAutoFlush() 返回缓冲区满时,是自动清空还是抛出异常
h. void close() 关闭输入流

 

 

表单有两种提交方式:get与post
<form action="dologin.jsp" name="loginForm" method="提交方式"></form>
1.get:以【明文】方式,通过URL提交数据,数据在URL中【可以看到】。提交数据最多不超过【2KB】。安全性较低,但效率比post方式高。适合提交数据量不大,且安全要求不高的数据:比如:搜索、查询等功能。
2.post:将用户提交的信息封装在HTML HEADER内。适合提交数据量大,【安全性高】的用户信息。如:注册、修改、上传等功能。

 

 

request对象
1)内容:
客户端的请求信息被封装在request对象中,通过它才能了解到客户的需求,然后做出响应。它是HttpServletRequest类的实例。request对象具有请求域,即完成客户端的请求之前,该对象一直有效。

2)方法:
1 String getParameter(String name) 返回name指定参数的参数值

用户名:<%=request.getParameter(“username”) %>
2 String[] getParameterValues(String name) 返回包含参数name的所有值的数组

爱好:<%

String[] favorites=request.getParameterValues(“favorites”);

For(int i=0;i<favorites.length;i++){

Out.println(favorites[i]+”&nasp;&nasp;”);

}

%>

    3 void setAttribute(String,Object) 储存此请求中的属性

密码:<%request.setAttribute("pwd","123456"); %>
4 object getAttribute(String name) 返回指定属性的属性值

获取密码:<%=request.getAttribute("pwd") %>
5 String getContentType() 得到请求体的MIME类型

请求体的MIME类型:<%=request.getContentType() %>
6 String getProtocol() 返回请求用的协议类型及版本号

协议类型及版本号:<%=request.getProtocol() %>
7 String getServerName() 返回接受请求的服务器主机名

服务器主机名:<%=request.getServerName() %>
8 int getServerPort() 返回服务器接受此请求所用的端口号

服务器端口号:<%=request.getServerPort() %>
9 String getCharacterEncoding() 返回字符编码方式

<%request.getCharacterEncoding(“utf-8”);%>
10 void setCharacterEncoding() 设置请求的字符编码方式

<%request.setCharacterEncoding(“utf-8”);%>
11 int getContentLength() 返回请求体的长度(以字节数)

请求文件的长度:<%=request.getContentLength() %>
12 String getRemoteAddr() 返回发送此请求的客户端IP地址

请求客户端的IP地址:<%=request.getRemoteAddr() %>

<!--//只能获取静态的IP地址,动态的话获取不到-->

13 String getRealPath() 返回一虚拟路径的真实路径

请求的真实路径:<%=request.getRealPath("request.jsp") %>
14 String getContextPath() 返回上下文路径

请求的上下文路径:<%=request.getContextPath() %>

 

 

 

jsp内置对象response:
不需要任何html代码,用out输出就可以;

HttpServletResponse类的实例,
response对象具有页面作用域,即访问一个页面时,该页面的response对象只对本次访问有效,其他页面的response对象对当前页面无效。
response.setContentType("text/html;charset=utf-8")====设置响应的MIMI类型
PrintWriter比out对象先打印====调用out.flush()可以解决

通过response的getWriter()方法创建的输出 流对象outer总是将要输出内容显示在页面的最开始(先于内置的out对象的输出)如果不想这样====可以使用out.flush();
response.sendRedirect(String addr) ====请求重定向,立刻跳转到定义的位置

 

请求重定向:服务端responce.sendRedirect("xx.jsp")重定向。

客户端行为】:即客户端会访问两次,第一次访问后会立 即跳转到第二个重定向页面上,

从本质上讲等于两次请求】,而前一次的请求封装的request对象不会保存,地址栏的URL地址会改变。
请求转发:服务端 request.getRequestDispatcher("xx.jsp").forward(request,response)请求转发。 forward(request,response)用于保存内置对象request和response。

服务器行为】:服务器会代替客户端去访问转发 页面,

从本质是一次请求】,转发后请求对象会保存,地址栏的URL地址不会改变。

结果是一样的

 

 

 



什么是session:
1、session表示客户端与服务器的一次会话
2、Web中的session指:用户在浏览某个网站时,从进入网站到浏览器关闭所经过的这段时间,也就是用户浏览网站所花费的时间。
3、在服务器的内存中保存着不同用户的session,一个用户对应一个session
4、从上述定义中可以看到,session实际是一个【特定的时间概念】

   
<%
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHH:mm:ss");
Date d = new Date(session.getCreationTime());
session.setAttribute("username", "admin");
session.setMaxInactiveInterval(10);//10s//设置当前session最大生成期限单位是秒
%>
Session创建时间:<%=sdf.format(d)%> 
SessionID编号:<%=session.getId()%> 
Session中获取用户名:<%=session.getAttribute("username")%> 
<%session.invalidate(); //销毁当前session%>


1. Session创建:
第一次访问服务器项目资源或者session超时被销毁后再次访问项目资源;
2. Session活动:
session超时之前,没有全部关闭访问服务器项目资源的窗口,开启的新的窗口仍然属于当前会话;
3. Session销毁:
a)调用“session.invalidate()”方法,主动销毁session;
b)超时的session会被服务器自动销毁;
c)重启服务器;
4. 配置Session超时时间:
a)调用“session.setMaxInactiveInterval()”方法;
b)在Web应用的配置文件“web.xml”中添加如下配置(时间单位为“分钟”):
<web-app>
<session-config>
<session-timeout>10</session-timeout>
</session-config>
</web-app>
5. 注意,在session超时之前,如果客户端关闭了所有的访问窗口,session并不会被销毁,只是不再使用。只有在上述第三点中描述的情况下,session才会被销毁!


application对象

一、application介绍
1、实现了用户间数据的共享,可存放全局变量。(类似静态对象)
2、开始于服务器启动,终止于服务器的关闭(生命周期)
3、在用户的前后连接或不同用户之间的连接中,可以对application对象的同一属性进行操作
4、在任何地方对application对象属性进行操作,都将影响到其他用户对此的访问
5、application对象是ServletContext类的实例
二、application 对象常用方法:
public void setAttribute(String name,Object value) 使用指定名称将对象绑定到此会话
public Object getAttribute(String name) 返回与此会话中的指定名称绑定在一起的对象,如果没有对象绑定在该名称下,则返回null
Enumeration getAttributeNames() 返回所有可用属性名的枚举
String getServerInfo() 返回JSP引擎及版本号

 

 

page对象
一、page对象:是指指向当前JSP页面本身,有点像类中的this指针,它是java.long.Object类的实例。
二、常用方法如下:
class getClass(); 返回此Object类
int hashCode(); 返回此Object的hash码
boolean equals(Object obj); 判断此Object是否与指定的Object对象相等
void copy(Object obj); 把此Object复制到指定的Object对象中
Object clone(); 克隆此Object对象
String toString(); 把此Object对象转换为String类的对象
void notify(); 唤醒一个等待的线程
void notyfyAll(); 唤醒所有等待的线程
void wait(int timeout); 使一个线程处于等待直到timeout结束或被唤醒
void wait(); 使一个线程处于等待直到被唤醒

 

 

pageContext对象
1.pageContext对象提供了对JSP页面中所有对象及名字空间的访问操作
2.pageContext对象可以访问本页面的session,可以访问本页面的application对象的任意属性值
3.pageContext对象是某个页面中所有功能的集大成者

pageContext对象的常用方法:
1.JspWriter getOut() 返回当前客户端相应被使用的JspWriter流(out)
2.HttpSession getSession() 返回当前页面中HttpSession对象(session)
3.Object getPage() 返回当前页面的Object对象(page)
4.ServletRequest getRequest() 返回当前面的ServletRequest对象(request)
5.ServletResponse getResponse() 返回当前页的ServletResponse对象(response)
6.void setAttribute(Strign name, Object attribute) 设置属性及属性值
7.Object getAttribute(String name ,int scope) 在指定范围内取属性值
8.int getAttributeScope(String name) 返回某属性的作用范围
9.void forward(String relativeUrlPath) 使当前页面跳转到另外一个页面(服务器转发)
10.void include(String relativeUrlPath) 在当前位置包含另一个文件

config对象 
常用方法:
ServletContext getServletContext()返回含有服务器相关信息的ServletContext对象
String getInitParameter(String name)返回初始化参数的值
Enumeration getInitParameterNames()返回Servlet初始化所需所有参数的枚举

 

 

Execption对象
exception对象是一个异常对象,当一个页面在运行过程中规发生了异常,就会产生这个对象。如果一个JSP页面要应用此对象,就必须把isErrorPage设为true,否则无法编译。
他实际上是java.lang.Throwable的对象,常用方法如下:
1.String getMessage();//返回描述异常的消息
2.String toString();//返回关于异常的简短描述消息
3.void printStackTrace();//显示异常及其栈轨迹
4.Throwable FillInStackTrace();//重写异常的执行栈轨迹

 

 

 

 

javabeans

一:概念:
1、Javabean是符合某种设计规范的java类。
2、在Model1,Javabean可以通过jsp来调用。
3、Javabean一般把属性设计为私有,使用setter和getter访问相应的属性。
4、Javabean既可以对数据进行封装,也能够封装业务逻辑。

1、Javabeans就是符合某种特定规范Java类。使用Javabeans的好处是【解决代码的重复编写】,减少代码冗余,功能区分明确,提高代码的维护性。
2、设计原则四点:公有类,属性私有,包含无参的共有构造方法,getter和setter方法封装属性

 

二:jsp动作元素

jsp动作元素为请求处理阶段提供信息。遵循XML元素的语法,有一个包含元素名的开始标签,可以有属性,可选的内容,与开始标签匹配的结束标签。

 

 

 

JSP中使用JavaBean

有两种方法:
1.像使用普通java类一样
创建一个web project项目。
src文件下,创建一个包,在包中创建一个类,满足设计原则即可
index.jsp页面中通过import导入之前创建的类(<%@ page import="包名.类名" %>)
通过使用new创建Javabean实例(创建对象)
使用set方法赋值
使用get方法取值
2.使用JSp的动作标签,如<jsp:useBean id="标识符(类似于Java中的new出来的实例变量名)" class="java类名(需要将包名一同写入)" scope="作用范围(默认是page)">

<jsp:useBean id="myUser" class="com.po.Users" scope="page"></jsp:useBean>
<h1>
使用userBean动作创建JavaBean的实例
</h1>
<hr />
用户名:<%=myUser.getName()%><br>
密码:<%=myUser.getPassword()%>

 

setProperty

<jsp:setProperty>动作:给【已经实例化的Javabean对象的属性赋值】,一共有四种形式。
1、需要表单提交属性:<jsp:setProperty name="Javabean实例名" property="*"/>: 与之前页面提交的表单的【所有属性进行匹配】,若有与javabean类属性名相同的,则进行赋值。比如表坛提交了username="xxx",而 javabean里有username属性,则对其进行赋值
2、需要表单提交属性<jsp:setPropery name="Javabean实例名" property="javabean属性名" />:对【指定的属性进行匹配】
3、手动设置属性:<jsp:setProperty name = "Javabean实例名" property="Javabean属性名" value="BeanValue" />
4、与request参数有关,通过url传参 :<jsp:setProperty name="Javabean实例名" property="propertyName" param="request对象中的参数名" />


1.根据表单自动匹配所有的属性
<jsp:setProperty name="myUsers" property="*"/>
2.根据表单自动匹配相应的属性(部分匹配)
<jsp:setProperty name="myUsers" property="username"/>
3.与表单无关,通过手工赋值给属性
<jsp:setProperty name="myUsers" property="username" value=“Lisa”/>
4.通过url传参数给属性赋值
<jsp:setProperty name="myUsers" property="username"/>
<jsp:setProperty name="myUsers" property="password" param=“mypass”/>

 

getProperty

<!-- 使用getProperty方式来获取用户名和密码 -->
用户名:<jsp:getProperty property="name" name="myUser"/>
密码:<jsp:getProperty property="password" name="myUser"/>

<!-- 使用传统的表达式方式来获取用户名和密码 -->
<%--
用户名:<%=myUser.getName()%><br>
密码:<%=myUser.getPassword()%>
--%>

JavaBean的生命周期

JavaBean的生命周期存在于4种范围之中,分别为page、request、session、application,它们通 过<jsp:useBean>标签的scope属性进行设置。这4种范围虽然存在很大的区别,但它们与JSP页面中的page、 request、session、application范围相对应。
page范围:与当前页面相对应,JavaBean的生命周期存在于一个页面之中,当页面关闭时JavaBean被销毁。
request范围:与JSP的request生命周期相对应,JavaBean的生命周期存在于request对象之中,当request对象销毁时JavaBean也被销毁。
session范围:与JSP的session生命周期相对应,JavaBean的生命周期存在于session会话之中,当session超时或会话结束时JavaBean被销毁。
application范围:与JSP的application生命周期相对应,在各个用户与服务器之间共享,只有当服务器关闭时JavaBean才被销毁。
4种作用范围与JavaBean的生命周期是息息相关的,当JavaBean被创建后,通过<jsp:setProperty>标签 与<jsp:getProperty>标签调用时,将会按照page、request、session和application的顺序来查找 这个JavaBean实例,直至找到一个实例对象为止,如果在这4个范围内都找不到JavaBean实例,则抛出异常。

 

注意
page pageContext不能获取javabean对象

Request 需要请求转发request.getRequestDispatcher(“xxx.jsp”).forward
(request,response);获取javabean对象
application、session 可以直接获取javabean对象

 

 

 

Model1分为三层:
1.界面层:由JSP页面进行与客户端浏览器的交互,可以直接调用JavaBeans
2.业务逻辑层:由JavaBeans进行处理业务逻辑,封装数据,并与数据库层进行交互
3.数据库层:底层数据库,可被javaBeans访问
避免了JSP页面直接进行业务逻辑处理所带来的维护性,扩展性差的弱点.体现了分层设计的思想

 

http的无状态性:
无状态性是指,当浏览器发送请求给服务器的时候,服务器响应客户端请求
但是当同一个浏览器再次发送请求给服务器的时候,服务器并不知道他就是刚才的那个浏览器
简单的说,就是服务器不会去记得你,所以就是无状态协议http的无状态性:
无状态性是指,当浏览器发送请求给服务器的时候,服务器响应客户端请求
但是当同一个浏览器再次发送请求给服务器的时候,服务器并不知道他就是刚才的那个浏览器
简单的说,就是服务器不会去记得你,所以就是无状态协议

 

Cookie

保存JSP状态的方法:jsp内置对象sessioncookie

Cookie的作用

1.保存用户对象的追踪;
2.保存用户网页浏览记录与习惯;
3.简化登录;
4.容易泄露用户信息。

创建与使用Cookie
一、创建与使用
1、创建CookieCookie newCookie = new Cookie(String key,String value);
2、写入Cookieresponse.addCookie(newCookie);
3、读取CookieCookie[] cookie = request.getCookies();

例题:

<%
request.setCharacterEncoding("utf-8");
String[] isUseCookies = request.getParameterValues("isUseCookie");//首先判断用户是否选择了记住登录状态
if(isUseCookies!=null&&isUseCookies.length>0)
{
//把用户名和密码保存在Cookie对象里面
String username = URLEncoder.encode(request.getParameter("username"),"utf-8");//使用URLEncoder解决无法在Cookie当中保存中文字符串问题
String password = URLEncoder.encode(request.getParameter("password"),"utf-8");
Cookie usernameCookie = new Cookie("username",username);
Cookie passwordCookie = new Cookie("password",password);
usernameCookie.setMaxAge(864000);
passwordCookie.setMaxAge(864000);//设置最大生存期限为10
response.addCookie(usernameCookie);
response.addCookie(passwordCookie);
}else{
Cookie[] cookies = request.getCookies();
if(cookies!=null&&cookies.length>0){
for(Cookie c:cookies)

if(c.getName().equals("username")||c.getName().equals("password")){
c.setMaxAge(0); //设置Cookie失效
response.addCookie(c); //重新保存。
}}}}%>

 

解决Cookie无法保存中文字符串的问题
1.java.net包下的URLEncoder类来进行编码
public static encode(String string, String enco);
2.URLDecoder类进行解码
URLDecoder.decode(String string, String enco);
3.如果在登录界面把usernamepassword的值设为了null,那么在登陆框就会出现null
最好是设为""
4.查找Cookie,是按照k值进行查找的
-----------------------------------
使用URLEncoder(在java.net包下)解决无法在Cookie当中保存中文字符串问题:

String username = URLEncoder.encode(request.getParameter("username"),"utf-8");//编码,防止中文乱码
String password = URLEncoder.encode(request.getParameter("password"),"utf-8");//编码,防止中文乱码

sessioncookie的区别
1、保存位置:session在服务器端内存,cookie在客户端文本
2、保存对象:session保存Object类(保存对象大小没有限制),cookie保存String类型(保存对象大小有限制)
3、生存权:session会话结束即销毁,cookie可以长期保存在客户端
4、重要性:session安全性更高,保存重要信息,cookie保存不重要的信息

 

常用的有pageincludetaglib指令这三种指令
page:位于页面顶端,一个页面可以包含多个page指令。
include:将一个外部文件嵌入jsp中,同时解析这个页面中的jsp语句。
taglib:使用标签库,自定义新的标签,在jsp中启动定制行为。

include指令 
1.语法 <% include file="地址"%>

指令:<%@ include file ="URL"%><br>
动作:<jsp:include page ="URL" flush="true|false"><br>
案例:显示当前时间的页面。(1)写一个只输出时间的方法的date.jsp。(2)用于显示的页面,包含<% include file="date.jsp"%>

Include指令与动作的区别

include指令在页面转换期间发生作用,包含文件的实际内容,主页面和包含页面转换为一个servlet,编译较慢,资源必需被解析,但是执行稍快。
include动作在请求期间发生作用,包含的是页面的输出,主页面和包含页面转换为独立的servlet,编译时间较快,执行较慢。

 

forward 指令

1、语法:<jsp:forward page="URL"/>
2、等于服务器内部转发指令 request.getRequestDispacher("URL").forward(req,res);

四种跳转.
<% response.sendRedirect("login_seccess.jsp"); %>//告诉浏览器此路不通,你再问问另一页面能解决你的问题不?
<jsp:forward page="login_fail.jsp"/> //服务器将请求转发到另一页面,浏览器不知情.
<% pageContext.forward("login_fail.jsp");%> //服务器将请求转发到另一页面,浏览器不知情.
<% request.getRequestDispatcher("login_fail.jsp").forward(request,response);%> //服务器将请求转发到另一页面,浏览器不知情.

param动作,传递方法为post
1、语法:<jsp:param name="参数名" value="参数值">
2、【常常与<jsp:forward></jsp:forward>一起使用】,并作为其【子标签】。
3、用于传递新参数或者【修改原有参数值】,修改参数时使用form表单里的参数名称即可。同样用request.getParameter("参数名")获取

@login.jsp
<form action="dologin.jsp" method="post">...</form>
@dologin.jsp
<jsp:forward page="user.jsp" >
<jsp:param value="8888" name="password"></jsp:param>//name要与login.jsp的一致
</jsp:forward>
@user.jsp
//同上章
Ps:可以把传过来的参数,修改再传过去;也可以新创建参数

最后

以上就是懵懂香烟为你收集整理的jsp基础语法整理的全部内容,希望文章能够帮你解决jsp基础语法整理所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(42)

评论列表共有 0 条评论

立即
投稿
返回
顶部