首先我们先学习一些HTML标记

1.form标记

语法:

<form action="目标文件的URL" method="post/get">

 
<from···> ···</form> 是表单标记(表单可以理解成用户提交的数据的集合),其中的method属性取值get或者post,post是隐式的数据传输,get是显示的数据传输,输出的数据可以在url中体现出来。(URL中不允许带有中文,会导致文字编码错误)
举个栗子,form中的input标记暂时先不看。
example3_1.jsp

<%@ page contentType="text/html;charset=gb2312" %>
<form action="/myfile/receive.jsp" method="post">
  <input type="text" name="test" value="ok">
  <input type="submit" name="submit" value="submit">
</form>

 
receive.jsp

<%@ page contentType="text/html;charset=gb2312" %>
<%
  String boy = request.getParameter("test");
  out.println(boy);
%>

 
我们访问example3_1.jsp,在消息栏中随便输入一串数字然后点击submit提交表单。
 

我们首先是post,我们发现跳转到了另一个页面,显示我们刚刚提交过来的数据,同时URL只显示receive.jsp,底下网络监测是post方法。
 

 
我们将example3_1.jsp中的post改成get,再访问example3_1.jsp并点击提交。

这时,我们发现URL部分变成了很长一串,我们提交的表单数据在URL中出现,并且底下网络监测部分是get方法。
所以我们一般使用get来传递一些不敏感的消息,用post来传递一些敏感的消息比如密码等。

2.<input>标记

语法:

<input type="GUI类型" name="名字">

 
该标记是<form>的子标记,用来指定表单中数据的输入方式以及表单的submit按钮。该标记中可以指定GUI类型,比如上栗中我们用到了text和submit两种类型,对应的分别是消息输入栏和提交按钮,我们接下来会提到其他GUI类型。
(1)文本框text

<input type="text" name="名字" value="默认值" size="12" align="left" maxlength="12">

其中,name为该文本框的名字,value是默认值,可以不填,size是文本框的大小,align是文本框在浏览器窗体中的对齐方式,maxlength是允许输入的最大长度。
(2)单选按钮radio

<input type="radio" name="名字" value="值" align="top" checked="hello">

其中,name为该单选按钮的名字,value是值,align是对齐方式,checked如果不为空,则默认为选中状态。(只能有一个是选中状态)
栗子(checked只要不为空就行,值是什么都行):

<%@ page contentType="text/html;charset=gb2312" %>
<form action="/myfile/receive.jsp" method="get">
  这个是单选按钮radio
  <br>你只能选
  <input type="radio" name="radio" value="red" align="top" checked="1">
  或者
  <input type="radio" name="radio" value="yellow" align="top" >
  中的一个
</form>

 
下面是在页面中插入上述代码的样子(真的可以点哦!)

这个是单选按钮radio
你只能选 或者 中的一个 

(3)复选框checkbox

<input type="checkbox" name="名字" value="值" align="top" checked="hello">

其中,name为复选框的名字,value是值,align是对齐方式,checked不为空则默认选中。(可以有多个是选中状态)
栗子:

<%@ page contentType="text/html;charset=gb2312" %>
<form action="/myfile/receive.jsp" method="get">
              这是一个checkbox复选框<br>你可以选择这个
  <input type="checkbox" name="checkbox" value="red" align="top" checked="java">
  或者这个
  <input type="checkbox" name="checkbox" value="yellow" align="top">
  或者这个
  <input type="checkbox" name="checkbox" value="bule" align="top">
  中的一个或者多个
</form>

 
下面是在页面中插入上述代码的样子(真的可以点哦!)

这是一个checkbox复选框
你可以选择这个 或者这个 或者这个 中的一个或者多个

 
 
(4)口令框password

<input type="password" name="名字" size="12" maxlength="12">

其中,name是口令框的名字,size是窗口大小,maxlength是允许输入的最大长度。
栗子:

<%@ page contentType="text/html;charset=gb2312" %>
<form action="/myfile/receive.jsp" method="get">
  <input type="password" name="password" size="12" maxlength="12">
  <input type="submit" name="submit" value="submit">
