java mvc建包结构_Java SSM框架的配置方法、MVC结构的分析、响应的流程
今天頭一次配置成功一個SSM框架,興奮之余,還應該從使用的角度,將整個ssm配置的方法,配置的原因,認真的分析一下。在結束了對SSM框架簡單的分析之后,就要開始回歸基礎,全面的認真復習。所以這個文檔,要盡量的完整,目標就是,這個文檔是是對SSM框架的學習,也是一個將來復習的資料。
1 RESOURCES 配置文件
1.1 配置文件簡介
這個部分用來解讀在resources文件夾下的配置信息。這一部分是整個ssm框架中,最難的一部分,也是最復雜的一部分。在配置這個部分的時候,盡管是不停的膚質粘貼,偶爾改一改路徑。但是這樣的一個 過程要比寫業務邏輯代碼麻煩的多。
1.1.1 jdbc.properties
這個文件是用來保存和數據庫連擊的相關的信息,比如JDBC驅動器、數據庫戶名、數據庫密碼等等,和數據庫相關的靜態信息,都會以KV的形式,保存在這個文件中。這樣在需要對數據庫的信息進行改變時,只需要打開這個文件,就可以對數據庫的配置進行改變。與之前傳統數據庫連接方式相比,在修改時,不用改變多處的信息。
1.1.2 spring-mvc.xml
和名字顯示的顯示的一樣,這是一個對MVC配置的一個文件。簡單來講有下面的幾點功能:
1 設定用來存放controller的包的位置。
2 以文件前綴、后綴的方式,設定存放JSP文件的路徑。
我對這個文件的理解為,從controller獲取執行哪一個文件的信息,在將這個信息,通過前綴和后綴的包裝,傳遞給下一級。
1.1.3 spring-mybatis.xml
這個配置也常常叫做:applicationContext.xml,但是其實是一個東西,都是用來配置mybatis。
1 將標注Spring注解的類自動轉化成Bean,并且完成Bean的注入。
2 配置數據庫相關的資源。
3 配置數據庫的sessionFactory
4 配置需要被掃描的用來存放DAO接口的接口包。
5 配置事務管理器。
1.1.4 UserDAO.xml
mapper.xml稍微好理解一些。就是使用DAO接口的全限定地址,和DAO中的操作數據庫的sql方法,封裝起來,那么調用DAO接口的某個方法的時候,就可以使用mapper.xml中封裝的sql語句操作數據庫。
通常在這個文件也叫做mapper.xml文件.
1.1.5 web.xml
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee?http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
SSM
SSM_test
encodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
encodingFilter
/*
SpringMVC
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring-*.xml
1
true
SpringMVC
/
index.html
1.1.6 其他
Logback是一個關于log日志的配置文件,并沒有使用sql文件夾。還有就是pom.xml文件,看起來很多,其實也就是添加了幾個依賴罷了。
pom.xml<?xmlversion ="1.0"?encoding="UTF-8"?>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0?http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
com.xzj
ssmSecondTry
1.0-SNAPSHOT
war
ssmSecondTry?Maven?Webapp
http://www.example.com
UTF-8
UTF-8
4.3.5.RELEASE
3.4.1
javax
javaee-api
7.0
junit
junit
4.12
ch.qos.logback
logback-classic
1.2.2
com.fasterxml.jackson.core
jackson-databind
2.8.7
mysql
mysql-connector-java
5.1.41
runtime
com.mchange
c3p0
0.9.5.2
org.mybatis
mybatis
${mybatis.version}
org.mybatis
mybatis-spring
1.3.1
org.springframework
spring-core
${spring.version}
org.springframework
spring-beans
${spring.version}
org.springframework
spring-context
${spring.version}
org.springframework
spring-jdbc
${spring.version}
org.springframework
spring-tx
${spring.version}
org.springframework
spring-web
${spring.version}
org.springframework
spring-webmvc
${spring.version}
org.springframework
spring-test
${spring.version}
ssmSecondTry
org.apache.maven.plugins
maven-compiler-plugin
1.8
1.8
maven-clean-plugin
3.1.0
maven-resources-plugin
3.0.2
maven-compiler-plugin
3.8.0
maven-surefire-plugin
2.22.1
maven-war-plugin
3.2.2
maven-install-plugin
2.5.2
maven-deploy-plugin
2.8.2
logback.xml<?xml ?version="1.0"?encoding="UTF-8"?>
%d{HH:mm:ss.SSS}?[%thread]?%-5level?%logger{36}?-?%msg%n
1.2 JDBC.PROPERTIES
1.2.1 代碼driver?=com.mysql.jdbc.Driver
url?=jdbc:mysql://localhost:3306/mySSM
username?=root
password?=admin97
maxPoolSize?=30
minPoolSize?=10
autoCommitOnClose?=false
checkoutTimeout?=10000
acquireRetryAttempts?=2
1.2.2 代碼解析
前面四行是我們在操作JDBC的時候,常常操作的四項,分別是:驅動器、地址、用戶名、密碼。
第7行設定最大連接數為30。最大連接數是連接池能申請的最大連接數。如果數據連接請求超過此數,后面的數據連接請求將被加入到等待隊列中,這會影響之后的數據庫操作。
第8行設定最小連接數為10。最小連接數是連接池一直保持的數據連接。如果應用程序對數據庫連接的使用量不大,將會有大量的數據庫連接資源被浪費掉。
第9行設定在關閉之后,不會自動執行commit。如果設置為true,那么在數據庫的連接狀態關閉的時候,會將沒有commit的數據庫操作,執行commit。
第10行設定連接超時時間。
第11行設定失敗后嘗試的次數。
這一個文件的設置十分明確。并且在它被讀取的時候,也是以鍵值對的形式被讀取的。
1.2 SPRING-MVC.XML
1.2.1 代碼<?xmlversion ="1.0"?encoding="UTF-8"?>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
1.2.2 代碼解析
在這樣的一個文件中,第1~11行都是環境。
第14行設置存放controller的目錄,在這個目錄下的類都會被掃描。
第17行將設定模式為注解模式,解析base-package目錄下面帶有@Controller注解的類。
第23~27行設定這個解析的前綴和后綴,前綴設定這個文件的目錄,后綴設定這個文件的拓展名。
1.2.3 功能簡析
SpringMVC是View層的一部分,來自于頁面的信息由SpringMVC控制的Controller將請求發送到Model層中的Service中,然后再Model中處理業務邏輯。從Model返回的model,添加上前綴和后綴,傳遞到View層中。
所以,具體的細分的話,這是一個介于頁面和Model層之間的模塊:
1 將來自頁面的請求,傳遞到合適的controller。
2 將從controller返回的一個jsp文件名的字符串,在這里包裝之后,的到下一個jsp文件的全限定路徑,然后顯示出來。當然并不是所有的controller都有返回值,如果沒有,那就是在當前的頁面修改。
1.3 SPRING-MYBATIS.XML
1.3.1 代碼<?xmlversion ="1.0"?encoding="UTF-8"?>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
1.3.2 代碼解析
第14行:加上這一行以后,將自動掃描路徑下面的包,如果一個類帶了@Service注解,將自動注冊到Spring容器,不需要在spring-mybatis.xml文件定義bean了。類似的注解還有Component、Repository、Controller。
例如:有下面一個類位于com.xzj.service或其子目錄中:@Service("xxx")
@Scope("yyy")
publicclasstestextendsAimplementsB{
······
}
那么就相當于在spring-mybatis.xml添加了一段這樣的。
......
簡而言之,這是一個將帶有注解的類添加到Spring容器的語句。
第20~30行,創建數據庫連接池,讀取jdbc.properties文件中的有關于數據庫的設置,按照這樣的設置,設定數據庫連接池的屬性。
1.3.3 功能簡析
縱觀整個項目,就是這一塊是最復雜的,在上面的代碼中:
第50行和第38行的bean將DAO接口和mapper連接起來。這樣的配置,使得在使用DAO接口的時候,直接調用接口方法,就可以直接調用DAO.xml中的sql語句。
另外的一點就是注冊了service的目錄,將service的內容注冊到了Spring的容器中。也就是說,這個這個文件配置了兩個方面的內容:一個是以service代表的業務邏輯,一個是以DAO及其映射mapper代表的數據訪問,這兩者共同組成了Model層。
1.4 WEB.XML
1.4.1 web.xml的代碼<?xmlversion ="1.0"?encoding="UTF-8"?>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee?http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
SSM
SSM_test
encodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
encodingFilter
/*
SpringMVC
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring-*.xml
1
true
SpringMVC
/
index.html
1.4.2 代碼解析
配置編碼過濾器。
配置分發器,并且這里的分發器中,注入了兩個xml文件。
配置welcome頁面。
2 MVC三層結構的簡析
2.1 MVC的構成
2.1.1 M層
M層表示Model層,模型層。用來實現業務邏輯、對數據進行訪問。
這一層大概分為三個部分,Model、Service、DAO這樣的三塊,以我創建的這個工程來講三個部分分別是:
1 User類,這個類中有三個屬性,分別有他們的get、set方法。
2 Service接口及其實現類。在spring-mybatis.xml中配置,從而被掃描。
3 UserDAO接口,在spring-mybatis.xml中配置,與UserDAO.xml配對,被動態實現。
即:這層的三個模塊都是在spring-mybatis.xml中被配置的。
2.1.2 V層
V層表示View層,顯示層。是用來和用戶交互的可視化界面,如html和jsp文件在瀏覽器中的顯示。同樣,在這些顯示頁面中,可以設定不同的請求,根據不同的前端動作,提交給分發器。那么這樣的到的響應也不同。
2.1.3 C層
C層表示Controller控制器。C層大致上有兩種功能:
1 根據不同的請求,調用M層中不同業務邏輯處理。
2 得到了來自M層處理結果的返回,給予V層的顯示結果也不相同。
這一塊是在spring-mvc.xml配置的。
2.2 M層的具體構成
2.2.1 簡述
M層是Model層,負責業務邏輯和數據訪問。以這個項目為例子,除了controller 以外的Java類和接口都是屬于Model層的的,除此之外還有UserDAO.xml也是屬于Model層的。
2.2.2 User類
User的代碼如下:packagecom.xzj.model;
//?@?author?:zjxu?time:2018/12/31
publicclassUser{
privateintuserID;
privateStringuserName;
privateStringuserPassword;
privateStringcomments;
publicintgetUserID()?{
returnuserID;
}
publicStringgetUserName()?{
returnuserName;
}
publicStringgetUserPassword()?{
returnuserPassword;
}
publicStringgetComments()?{
returncomments;
}
publicvoidsetUserID(intuserID)?{
this.userID=userID;
}
publicvoidsetUserName(StringuserName)?{
this.userName=userName;
}
publicvoidsetUserPassword(StringuserPassword)?{
this.userPassword=userPassword;
}
publicvoidsetComments(Stringcomments)?{
this.comments=comments;
}
@Override
publicStringtoString()?{
return"User{"+
"userID="+userID+
",?userName='"+userName+'\''+
",?userPassword='"+userPassword+'\''+
",?comments='"+comments+'\''+
'}';
}
}
言簡意賅,這一段代碼就是定義一個User類,并且定義了幾個域。id、name、password、comments。設定了它們的getter和setter。
2.2.3 UserService接口packagecom.xzj.service;
importcom.xzj.model.User;
//?@?author?:zjxu?time:2018/12/31
publicinterfaceUserService{
publicUserselectUser(longuserID);
}
申明一個接口,這個接口是Model層中的service的接口。它的實現類,必須實現在這個類中定義的方法。其實這個接口并不是必須的,在spring-mybatis.xml中,配置的com.xzj.service目錄中直接寫UserServiceImple類,即可將這個類配置進spring中。但是有這個過接口可以將Model層中的service服務的結構更加清晰。所以在這個工程中,就使用了UserService接口。
2.2.4 UserServiceImple 類packagecom.xzj.service.imple;
//?@?author?:zjxu?time:2018/12/31
importcom.xzj.DAO.UserDAO;
importcom.xzj.model.User;
importcom.xzj.service.UserService;
importorg.springframework.stereotype.Service;
importjavax.annotation.Resource;
@Service("userService")
publicclassUserServiceImpleimplementsUserService{
@Resource
privateUserDAOuserDAO;
publicUserselectUser(longUserID)?{
returnthis.userDAO.selectUser(UserID);
}
}
UserService的實現類,其中兩個很重要的是兩個注解11和14行的兩個注解。 ?第11行的注解@Service("userService”),表示是為userService服務的,這個userService是controller的userService類。
2.2.5 UserDAO 接口packagecom.xzj.DAO;
//?@?author?:zjxu?time:2018/12/31
importcom.xzj.model.User;
publicinterfaceUserDAO{
UserselectUser(longid);
}
2.2.5 UserDAO.xmlmapper?PUBLIC?"-//mybatis.org//DTD?Mapper?3.0//EN"?"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
SELECT?*?FROM?userList?WHERE?userID?=?#{id}
2.3 C層的具體構成
2.3.1 簡述
C層就是 controller,位于Model層和View層之間的一層。
2.3.2 Controller 類packagecom.xzj.controller;
//?@?author?:zjxu?time:2018/12/31
importcom.fasterxml.jackson.databind.ObjectMapper;
importcom.xzj.model.User;
importcom.xzj.service.UserService;
importorg.springframework.stereotype.Controller;
importorg.springframework.web.bind.annotation.RequestMapping;
importorg.springframework.web.servlet.ModelAndView;
importjavax.annotation.Resource;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importjava.io.IOException;
@Controller
publicclassUserController{
@Resource
privateUserServiceuserService;
@RequestMapping("/showUser.do")
publicvoidselectUser(HttpServletRequestrequest,HttpServletResponseresponse,ModelAndViewmav)?throwsIOException{
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
longuserId=Long.parseLong(request.getParameter("id"));
Useruser=this.userService.selectUser(userId);
System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n"+userId+"\n\n\n\n\n\n\n\n\n\n\n\n");
ObjectMappermapper=newObjectMapper();
response.getWriter().write(mapper.writeValueAsString(user));
response.getWriter().close();
}
@RequestMapping("/test")
publicModelAndViewtest(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException{
ModelAndViewmav=newModelAndView();
mav.addObject("name",?"SpringMVC");
mav.setViewName("test");
returnmav;
}
}
2.3.3 Controller層注解的詳細分析
在controller中,重要的地方在于這幾個注解。controller、Resource、RequestMapping這單個注解。
1 注解@Controller。
表明這是一個Controller類,spring-mvc.xml文件設定的掃描目錄下被掃描。
2 注解@Resource。
這個注解放在UserService的申明的前一行。它聲明一個名為userService的對象,并且這個對象的類型為UserService接口的實現類。
通過@Resource注解,可以在service目錄下UserServiceImple類中找到帶有一個@Service("userService”)的注解,找到的注解中的變量名和這個注解下一行聲明的對象的變量名是一致的。
在service目錄下找到的那個類前面的注解表明在controller中的申明的對象的具體類型的UserServiceImple,它實現了UserService這個接口。
也就是說,@Service(“userService”)注解的類,為@Resource下一行的名為userService的對象服務。而它們一個位于service目錄下,一個位于controller目錄下。這兩個目錄都被添加到了spring-*.xml中。這樣的對應關系,是屬于兩個層的
3 注解@RequestMapping
參數類型為一個字符串。這個參數的意義是從controller來的除了項目以外的三級及以下的URL地址。比如:http://localhost:8080/ssm/test
這樣的一個地址,經過分發器,來到了controller,controller會根據除了localhost/ssm/之外的地址,調用不同的方法。在controller這端,就會將后面的這段url地址通過注解,標記在方法上,或者是類上面。以這個url來看,它就會調用UserController.test(request,response)方法。
注解的位置的區別在于:
<1> 類的上方沒有注解的時候,這個類的下面所有的方法的注解都需要添加參數。當然,也不是所有的方法都需要有注解。
但是只要是存在的注解都需要有參數。否則這樣寫的controller方法,作出的效果將會是“localhost:8080/ssm”的結果,這樣welcome頁面將會失效。
<2> 類的上方存在注解,那么這個注解會成為這個一個上級字符串加在類中的方法上的字符串上。就如同java的package的目錄一樣。com.xzj.test這樣子,只不過在這里是用’/’來連接。
2.4 V層的具體構成
V層是直接面對用戶的頁面。所以在V層中,寫的代碼都是面向用戶的操作的,盡管有一部分和請求相關,但是絕大部分還是于頁面的展示相關的。
2.4.1 index.html文件html>
testfunctionselectUser()?{
varxmlhttp=newXMLHttpRequest();
xmlhttp.onreadystatechange=function()?{
if(xmlhttp.readyState==4&&xmlhttp.status==200)?{
document.getElementById("test").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("POST",?"showUser.do",?true);
xmlhttp.setRequestHeader("Content-type",?"application/x-www-form-urlencoded");
xmlhttp.send("id=100");
}
Hello?World!
onclick?test
ThisIsALinkForTest
這段html代碼,其中的重點在于javascript代碼中的Ajax掌握。
這段短短的javascript,發起請求,獲得響應,設定顯示,完成這三個工作。
按鈕-響應,這一塊非常基礎的前端應用,主要的問題來自于響應方法中的Http請求。關于javascript的代碼邏輯,雖然一眼就能明了,但是,還是要仔細研究一下ajax如何在html文件中,更加精巧的應用。
對于這個連接,就是在點擊之后,會跳轉到顯示/WEB-INF/views/test.jsp相當于一個請求controller,并通過controller的到一個“test”的字符串,將其包裝成為了一個完整的路徑,在View層顯示。
2.4.2 jsp目錄及其下的test.jsp文件
CreatedbyIntelliJIDEA.
User:?thisxzj
Date:?2019/1/1
Time:?23:45
TochangethistemplateuseFile|Settings|FileTemplates.
--%>
xxxtest
我新建的項目是${name}
這個jsp的路徑是/WEB-INF/views/test.jsp,在從controller中返回一個字符串,比如一個“test”串,或者是modelAndView.setViewName("test”),并將其返回。
就會通過spring-mvc.xml中的下兩行,將其包裝成/WEB-INF/views/test.jsp。并將其顯示到頁面中。
在這樣一個jsp頁面中,${name}這個變量,是通過controller類中以返回modealAndView的方式,在modelAndView對象:modelAndView.addObject("name",?"SpringMVC");
那么在jsp頁面中,將會讀取這個KV,將name顯示為成“SpringMVC”。這樣就完成了一個從后臺向前臺的傳輸的過程。
響應過程
1 用戶在瀏覽器窗口輸入一個URL地址,以localhost:8080/ssm/為例子,由于這個URL是直接localhost/ssm/后面并沒有接更多的信息,就會直接顯示在web.xml中設定的welcome頁面index.html。 這個過程發生在View層。
2 于是在瀏覽器頁面上就會顯示index.html的內容。用戶按下顯示onclick test的按鈕,通過javascript的ajax發送一個包含一個字符串“showUser.do”和一個KV對“id = 1”的一個請求到controller,controller再根據請求中的“showUser.do”調用對應的controller方法。 這個過程從View層到Controller層。
3 請求來到Cotroller,通過掃描在Spring-MVC.xml中配置的目錄下的所有的Java類。找到這個目錄下所有帶有@Controller的類。在這些類中尋找“showUser.do”對應的方法。在Controller類的第24行找到了一個selectUser方法。那么就會執行這個方法,對來自View層的請求進行響應。這個過程發生在Controller層。
4 找到這個方法了,開始執行。這個方法的核心在于,使用了userService這個對象以及它的的方法。關于如何使用的,在2.3.3中有詳細的解釋。在在這個類中,使用這個對象以及它的seclectUser方法,就是工作從Controller層到Model層的轉移。
5 來到Model層,映入眼簾的就是Service接口的實現類ServiceImple。我們不關注Service接口,經過我的測試,去掉這個接口對程序的運行也沒有影響。但是這個接口的存在,可以使Service方法更加規范化。在大型工程中,有一個這樣的接口可以更加規范。在這個ServiceImple類中,申明了一個UserDAO的對象,這個對象并沒有實體。通過注解,將UserDAO.xml作為這個接口的實體,使用定義在UserDAO.xml中的sql語句操作數據庫。
sql語句和UserDAO的對應,通過在spring-mybatis.xml中,將mapper的目錄和DAO接口的目錄配置進去。這樣在mapper的xml中,聲明是對哪一個DAO接口的實現,并且在每一個sql方法的標簽內,設置id為對應的DAO接口中的方法名,就可以視作將DAO的方法在mapper的xml中實現了。
通過目錄、接口名、方法名的一系列配置,在調用UserDAO接口的方法的時候,就可以直接使用對應的sql語句。以:Useruser=this.userService.selectUser(userId);
然后在UserServiceImple中,調用UserDAO的方法:this.userDAO.selectUser(UserID);
在通過DAO的配置,使用UserDAO.xml中的sql語句操作數據庫。
這個部分的操作都是在Model層。但是將Model層分為兩個模塊:service和DAO的話,那么這個部分是在Model層中是從service到DAO的轉移。
6 我們忽略mapper的xml文件中具體執行了什么。只考慮對數據庫操作之后有沒有數據的返回。
如果沒有,那么一個從前到后的SSM請求到響應就已經結束了。
大多數時候是有返回的。通過mapper的xml文件中的result設定的返回值類型,將從數據庫中獲取的數值,包裝成一個返回類型,返回給UserServiceImple的對象。
在這個例子中是從數據庫中獲取指定id處的,一個User對象的所有信息,將其包裝成一個User對象,返回給UserServiceImple。
這個部分的操作都是在Model層,細分的話那么這個部分是在Model層中是從DAO到service的轉移。
7 UserServiceImple對象將從DAO獲得了一個User對象的返回值,返回給Controller層。
這一個操作是從Model層返回到Controller層。
8 這樣的一個User對象從DAO、Service傳遞了Controller層中由“showUser.do”對應的那個方法中繼續著下一步的操作。
通過下面兩行語句,將獲取的User對象轉換成一個字符串,然后傳送到javascript代碼中請求所對應的響應碼responseText中。ObjectMappermapper=newObjectMapper();
response.getWriter().write(mapper.writeValueAsString(user);
然后通過DOM操作,將html中的某個字段修改成User對象的字符串形式。完成了獲取內容在頁面上的顯示。這一步是從Controller層到View層的傳遞。
總結
以上是生活随笔為你收集整理的java mvc建包结构_Java SSM框架的配置方法、MVC结构的分析、响应的流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java模型给泛型_【一天一个基础系列】
- 下一篇: java美元兑换,(Java实现) 美元