jsp怎么连接mysql数据库

jsp怎么连接mysql数据库,第1张

我写的一个用JSP连接MySQL数据库的代码。

要正确的使用这段代码,你需要首先在MySQL数据库里创建一username表,表里面创建两个字符型的字段,字段名分别为:uid,pwd,然后插入几条测试数据。

以下用两种方式来实现JSP连接MySql数据库。

第一种方式,用JSP实现。

<%@ page contentType="text/htmlcharset=gb2312" language="java"

import="java.sql.*"%>

<%

//**************************************

********* JDBC_ODBC连接MySql数据库,不需要设置数据源

*********************************/

//********** 数据库连接代码 开始 ******/

//以下几项请自行修改

String server="localhost" //MYSQL 服务器的地址

String dbname="test" //MYSQL 数据库的名字

String user="root" //MYSQL 数据库的登录用户名

String pass="chfanwsp" //MYSQL 数据库的登录密码

String port="3306" //SQL Server 服务器的端口号,默认为1433

//数据库连接字符串

String url ="jdbc:mysql://"+server+":"+port+"/"+dbname+"?user="+user+

"&password="+pass+"&useUnicode=true&characterEncoding=GB2312"

//加载驱动程序

Class.forName("org.gjt.mm.mysql.Driver").newInstance()

//建立连接

Connection conn= DriverManager.getConnection(url)

//创建语句对象

Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,

ResultSet.CONCUR_UPDATABLE)

// **** 数据库连接代码 结束 *******

String sql="select * from username"

ResultSet rs=stmt.executeQuery(sql)

//rs.first()

while(rs.next()){

out.print("用户名:")

out.print(rs.getString("uid")+" 密码:")

out.println(rs.getString("pwd")+"

")

}

rs.close()

stmt.close()

conn.close()

%>

第二种方式,用JavaBean来实现。请看代码:

DBConnMySql.java

编译以后的Class文件应该放在WEB-INF\classes\conn目录下。

package conn //导入包

import java.sql.* //导入数据库操作的类

public class DBConnMySql//构造方法,初始化

{

private Connection conn //连接对象

private Statement stmt //语句对象

private ResultSet rs //结果集对象

private String MySqldriver//MYSQL Server驱动程序字符串

private String MySqlURL//MYSQL Server连接字符串

//********************************

*用 org.gjt.mm.mysql.Driver 驱动

* 该方法取得连接所需各种参数,组成连接字符串,然后再建立连接

* serverdbname,user,pass,port 分别表示MYSQL 服务器的地址,

* 数据库,用户名,密码,端口

**********************************/

public Connection getConnToMySql(String server,String dbname,

String user,String pass,String port){

//MYSQl驱动程序

MySqldriver = "org.gjt.mm.mysql.Driver"

MySqlURL = "jdbc:mysql://" //连接字符串一部分

try{

//完整的连接字符串

MySqlURL =MySqlURL+server+":"+port+"/"+dbname+

"?user="+user+"&password="+pass+

"&useUnicode=true&characterEncoding=GB2312"

Class.forName(MySqldriver)

conn = DriverManager.getConnection(MySqlURL)

}catch(Exception e){

System.out.println("操作数据库出错,请仔细检查")

//System.err.println(e.getMessage())

}

return conn

}

//关闭数据库连接

public void close()

{

try{

//rs.close()

//stmt.close()

conn.close()

}catch(SQLException sqlexception){

sqlexception.printStackTrace()

}

}

}

这个文件只是实现了数据库的连接,下面我们再写一个测试文件。

就是用sql语句从数据库里查询出记录,以验证我们数据库的连接是否成功。

connmysql.jsp文件源代码如下:

<%@ page contentType="text/htmlcharset=gb2312" language="java"

import="java.sql.*" %>

<%

//以下几项请自行修改

String server="localhost" //MYSQL 服务器的地址

String dbname="test" //MYSQL 数据库的名字

String user="root" //MYSQL 数据库的登录用户名

String pass="chfanwsp" //MYSQL 数据库的登录密码

String port="3306" //SQL Server 服务器的端口号,默认为1433

Connection conn=DBConn.getConnToMySql(server,dbname,user,pass,port)

Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,

ResultSet.CONCUR_READ_ONLY)