</form>

 
下面是在页面中插入上述代码的样子(真的可以点哦!)


 

不过,仅仅是起到不让人偷看的作用,并不提供任何加密措施,在你使用get时,依然会在URL上显式显示传输的值。

 
 
(5)隐藏hidden

<input type="hidden" name="名字" value="值">

隐藏没有可见的任何东西,表单直接将value值提交给服务器,通过request对象调用getParameter()方法来获取value。
栗子:

<%@ page contentType="text/html;charset=gb2312" %>
<form action="/myfile/receive.jsp" method="get">
  <input type="hidden" name="password" value="12" >
  <input type="submit" name="submit" value="submit">
</form>

 
(6) submit按钮
一直在用emmm,这就不说了
 
(7)reset按钮

<%@ page contentType="text/html;charset=gb2312" %>
    <form action="/myfile/receive.jsp" method="get">
            <input type="reset" >
    </form>

栗子:

<%@ page contentType="text/html;charset=gb2312" %>
<form action="/myfile/receive.jsp" method="get">
  <input type="text" name="test" value="ok">
  <input type="text" name="test1" value="ok">
  <input type="submit" name="submit" value="submit">
  <input type="reset" value = "重置">
</form>

 
 

 
点击reset,恢复成默认状态。
3.<select>、<option>标记
下拉式列表和滚动列表通过<select>、<option>标记来定义。
格式:

<select name="name">
  <option value="one">one
  <option value="two">two
</select>

或者

<select name="name" size="整数">
  <option value="one">one
  <option value="two">two
</select>

其中,第二种的size中的整数是定义可见行的数量。

<%@ page contentType="text/html;charset=gb2312" %>
<select name="name">
  <option value="one">one
  <option value="two">two
  <option value="three">three
  <option value="four">four
</select>
  <select name="name" size="3">
  <option value="one">one
  <option value="two">two
  <option value="three">three
  <option value="four">four
</select>

 
下面是在页面中插入上述代码的样子(真的可以点哦!)


 
4.<textArea>标记
该标记是一个能输入或显示多行文本的文本区。
格式:

<textArea name="名字" rows="文本可见行数" cols="文本可见列数">
</textArea>

 

5.<table>标记
该标记以表格的形式显示数据,不提供数据输入功能。
格式:

<table>
    <tr width="该行的宽度>
      <th width="单元格的宽度">单元格中的数据</th>
      ···
                        ···
    </tr>
  </table>

 
栗子:

<%@ page contentType="text/html;charset=gb2312" %>
<table border=1>
    <tr width="40">
      <th width="10">123</th>
      <th width="10">123</th>
      <th width="10">123</th>
    </tr>
    <tr width="10">
      <th width="10">123</th>
      <th width="10">123</th>
      <th width="10">123</th>
    </tr>
  </table>

 
然后就是这样事的。

123 123 123
123 123 123

 
6.<image>标记
使用image标记可以显示一副图像。
格式:

<image src="图片URL">描述文字</image>

 
比如:

<%@ page contentType="text/html;charset=gb2312" %>
<image src="https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1171314795,738366933&fm=27&gp=0.jpg">就是这样的</image>

 

7.<embed>标记
使用该标记可以播放音乐和视频。
格式:

<embed src="音视频的URL">描述文字</embed>

embed中也有一些其他属性,比如autostart,当为true时是自动播放,默认值flase,即不自动播放;loop,取正值时为重复播放的次数,取-1为无限播放;width、height等。
3.处理超链接
格式:

<a href=链接地址>文字说明</a>

超链接也可以用向目标页面传送参数。

<a href=链接地址?参数1=值&参数2=值>文字说明</a>

 
这里我们可以用之前我们学习get、post时的栗子,我们说get是显式传递,观察他的URL部分,就是这种格式。
 

 
学习完HTML标记之后我们继续学习JSP的内置对象。

1.request

这个我们之前用过,request是实现了ServletRequest接口的一个实例。
我们可以稍微复习一下之前所学的知识,我们来看这段代码。
example3_1.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<HTML><BODY bgcolor=white><FONT size=2>
<FORM action="/myfile/computer.jsp" method=post name=form>
  <input type="text" name="sizeA" value=1 size=6>
  <input type="text" name="sizeB" value=1 size=6>
  <input type="text" name="sizeC" value=1 size=6>
  <input TYPE="submit" value="提交" name="submit">
</FORM>
</FONT> </BODY></HTML>

 
computer.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<HTML><BODY bgcolor=white><Font size=3>
 <% String sideA=request.getParameter("sizeA");
    String sideB=request.getParameter("sizeB");
    String sideC=request.getParameter("sizeC");
    try {   double a=Double.parseDouble(sideA);
           double b=Double.parseDouble(sideB);
           double c=Double.parseDouble(sideC);
           double p=(a+b+c)/2,area=0;
           area=Math.sqrt(p*(p-a)*(p-b)*(p-c));
           out.println("<BR>三角形面积"+area);
        }
    catch(NumberFormatException ee)
        {  out.println("<BR>请输入数字字符");
        }
 %>
</FONT></BODY></HTML>

 
在example3_1.jsp中,使用了form标记和input子标记,点击提交之后,将表单提交到comouter.jsp中,然后comouter.jsp通过request对象的getParameter方法来获取表单中的值,最后完成计算。
当然,如果是传输汉字的话,需要对传输的消息重新确认编码,有两种方式,一种是使用

String str = request.getParameter("message");
byte b[] = str.getByte("ISO-8859-1");
str=new String(b);

另一种方法是接受方。

request.setCharacterEncoding("gb2312");

这两种方法都可以对汉字进行重新编码,使发送的汉字不会变成乱码。
 

点击提交之后。

2.response对象

当用户访问一个服务器的页面时,会提交一个HTTP请求,服务器收到请求时,返回HTTP响应。响应和请求类似,也有某种结构,每个响应都由状态行开始,可以包含几个头及可能的信息体(网页的结果输出部分)。
可以用response对象对用户的请求做出动态响应,向用户端发送数据。
1.动态响应的contentType属性
页面用page指令设置页面的contentType属性的值,然后JSP引擎根据属性值做出响应,我们说过,一个页面不能设置多次contentType值;response对象提供了一种方法可以更改contentType属性值。
setContentType(String s)方法,其中s可以取之前提到过的MIME类型。
思考下面栗子:
example3_3.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<HTML><BODY bgcolor=white><Font size=1 >
 <P>我正在学习response对象的
 <BR>setContentType方法
 <P>将当前页面保存为word文档吗?
  <FORM action="" method="get" name=form>
     <INPUT TYPE="submit" value="yes" name="submit">
   </FORM>
 <% String str=request.getParameter("submit");
      if(str==null) {
str="";
         }
      if(str.equals("yes")) {
response.setContentType("application/msword;charset=GB2312");
         }
%>
</FONT></BODY></HTML>

 
我们访问这个页面,然后点击yes,我们就会发现这种情况。

 
上面程序需要注意的是,当JSP页面被初始化的时候,submit是空,这时候并不需要对contentType属性进行更改,所以需要对submit是否为空的判断,很多类似地方也需要这种操作,值得注意。
2.response的HTTP文件头
我们可以添加新的HTTP响应报头,可以使用方法:

addHeader(String head,String value);

 

setHeader(String head,String value);

 
动态添加新的响应头和头的值,将这些头发送给用户的浏览器。如果添加的头已经存在,则先前的头被覆盖。
example3_4.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="java.util.*" %>
<HTML><BODY bgcolor=cyan><Font size=5 >
<P>现在的时间是:<BR>
<%  out.println(""+new Date());
       response.setHeader("Refresh","5");
 %>
</FONT></BODY></HTML>

 
这个程序添加了refresh属性,值为5,也就是每5秒刷新一次页面,我们访问页面发现每5秒时间更新一次。(动图)

 
 
 
3.response 重定向
在某些情况下相应用户时,需要将用户重新引导至另一个页面,例如:如果用户输入的表单信息不完整,就会再被引导到该表单的输入页面,可以使用response和sendRedirect(URL url)方法实现用户的重定向。
思考下面栗子:
example3_5.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<HTML><BODY>
<P>填写姓名:<BR>
   <FORM action="myfile/receive.jsp" method="get" name=form>
     <INPUT TYPE="text"   name="boy">
     <INPUT TYPE="submit" value="Enter">
   </FORM>