String sql="select * from username"

String sql1="insert into username (uid,pwd) values('梦想年华','梦想年华')"

stmt.executeUpdate(sql1)

ResultSet rs=stmt.executeQuery(sql)

while(rs.next()){

out.print("用户名:")

out.print(rs.getString("uid")+" 密码:")

out.println(rs.getString("pwd")+"

")

}

//rs.close()

//stmt.close()

//conn.close()

DBConn.close()

%>

获取表单中的信息,然后插入到Mysql中 

<%@ page language="java" contentType="text/html charset=gbk"

    pageEncoding="gbk"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<%

int id = Integer.parseInt(request.getParameter("id"))

int rootid = Integer.parseInt(request.getParameter("rootid"))

%>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html charset=gbk">

<title>Replay</title>

</head>

<body>

<form method="post" action="ReplayOK.jsp">

 <input type="hidden" name="id" value="<%=id %>">

 <input type="hidden" name="rootid" value="<%=rootid %>">

<table align="center">

 <tr>

  <td>

   <input type="text" name="title" size="80">

  </td>

 </tr>

 <tr>

  <td>

   <textarea cols="80" rows="20" name="cont"></textarea>

  </td>

 </tr>

 <tr>

  <td>

   <input type="submit" value="提交">

  </td>

 </tr>

</table>

</form>

</body>

</html>

---------------------------------------------------------------

下面接收上面表单中传过来的信息,并插入到mysql中

<%@ page language="java" contentType="text/html charset=gbk"

    pageEncoding="gbk"%>

<%@ page import="java.sql.*" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<%

request.setCharacterEncoding("GBK")

int id = Integer.parseInt(request.getParameter("id"))

int rootid = Integer.parseInt(request.getParameter("rootid"))

String title = request.getParameter("title")

String cont = request.getParameter("cont").replaceAll("\n","<br/>")

Connection conn = null

Statement st = null

Class.forName("com.mysql.jdbc.Driver")

conn = DriverManager.getConnection("jdbc:mysql://localhost/bbs?user=root&password=690115399")

st = conn.createStatement()

conn.setAutoCommit(false)

String sql = "insert into article values(null,?,?,?,?,now(),0)"

PreparedStatement pstmt = conn.prepareStatement(sql)

pstmt.setInt(1,id)

pstmt.setInt(2,rootid)

pstmt.setString(3,title)

pstmt.setString(4,cont)

pstmt.executeUpdate()

st.executeUpdate("update article set isleaf = 1 where id = " + id)

conn.commit()

conn.setAutoCommit(true)

st.close()

pstmt.close()

conn.close()

%>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html charset=gbk">

<title>Insert title here</title>

</head>

<body>

<%response.sendRedirect("ShowArticleTree.jsp") %>

</body>

</html>

当然最好的方法还是应该用jsp + JavaBean方式。

分类: 电脑/网络 >>软件

问题描述:

我制作的是留言版,回复时得弄分页,但是不知道分页怎么弄,网上的代码没有注释,也看不懂。

请各位大哥大姐们一定要帮帮我,后面加上注释,谢谢!

注意:我不用JavaBean写,就用前台写。

解析:

作为参考:

<%@ page contentType="text/charset=8859_1" %>

<%

变量声明

java.sql.Connection sqlCon数据库连接对象

java.sql.Statement sqlStmtSQL语句对象

java.sql.ResultSet sqlRst结果集对象

javang.String strCon数据库连接字符串

javang.String strSQLSQL语句

int intPageSize一页显示的记录数

int intRowCount记录总数

int intPageCount总页数

int intPage待显示页码

javang.String strPage

int i

设置一页显示的记录数

intPageSize = 2

取得待显示页码

strPage = request.getParameter("page")

if(strPage==null){表明在QueryString中没有page这一个参数,此时显示第一页数据

intPage = 1

}

else{将字符串转换成整型

intPage = javang.Integer.parseInt(strPage)

if(intPage<1) intPage = 1

}

装载JDBC驱动程序

java.sql.DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver())