</BODY></HTML>

 
receive.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<HTML><BODY>
  <% String str=request.getParameter("boy");
      if(str.length()==0)
      {  response.sendRedirect("../example3_5.jsp");
      }
      else
      {  out.print("欢迎您来到本网页!");
         out.print(str);
      }
%>
</BODY></HTML>

 
我们访问example3_5.jsp页面,我们会发现,当我们不输入任何东西时,网络监测部分会get receive.jsp之后,重新被定向到example3_5.jsp,而我们输入1之后,页面成功跳转到receive.jsp
 

 
4.response的状态行
可以更改网页的状态, 比如最常见的404 not found。

1xx 信息,服务器收到请求,需要请求者继续执行操作
2xx 成功,操作被成功接收并处理
3xx 重定向,需要进一步的操作以完成请求
4xx 客户端错误,请求包含语法错误或无法完成请求
5xx 服务器错误,服务器在处理请求的过程中发生了错误

下面是几个常见的状态码:详见这里

  • 200 – 请求成功
  • 301 – 资源(网页等)被永久转移到其它URL
  • 404 – 请求的资源(网页等)不存在
  • 500 – 内部服务器错误

书上说:

我们只需要在网页里调用response.setStatus();就可以更改页面状态,类似于我们看到的404 not found(P50最上面)

这里其实书写错了,不管你信不信,反正我是信了,这个response.setStatus();,只可以改变状态码,但是页面还是会执行完毕。换个方式说,运行成功的状态码一般是200,我们可以用这个方法,让服务器返回的状态码变成你想要的一个数字,而真正做到这个功能的方法,实际上是response.sendError();
我们来检验一下。
example3_6.jsp
 

<%@ page contentType="text/html;charset=GB2312" %>
<HTML><BODY>
 <% response.setStatus(408);
    //response.sendError(408);
    out.print("不显示了");
 %>
</BODY></HTML>

 
我们先使用setStatus();发现依然可以显示,但是底下的状态码变成了408.(如果你忘了可以向上翻,运行成功的状态码是一个绿色的200)

 
我们试试sendError();

页面变成了HTTP status 408 ,状态码依然是408。

3.session对象

我们都知道,HTTP是无状态连接,那么服务器怎么区分用户呢,用的就是session对象。用户在访问一个Web服务目录期间,服务器为该用户重新分配一个session对象,服务器可以在各个页面使用这个session记录当前用户的有关信息。服务器保证不同用户的session对象互不相同。我们通常所说的cookies,就是浏览器用来保存session对象的。
example3_7.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<HTML><BODY  bgcolor=white>
   我是first.jsp页面,输入你的姓名连接到second.jsp
   <% String id=session.getId();
      out.println("您的session对象的ID是:<br>"+id);
   %>
  <FORM action="myfile/second.jsp" method=post name=form>
       <INPUT type="text" name="boy">
       <INPUT TYPE="submit" value="送出" name=submit>
  </FORM>
</BODY></HTML>

 
second.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<HTML><BODY  bgcolor=white>
   我是second.jsp页面
   <%  String id=session.getId();
       out.println("您的session对象的ID是:<br>"+id);
   %>
<BR> 点击超链接,连接到third.jsp的页面。
<A HREF="/myfile/third.jsp"> 欢迎去third.jsp页面!</A>
</BODY></HTML>

 
third.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<HTML><BODY bgcolor=white>
   我是third.jsp页面
   <%  String id=session.getId();
       out.println("您的session对象的ID是:<br>"+id);
   %>
<BR> 点击超链接,连接到first.jsp的页面。
<A HREF="../example3_7.jsp">  欢迎去first.jsp!</A>
</BODY></HTML>

 



我们发现,每个界面的session ID都是一样的,如果我们把浏览器保存cookies的选项关掉,我们就会发现另一种情况。

我们发现每个页面的session ID都是不一样的。



这就是session ID的作用,我们还可以在session对象中存储数据。
1.public void setAttibute(String key,Object obj)
调用该方法可以向session对象指定一个索引关键字,如果添加的两个关键字相同,那先前的会被覆盖。
2.public Object getAttribute(String key)
返回关键字对应的对象,Object类型的,需要强制转换。
3.public void removeAttribute(String name)
移除对应对象。
 

3 session的生命周期

session达到发呆时间或者服务器关闭,session失效。
发呆时间是指服务器没有收到用户的请求的时间。
可以修改解压目录下的conf/web.xml中重新设定Web服务目录下的session对象的最长发呆时间。

<!-- ==================== Default Session Configuration ================= -->
<!-- You can set the default session timeout (in minutes) for all newly   -->
<!-- created sessions by modifying the value below.                       -->
  <session-config>
      <session-timeout>30</session-timeout>
  </session-config>

将其中的30改为需要的值(单位分钟)。

当然也有一些方法可以操作这个值,比如
public long getCreationTime() 可以获取session的创建时间
public long getMaxInactiveIntercal() 可以获取session最后一次被操作的时间
public int getMaxInactiveInterval()可以获取最长发呆时间(单位为秒)
public void setMaxInactiveInterval() 设置session最长发呆时间(单位为秒)
 

4.application对象

该对象和session对象类似,都是用来保存信息的,不同的是,session是为每个用户都分配一个,每个用户独享一个session对象,并且随着发呆时间结束而消失;但是application对象是随着页面的存在而存在,用来保存页面中的信息,多个用户共享一个application对象,但每个Web服务目录下的application互不相同。
application对象也和session对象一样有很多不同的方法:
1.public void setAttibute(String key,Object obj)
调用该方法可以向session对象指定一个索引关键字,如果添加的两个关键字相同,那先前的会被覆盖。
2.public Object getAttribute(String key)
返回关键字对应的对象,Object类型的,需要强制转换。
3.public void removeAttribute(String key)
移除对应对象。
 
栗子:用application制作留言板
example3_8.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<HTML><BODY>
 <FORM action="/myfile/messagePane.jsp" method="post" name="form">
     输入您的名字:<BR><INPUT  type="text" name="peopleName">
     <BR>输入您的留言标题:<BR><INPUT  type="text"  name="Title">
     <BR>输入您的留言:<BR> <TEXTAREA name="messages" ROWs="10" COLS=36 WRAP="physical"></TEXTAREA>
     <BR><INPUT type="submit" value="提交信息" name="submit">
 </FORM>
 <FORM action="/myfile/showMessage.jsp" method="post" name="form1">
    <INPUT type="submit" value="查看留言板" name="look">
 </FORM>
</BODY></HTML>

 
messagePane.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="java.util.*" %>
<HTML><BODY>
     <%! Vector v=new Vector();
         int i=0; ServletContext  application;
         synchronized void sendMessage(String s)
          { application=getServletContext();;
            i++;
           v.add("No."+i+","+s);
           application.setAttribute("Mess",v);
          }
     %>
     <% String name=request.getParameter("peopleName");
        String title=request.getParameter("Title");
        String messages=request.getParameter("messages");
           if(name==null)
             {name="guest"+(int)(Math.random()*10000);
             }
           if(title==null)
             {title="无标题";
             }
           if(messages==null)
             {messages="无信息";
             }
      byte a[]=name.getBytes("ISO-8859-1");
          name=new String(a);
      		  out.println(name+"<br>");
      	byte a1[]=title.getBytes("ISO-8859-1");
          title=new String(a1);
      		  out.println(title+"<br>");
      	byte a2[]=messages.getBytes("ISO-8859-1");
          messages=new String(a2);
      		  out.println(messages+"<br>");
          String s="姓名:"+name+"#"+"标题:"+title+"#"+"内容:"+"<BR>"+messages;
      //byte a3[]=s.getBytes("ISO-8859-1");
          //s=new String(a3);
      out.println(s+"<br>");
          sendMessage(s);
          out.print("您的信息已经提交!");
     %>
  <A HREF="../example3_8.jsp" >返回