设置数据库连接字符串

strCon = "jdbc:oracle:thin:@linux:1521:ora4cweb"

连接数据库

sqlCon = java.sql.DriverManager.getConnection(strCon,"hzq","hzq")

创建一个可以滚动的只读的SQL语句对象

sqlStmt = sqlCon.createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,java.sql.ResultSet.CONCUR_READ_ONLY)

准备SQL语句

strSQL = "select name,age from test"

执行SQL语句并获取结果集

sqlRst = sqlStmt.executeQuery(strSQL)

获取记录总数

sqlRstst()

intRowCount = sqlRst.getRow()

记算总页数

intPageCount = (intRowCount+intPageSize-1) / intPageSize

调整待显示的页码

if(intPage>intPageCount) intPage = intPageCount

%>

<>

<head>

<meta -equiv="Content-Type" content="text/charset=gb2312">

<title>JSP数据库操作例程 - 数据分页显示 - JDBC 2.0 - Oracle</title>

</head>

<body>

<table border=1 cellspacing="0" cellpadding="0">

<tr>

<th>姓名</th>

<th>年龄</th>

</tr>

<%

if(intPageCount>0){

将记录指针定位到待显示页的第一条记录上

sqlRst.absolute((intPage-1) * intPageSize + 1)

显示数据

i = 0

while(i<intPageSize &&!sqlRst.isAfterLast()){

%>

<tr>

<td><%=sqlRst.getString(1)%></td>

<td><%=sqlRst.getString(2)%></td>

</tr>

<%

sqlRst.next()

i++

}

}

%>

</table>

第<%=intPage%>页 共<%=intPageCount%>页 <%if(intPage<intPageCount){%><a href="jdbc20-oracle.jsp?page=<%=intPage+1%>">下一页</a><%}%><%if(intPage>1){%><a href="jdbc20-oracle.jsp?page=<%=intPage-1%>">上一页</a><%}%>

</body>

</>

<%

关闭结果集

sqlRst.close()

关闭SQL语句对象

sqlStmt.close()

关闭数据库

sqlCon.close()

%>

可以试试先!

祝你好运!

----------------------------------

也可以用jsp+xml+来实现,下面给出一个saucer(思归)给的xml+的分页例子,不妨参考一下:

<>

<body>

<!--the following XML document is "stolen" from MSXML4 documentation-->

<xml id="xmldoc">

<catalog>

<book id="bk101">

<author>Gambardella, Matthew</author>

<title>XML Developer's Guide</title>

<genre>Computer</genre>

<price>44.95</price>

<publish_date>2000-10-01</publish_date>

<description>An in-depth look at creating applications

with XML.</description>

</book>

<book id="bk102">

<author>Ralls, Kim</author>

<title>Midnight Rain</title>

<genre>Fantasy</genre>

<price>5.95</price>

<publish_date>2000-12-16</publish_date>

<description>A former architect battles corporate zombies,

an evil sorceress, and her own childhood to bee queen

of the world.</description>

</book>

<book id="bk103">

<author>Corets, Eva</author>

<title>Maeve Ascendant</title>

<genre>Fantasy</genre>

<price>5.95</price>

<publish_date>2000-11-17</publish_date>

<description>After the collapse of a nanotechnology

society in England, the young survivors lay the

foundation for a new society.</description>

</book>

<book id="bk104">

<author>Corets, Eva</author>

<title>Oberon's Legacy</title>

<genre>Fantasy</genre>

<price>5.95</price>

<publish_date>2001-03-10</publish_date>

<description>In post-apocalypse England, the mysterious

agent known only as Oberon helps to create a new life

for the inhabitants of London. Sequel to Maeve

Ascendant.</description>

</book>

<book id="bk105">

<author>Corets, Eva</author>

<title>The Sundered Grail</title>

<genre>Fantasy</genre>

<price>5.95</price>

<publish_date>2001-09-10</publish_date>

<description>The o daughters of Maeve, half-sisters,

battle one another for control of England. Sequel to

Oberon's Legacy.</description>

</book>

<book id="bk106">

<author>Randall, Cynthia</author>

<title>Lover Birds</title>