</BODY></HTML>

 
showMessage.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<%@ page import="java.util.*" %>
<HTML><BODY>
     <% Vector v=(Vector)application.getAttribute("Mess");
          for(int i=0;i<v.size();i++)
            { String message=(String)v.elementAt(i);
              StringTokenizer fenxi=new StringTokenizer(message,"#");
                while(fenxi.hasMoreTokens())
                     { String str=fenxi.nextToken();
         //out.print("<BR>"+str);
                        //byte a[]=str.getBytes("ISO-8859-1");
                        //str=new String(a);
                       out.print("<BR>"+str);
                     }
            }
      %>
</BODY></HTML>

 
然后我们就可以访问页面,我们会发现任何人发送的留言可以被所有人看到。
 

5.out对象

out对象是一个输出流,用来向客户端输出数据。需要注意的是out.print和out.println,虽然从java语法来说两者差一个回车,但是浏览器并不识别println的换行标记,所以实际上二者效果一样,如果需要换行可以输出<br>实现换行。
 
 

课后题:

1.假设JSP使用的表单中有如下的GUI:

<input type="checkbox" name="item" value="bird">鸟
<input type="checkbox" name="item" value="apple">苹果
<input type="checkbox" name="item" value="cat">猫
<input type="checkbox" name="item" value="moon">月亮

该表单所请求的JSP可以使用内置对象request获取该表单提交的数据,那么,下列哪些是request获取该表单提交的值的正确语句( C )
A.String a = request.getParameter(“item”);
B.String b = request.getParameter(“checkbox”);
C.String a[] = request.getParameterValues(“item”);
D.String a[] = request.getParameterValues(“checkbox”);
2.如果表单提交的信息中有汉字,接受该信息的页面应做怎样的处理?
·    接受之前调用request.setCharacterEncoding()或者接受之后使用

String str=request.getParameter("message");
byte a[]=str.getBytes("ISO-8859-1");
str=new String(a);

进行编码转换。
3.编写两个JSP页面inputString.jsp和computer.jsp,用户可以使用inputString.jsp提供的表单输入一个字符串,并提交给computer.jsp页面,该页面通过内置对象获取inputString.jsp页面提交的字符串,计算并显示该字符串的长度。
inputString.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<html>
<body bgcolor=white>
  <form action="computer.jsp" method="post">
    <input type="text" name="message" size=12 maxlength=12>
    <input type="submit" name="submit" value="submit">
  </form>
</body></html>

 
computer.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<%
  String message=request.getParameter("message");
  message=new String(message.getBytes("iso-8859-1"));
  out.print(message.length());
%>

 
4.response调用sendRedirect(URL url)方法的作用是什么?
·    在某些情况下响应用户时,需要将用户重新引导至另一个页面,例如:如果用户输入的表单信息不完整,就会再被引导到该表单的输入页面,可以使用response和sendRedirect(URL url)方法实现用户的重定向。
5.对栗子3_1的代码进行改动,如果用户在3_1页面提供的表单中输入了非数字字符,example3_1_compute.jsp就将用户重新定向到example3_1.jsp中。
只需要对example3_1_compute.jsp进行改动(第15行)
example3_1_compute.jsp

<%@ page contentType="text/html;charset=GB2312" %>
<HTML><BODY bgcolor=white><Font size=3>
 <% String sideA=request.getParameter("sizeA");
    String sideB=request.getParameter("sizeB");
    String sideC=request.getParameter("sizeC");
    try {   double a=Double.parseDouble(sideA);
           double b=Double.parseDouble(sideB);
           double c=Double.parseDouble(sideC);
           double p=(a+b+c)/2,area=0;
           area=Math.sqrt(p*(p-a)*(p-b)*(p-c));
           out.println("<BR>三角形面积"+area);
        }
    catch(NumberFormatException ee)
        {
      response.sendRedirect("../example3_9.jsp"); //原来是 out.print()
        }
 %>
</FONT></BODY></HTML>

6.一个用户在不同的Web服务目录中的session对象相同么?
·    不相同。
7.一个用户在用一Web服务目录的不同子目录中的session对象相同么?
·    相同。
 

分类: JSP

0 条评论

发表回复

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用 * 标注