<genre>Romance</genre>

<price>4.95</price>

<publish_date>2000-09-02</publish_date>

<description>When Carla meets Paul at an ornithology

conference, tempers fly as feathers get ruffled.</description>

</book>

<book id="bk107">

<author>Thurman, Paula</author>

<title>Splish Splash</title>

<genre>Romance</genre>

<price>4.95</price>

<publish_date>2000-11-02</publish_date>

<description>A deep sea diver finds true love enty

thousand leagues beneath the sea.</description>

</book>

<book id="bk108">

<author>Knorr, Stefan</author>

<title>Creepy Crawlies</title>

<genre>Horror</genre>

<price>4.95</price>

<publish_date>2000-12-06</publish_date>

<description>An anthology of horror stories about roaches,

centipedes, scorpions and other insects.</description>

</book>

</catalog>

</xml>

<table id="mytable" datasrc="#xmldoc" border=1 DATAPAGESIZE="2">

<thead><th>Title</th><th>Author</th><th>Genre</th><th>Publish Date</th><th>Price</th></thead>

<tbody><tr>

<td><span datafld="title"></span></td>

<td><span datafld="author"></span></td>

<td><span datafld="genre"></span></td>

<td><span datafld="publish_date"></span></td>

<td><span datafld="price"></span></td>

</tr>

</tbody>

</table>

<input type=button value="previous page" onclick="mytable.previousPage()">

<input type=button value="next page" onclick="mytable.nextPage()">

</body>

</>

------------------------------------

分页显示的模板程序

<!--show_page.jsp-->

<%@ page import="javang.*" import="java.sql.*" import="java.util.*" contentType="text/charset=GB2312"%>

<%@ page import="tax.*"%>

<jsp:useBean id="RegisterBean" class="tax.RegisterBean" scope="page"/>

<jsp:useBean id="itemlist" class="tax.itemlist" scope="page"/>

<%

int PageSize = 10设置一页显示的记录数

int PageNum = 1初始化页码=1

int PageNumCount = (136+PageSize-1) / PageSize记算总页数

计算要显示的页码

String strPageNum = request.getParameter("page")取得<href>提交的页码

if(strPageNum==null){ 表明在QueryString中没有page这一个参数,此时显示第一页数据

PageNum = 1

}

else{

PageNum = javang.Integer.parseInt(strPageNum)将字符串转换成整型

if(PageNum<1) PageNum = 1

}

if(PageNum>PageNumCount) PageNum = PageNumCount调整待显示的页码

%>

<>

<head>

<meta -equiv="Content-Type" content="text/charset=gb2312">

<title>JSP例程 - 数据分页显示 -JDK1.2 </title>

</head>

<body>

<%

if(PageNumCount>0){

out.println(PageNum)显示数据,此处只简单的显示页数

}

/*需要显示的数据,在此处显示

、、、

例如:

*/

显示一个简单的表格

%>

<table border=1 cellspacing="0" cellpadding="0">

<tr>

<th>总数</th>

<th>页数</th>

</tr>

<tr>

<th><%=PageNumCount%></th>

<th><%=PageNum%></th>

</tr>

</table>

第<%=PageNum%>页 共<%=PageNumCount%>页

<%if(PageNum<PageNumCount){%><a href="show_page.jsp?page=<%=PageNum+1%>">下一页</a><%}%>

<%if(PageNum>1){%><a href="show_page?page=<%=PageNum-1%>">上一页</a><%}%>

</body>

</>

---------------------------------

一个bean,按照文档说的用。也希望你给出修改意见。

package mshtang

/**

* <p>Title: DataBaseQuery</p>

* <p>Description: 用于数据库翻页查询操作</p>

* <p>Copyright: 厦门一方软件公司版权所有Copyright (c) 2002</p>

* <p>Company: 厦门一方软件公司</p>

* @author 小唐蔡

* @version 1.0

*/

import java.sql.*

import javax.servlet..*

import java.util.*

import mshtang.StringAction

public class DataBaseQuery

{

private HttpServletRequest request

private StringAction S

private String sql

private String userPara

private String[][] resultArray

private String[] columnNameArray

private String[] columnTypeArray

private int pageSize

private int columnCount

private int currentPageNum

private int currentPageRecordNum

private int totalPages

private int pageStartRecord

private int totalRecord

private static boolean initSuccessful

private String currentJSPPageName

private String displayMessage

public DataBaseQuery()

{

S = new StringAction()

sql = ""

pageSize = 10

totalRecord = 0

initSuccessful = false

currentJSPPageName = ""

displayMessage = ""

columnNameArray = null

columnTypeArray = null

currentPageRecordNum = 0

columnCount = 0

}

/**功能:数据库初始化操作,其它操作的前提。

*

* @param conn:数据库连接;

* @param request:jsp页面request对象;

* @param querySQL:查询语句;

* @param pageSize:每页显示记录数;

* @param startPageNum:开始显示页码

*/

public void init(Connection conn, HttpServletRequest request, String querySQL, int pageSize, int startPageNum)

{

if(conn != null)

{

this.request = request

this.sql = request.getParameter("querySQL")

this.userPara = request.getParameter("userPara")

if(sql == null || sql.equals(""))

{

sql = querySQL

}

if(this.userPara == null)

{

this.userPara = ""

}

if(S.isContains(sql, "selectfrom", "", true))

{

try

{

Statement st = conn.createStatement()

ResultSet rs = st.executeQuery(sql)

ResultSetMetaData r *** d = rs.getMetaData()

columnCount = r *** d.getColumnCount()

columnNameArray = new String[columnCount]

columnTypeArray = new String[columnCount]

String columnName

String value

while(rs.next())

{

totalRecord++

if(totalRecord == 1)

{

for(int i = 0i <columnCounti++)

{

columnNameArray[i] = r *** d.getColumnName(i + 1)

columnTypeArray[i] = r *** d.getColumnTypeName(i + 1)

}

}

}

rs.close()

在总记录数大于0的情况下进行下列操作

获取链接图象

if(totalRecord >0 &&pageSize >0 &&columnCount >0 &&startPageNum >0)

{

获取总页数

totalPages = totalRecord / pageSize

int tempNum = totalRecord % pageSize

if(tempNum != 0)

{

totalPages++

}

获得当前页页码

String currentPage = request.getParameter("currentPageNum")

currentPageNum = (currentPage == null || currentPage.equals(""))? startPageNum:Integer.parseInt(currentPage)

currentPageNum = (currentPageNum >totalPages)?totalPages:currentPageNum

currentPageNum = (currentPageNum <= 0)?1:currentPageNum

获得当前页起始显示记录数

pageStartRecord = (currentPageNum - 1) * pageSize + 1

pageStartRecord = (pageStartRecord <= 0)?1:pageStartRecord

pageStartRecord = (pageStartRecord >totalRecord)?totalRecord:pageStartRecord

获得当前页显示记录数

if(currentPageNum * pageSize >totalRecord)

{

currentPageRecordNum = totalRecord - (currentPageNum - 1) * pageSize

}

else

{

currentPageRecordNum = pageSize

}

resultArray = new String[currentPageRecordNum][columnCount]

用于跳过前面不需显示的记录

int continueRowNum = 0

用于跳过后面不再显示的记录

int breakRowNum = 0

ResultSet rs2 = st.executeQuery(sql)

while(rs2.next())

{

跳过前面不需显示的记录

continueRowNum++

if(continueRowNum <pageStartRecord)

{

continue

}

存取当前页需显示的记录到二维数组

for(int i = 0i <columnCounti++)

{

value = rs2.getString(columnNameArray[i])

value = (value == null)?"":value.trim()

resultArray[breakRowNum][i] = value

}

跳过后面不再显示的记录

breakRowNum++

if(breakRowNum >= currentPageRecordNum)

{

break

}

}

rs2.close()

}

st.close()

}

catch(SQLException e)

{

e.printStackTrace()

}

}

transferSQL(sql)

initSuccessful = true

}

}

/**功能:数据库初始化操作,其它操作的前提,默认每页显示10条记录。

*

* @param conn:数据库连接;

* @param request:jsp页面request对象;

* @param querySQL:查询语句;

* @param startPageNum:开始显示页码

*/

public void init(Connection conn, HttpServletRequest request, String querySQL, int startPageNum)

{

init(conn, request, querySQL, 10, startPageNum)

}

/**功能:数据库初始化操作,其它操作的前提,默认从第一页开始显示。

*

* @param conn:数据库连接;

* @param request:jsp页面request对象;

* @param querySQL:查询语句;

* @param pageSize:每页显示记录数;

*/

public void init(Connection conn, HttpServletRequest request, int pageSize, String querySQL)

{

init(conn, request, querySQL, pageSize, 1)

}

/**功能:数据库初始化操作,其它操作的前提,默认从第一页开始显示,每页显示10条记录。

*

* @param conn:数据库连接;

* @param request:jsp页面request对象;

* @param querySQL:查询语句;

*/

public void init(Connection conn, HttpServletRequest request, String querySQL)

{

init(conn, request, querySQL, 10, 1)

}

/**功能:给出没有初始化的提醒信息,内部调用。

*

*/

private static void getMessage()

{

if(!initSuccessful)

{

System.out.println("没有完成初始化")

}

}

/**功能:得到查询结果的总记录数。

*

* @return

*/

public int getTotalRecord()

{

getMessage()

return totalRecord

}

/**功能:得到当前页的页码

*

* @return

*/

public int getCurrentPageNum()

{

getMessage()

return currentPageNum

}

/**功能:获得当前页记录数

*

* @return

*/

public int getCurrentPageRecord()

{

getMessage()

return currentPageRecordNum

}

/**功能:获得总页数

*

* @return

*/

public int getTotalPages()

{

getMessage()

return totalPages

}

/**获得调用该javaBean的jsp页面文件名,用于翻页操作,可以免去外界输入页面参数的错误,用于内部调用。

*

* @return:调用该javaBean的jsp页面文件名

*/

private String getCurrentJSPPageName()

{

getMessage()

if(request != null)

{

String tempPage = request.getRequestURI()

String[] tempArray = S.stringSplit(tempPage, "/")

if(tempArray != null &&tempArray.length >0)

{

currentJSPPageName = tempArray[tempArray.length - 1]

}

}

return currentJSPPageName

}

/**功能:用于显示图片链接或字符串(上一页、下一页等链接)。用于翻页操作,内部调用

*

* @param imageSource:图片来源;

* @param i:翻页信息,1表示第一页,2表示上一页,3表示下一页,4表示尾页,

* @return:显示的链接图片或链接文字

*/

private void displayMessage(String imageSource, int i)

{

getMessage()

if(imageSource != null &&!imageSource.equals(""))

{

displayMessage = "<img src=\"" + imageSource + "\" border=\"0\">"

}

else

{

switch(i)

{

case 1:

displayMessage = "<font size=\"2\">[首页]</font>"

break

case 2:

displayMessage = "<font size=\"2\">[上一页]</font>"

break

case 3:

displayMessage = "<font size=\"2\">[下一页]</font>"

break

case 4:

displayMessage = "<font size=\"2\">[尾页]</font>"

}

}

}

/**功能:链接到相应页面,内部调用。

*

* @param imageSource:图片来源;

* @param i:翻页信息,1表示第一页,2表示上一页,3表示下一页,4表示尾页,

* @return:相应页面的链接

*/

private String getNavigation(String imageSource, int i)

{

displayMessage(imageSource, i)

int pageNum = 0

switch(i)

{

case 1:

pageNum = 1

break

case 2:

pageNum = currentPageNum - 1

break

case 3:

pageNum = currentPageNum + 1

break

case 4:

pageNum = totalPages

}

currentJSPPageName = "<a columnName, true)

if(resultArray != null &&columnIndex != -1)

{

columnValue = resultArray[recordIndex][columnIndex]

}

}

return columnValue

}

/**功能:方法重载。返回特定行特定列的值。

*

* @param recordIndex:行索引,从0开始;

* @param columnIndex:列索引,从1开始;

* @return

*/

public String g


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/53309.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-02-25
下一篇2023-02-25

发表评论

登录后才能评论

评论列表(0条)

    保存