在大一下學期,除了學習課文內容之余,在空暇的時間內進行了簡單的JavaWeb服務端學習。以此作為學習的總結為以后進一步學習的做好基礎。
我主要學習的是后端設計,而后端設計中分層次的進行開發是很重要的。分層開發有利于提高系統的可拓展性,增加新功能時于已有模塊不沖突。方便查錯與調試,某一層出問題不會牽一發而動全身。規范化,每一個業務功能實現都按照相同的結構來實現。Bean、Dao、Service、Servlet是服務端開發最基本最必要的層次,它其實是MVC開發模式的體現。在實際項目開發中可以選擇從Bean層開始設計根據數據庫的數據由下往上至Servlet開發,也可以根據前端需求從Servlet由上至下Service開發。下面以學校課表查詢為例對各層進行介紹。
一、Bean
public class TableBean {
private Integer id;
private String classCode;
private String semester;
private String section;
private String one;
private String two;
private String three;
private String four;
private String five;
private String six;
private String seven;
private String ClassName;
public TableBean(){}
public TableBean(Integer id, String classCode, String semester,
String section, String one, String two, String three, String four,
String five, String six, String seven, String className) {
this.id = id;
this.classCode = classCode;
this.semester = semester;
this.section = section;
this.one = one;
this.two = two;
this.three = three;
this.four = four;
this.five = five;
this.six = six;
this.seven = seven;
ClassName = className;
}
public String getClassName() {
return ClassName;
}
public void setClassName(String className) {
ClassName = className;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getClassCode() {
return classCode;
}
public void setClassCode(String classCode) {
this.classCode = classCode;
}
public String getSemester() {
return semester;
}
public void setSemester(String semester) {
this.semester = semester;
}
public String getSection() {
return section;
}
public void setSection(String section) {
this.section = section;
}
public String getOne() {
return one;
}
public void setOne(String one) {
this.one = one;
}
public String getTwo() {
return two;
}
public void setTwo(String two) {
this.two = two;
}
public String getThree() {
return three;
}
public void setThree(String three) {
this.three = three;
}
public String getFour() {
return four;
}
public void setFour(String four) {
this.four = four;
}
public String getFive() {
return five;
}
public void setFive(String five) {
this.five = five;
}
public String getSix() {
return six;
}
public void setSix(String six) {
this.six = six;
}
public String getSeven() {
return seven;
}
public void setSeven(String seven) {
this.seven = seven;
}
@Override
public String toString() {
return "TableBean [id=" + id + ", classCode=" + classCode
+ ", semester=" + semester + ", section=" + section + ", one="
+ one + ", two=" + two + ", three=" + three + ", four=" + four
+ ", five=" + five + ", six=" + six + ", seven=" + seven
+ ", ClassName=" + ClassName + "]";
}
}
Bean層主要進行的是提供對數據的存與取的方法即get和set方法。
二、Dao
public class ImpleDao implements InterDao {
/*
*課表
*/
public List<TableBean> getTimeTable(TableBean timetable) {
SqlSession session=null;
AccessUtil Util=new AccessUtil();
List<TableBean>Tlist=new ArrayList<TableBean>();
try {
session=Util.getSqlSession();
ITimeTable mapper = session.getMapper(ITimeTable.class);
Tlist=mapper.getTimetable(timetable);
} catch (IOException e) {
e.printStackTrace();
}finally{
Util.destorySession(session);
}
return Tlist;
}
/*
* 成績
*/
public List<Student> getGrade(Student student) {
SqlSession session=null;
AccessUtil Util=new AccessUtil();
List<Student>Slist=new ArrayList<Student>();
try {
session=Util.getSqlSession();
ITimeTable mapper = session.getMapper(ITimeTable.class);
Slist=mapper.getGrade(student);
} catch (IOException e) {
e.printStackTrace();
}finally{
Util.destorySession(session);
}
return Slist;
}
}
Dao層是數據交換層,它是連接數據庫的橋梁,對數據庫中的數據進行增刪改查的基本操作。
三、Service
public class ImpleService implements InterService {
/*
* 課表
*
*/
public List<TableBean> getTimeTable(String semester, String className) {
TableBean Tbean=new TableBean();
semester=semester.trim();
className=className.trim();
if(semester!=null&&className!=null){
Tbean.setSemester(semester);
Tbean.setClassName(className);
}
InterDao IDao=new ImpleDao();
return IDao.getTimeTable(Tbean);
}
/*
* 成績
*
*/
public List<Student> getGrade(String number, String password) {
Student student=new Student();
List<Student>Sl=new ArrayList<Student>();
number=number.trim();
password=password.trim();
if(password!=null&&number!=null){
if(password.matches("^[0.0-9.0]+$")&&number.matches("^[0.0-9.0]+$")){
student.setS_number(number);
student.setS_password(password);
InterDao IDao=new ImpleDao();
Sl= IDao.getGrade(student);
}
}
return Sl;
}
}
Service業務層對前端的數據進行業務處理,對服務端而言,各類它分析這個數據,就知道要調用哪個java類的哪個方法,于是去查找或創建這個對象,并調用其方法,再把方法返回的結果包裝成soap格式的數據,通過http響應消息回給客戶端。使之達到我們要實現的功能,調用Dao層方法向前端返回數據
public class GetTableSerlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String method=request.getParameter("method");
if("getTime".equals(method)){
this.getTime(request, response);
}
else if("getGrade".equals(method)){
this.getGrade(request, response);
}
}
/*
* 課表
*/
public void getTime(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//獲取頁面值
String semester=request.getParameter("SEMESTER");
String className=request.getParameter("CLASSNAME");
//獲取結果集
InterService Iservice=new ImpleService();
List<TableBean>List=Iservice.getTimeTable(semester,className);
if(List!=null&&List.size()>0){
request.setAttribute("TableList",List);
request.getRequestDispatcher("/Timetable.jsp").forward(request, response);
}
else{
request.setAttribute("Error","查無此課表");
request.getRequestDispatcher("/Error.jsp").forward(request, response);
}
}
/*
* 成績
*/
public void getGrade(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//獲取頁面值
String number=request.getParameter("number");
String password=request.getParameter("password");
//獲取結果集
InterService Iservice=new ImpleService();
List<Student>SList=Iservice.getGrade(number, password);
if(SList!=null&&SList.size()>0){
request.setAttribute("StudnetList",SList);
request.getRequestDispatcher("/StudentGrade.jsp").forward(request, response);
}
else{
request.setAttribute("Error","查無此學生");
request.getRequestDispatcher("/Error.jsp").forward(request, response);
}
}
}
Servlet是一個供其他Java程序(Servlet引擎)調用的Java類,它不能獨立運行,它的運行完全由Servlet引擎來控制和調度。針對客戶端的多次Servlet請求,通常情況下,服務器只會創建一個Servlet實例對象,也就是說Servlet實例對象一旦創建,它就會駐留在內存中,為后續的其它請求服務,直至web容器退出,servlet實例對象才會銷毀。Servlet控制層,是一個頁面攔截器負責攔截來自前端頁面的請求,調用Service的方法然后向頁面返回數據,實現前端頁面的動態顯示。
配置tomcat
在這種小項目中我們通常使用的是tomcat服務器,因為它是開源免費的,在我們剛剛接觸Javaweb來時使用很容易上手。電腦上安裝配置Tomcat的方法和java有些相同,不過首先需要配置好java的環境才行。
下載Tomcat文件,文件是一個exe的安裝文件,下載后直接安裝即可。
下載地址在百度輸入Tomcat進入官網即可找到下載文件。安裝文件沒有什么技巧,一直點擊下一步即可。
同樣安裝時注意安裝目錄,因為一會要配置和java一樣的環境變量。
同樣打開環境變量的配置窗口,在系統環境變量一欄點擊新建。
輸入內容如下:
變量名:CATALINA_HOME
變量值:剛剛安裝的路徑
測試安裝配置是否成功
找到暗黑族昂路徑下的bin 文件夾,找到里面的執行文件,運行,然后執行下面的操作。
打開瀏覽器,輸入http://localhost:8080.如果出現下面的內容說明成功了。****
如何在IDE中配置服務器
我們以myeclipse10作為開發工具為例
[運行Eclipse程序文件,打開Eclipse工作界面。
選擇菜單欄中的window——preferences。
選擇左側的 server——runtime environment——在彈出的窗口中選擇 add——然后選擇你的Tomcat的版本即可。
選擇tomcat的路徑,和java的版本即可完成配置工作。
數據庫的安裝
mysql是一個很好用的開源數據庫,在項目中我們往往要進行數據的交換,Mysql如何安裝呢
MySQL安裝文件分為兩種,一種是msi格式的,一種是zip格式的。如果是msi格式的可以直接點擊安裝,按照它給出的安裝提示進行安裝(相信大家的英文可以看懂英文提示),一般MySQL將會安裝在C:\Program Files\MySQL\MySQL Server 5.6 該目錄中;zip格式是自己解壓,解壓縮之后其實MySQL就可以使用了,但是要進行配置。
解壓之后可以將該文件夾改名,放到合適的位置,個人建議把文件夾改名為MySQL Server 5.6,放到C:\Program Files\MySQL路徑中。當然你也可以放到自己想放的任意位置。
完成上述步驟之后,很多用戶開始使用MySQL,但會出現圖示的錯誤。這是因為沒有配置環境變量所致。配置環境變量很簡單:
我的電腦->屬性->高級->環境變量
選擇PATH,在其后面添加: 你的mysql bin文件夾的路徑 (如:C:\Program Files\MySQL\MySQL Server 5.6\bin )
PATH=.......;C:\Program Files\MySQL\MySQL Server 5.6\bin (注意是追加,不是覆蓋)
配置完環境變量之后先別忙著啟動mysql,我們還需要修改一下配置文件(如果沒有配置,之后啟動的時候就會出現圖中的錯誤哦!:錯誤2 系統找不到文件),mysql-5.6.1X默認的配置文件是在C:\Program Files\MySQL\MySQL Server 5.6\my-default.ini,或者自己建立一個my.ini文件,
在其中修改或添加配置(如圖):
[mysqld]
basedir=C:\Program Files\MySQL\MySQL Server 5.6(mysql所在目錄)
datadir=C:\Program Files\MySQL\MySQL Server 5.6\data (mysql所在目錄\data)
以管理員身份運行cmd(一定要用管理員身份運行,不然權限不夠),
輸入:cd C:\Program Files\MySQL\MySQL Server 5.6\bin 進入mysql的bin文件夾(不管有沒有配置過環境變量,也要進入bin文件夾,否則之后啟動服務仍然會報錯誤2)
輸入mysqld -install(如果不用管理員身份運行,將會因為權限不夠而出現錯誤:Install/Remove of the Service Denied!)
安裝成功
安裝成功后就要啟動服務了,繼續在cmd中輸入:net start mysql(如圖),服務啟動成功!
此時很多人會出現錯誤,請看注意:
注意:這個時候經常會出現錯誤2和錯誤1067。
如果出現“錯誤2 系統找不到文件”,檢查一下是否修改過配置文件或者是否進入在bin目錄下操作,如果配置文件修改正確并且進入了bin文件夾,需要先刪除mysql(輸入 mysqld -remove)再重新安裝(輸入 mysqld -install);
如果出現錯誤1067,那就是配置文件修改錯誤,確認一下配置文件是否正確。
服務啟動成功之后,就可以登錄了,如圖,輸入mysql -u root -p(第一次登錄沒有密碼,直接按回車過),登錄成功!
Mysql-join的使用
1.Left Outer Join左外連接
設數據庫中有A、B兩表,A和B有共同的交集C,當我們想查詢出A的所有記錄時我們可以使用左外連接:
select <select_list> from TableA A Left Join TableB B on A.key=B.key
當我們只想查詢出只有A表才有的數據而B表沒有的數據時,即去掉集合C
select <select_list> from TableA A Left Join TableB B on A.key=B.key where B.key is NULL
2.右外連接
右外連接與左連接是類似的,只是我們把哪個表看為基礎表的區別而已。左外連接將A作為基礎表,右連接我們把B作為基礎表。在A、B表中,查詢出B表的所有記錄
select <select_list> from TableA A Right Join TableB B on A.key=B.key
只查詢出B表存在而A表沒有的記錄
select <select_list> from TableA A Right Join TableB B on A.key=B.key where B.key is NULL
3.全連接
當需要查詢出A、B兩表的所有數據時可以使用全鏈接(Full Join)但在Mysql中是不支持Full Join的。但我們可以通過左連接+右連接的聯合達到Full Join的效果,即:
select <select_list> from TableA A Left Join TableB B on A.key=B.key UNION ALL select <select_list> from TableA A Right Join TableB B on A.key=B.key
4.交叉連接
交叉連接(cross join)又稱為笛卡兒積連接(cartesian join)或差乘,如果A和B是兩個集合,它們的交叉連接記為:A x B。即A表中的一條記錄與B表中每一條記錄進行匹配,產生一個新的結果集。如果A中有4條記錄,B中有5條記錄,則會產生20條結果
select <select_listA>,<select_listB> from TableA A CROSS JOIN TableB B
Mybatis的MyBatis一對多和一對一xml文件的配置
在使用mybatis的時候我們經常要用到聯合查詢,現在就對一表對多表和一對一表的xml文件配置進行說明
Student.xml
<resultMap type="many.one.entiry.Student" id="StudentResult">
<id column="s_id" jdbcType="INTEGER" property="id"/>
<result column="o_id" jdbcType="INTEGER" property="oid"/>
<result column="s_name" jdbcType="VARCHAR" property="name"/>
<result column="s_sex" jdbcType="VARCHAR" property="sex"/>
<association property="teacher" javaType="many.one.entiry.Teacher" resultMap="many.one.mapper.TeacherMapper.TeacherResult" ></association>
<collection property="courseList" ofType="many.one.entiry.Course" resultMap="many.one.mapper.CourseMapper.CourseResult" />
</resultMap>
StudentBean
public class Student {
private Integer id;
private String name;
private String sex;
private Integer oid;
private Teacher teacher;//一對一
private List<Course> courseList;//一對多
public Student() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Integer getOid() {
return oid;
}
public void setOid(Integer oid) {
this.oid = oid;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
public Achievement getAchievement() {
return achievement;
}
public void setAchievement(Achievement achievement) {
this.achievement = achievement;
}
public List<Course> getCourseList() {
return courseList;
}
public void setCourseList(List<Course> courseList) {
this.courseList = courseList;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", sex=" + sex
+ ", oid=" + oid + ", teacher=" + teacher + ", achievement="
+ achievement + ", courseList=" + courseList + "]";
}
}
一對一在Bean中我們可以將其對象作為自身實體類的一個成員變量,一對多返回的結果是一個集合所以將其集合作為成員變量。
CourseBean
public class Course {
private Integer c_id;
private Integer c_sid;
private String biology;
private String physic;
private String chemistry;
public Course(){}
public Integer getC_id() {
return c_id;
}
public void setC_id(Integer c_id) {
this.c_id = c_id;
}
public Integer getC_sid() {
return c_sid;
}
public void setC_sid(Integer c_sid) {
this.c_sid = c_sid;
}
public String getBiology() {
return biology;
}
public void setBiology(String biology) {
this.biology = biology;
}
public String getPhysic() {
return physic;
}
public void setPhysic(String physic) {
this.physic = physic;
}
public String getChemistry() {
return chemistry;
}
public void setChemistry(String chemistry) {
this.chemistry = chemistry;
}
@Override
public String toString() {
return "Course [c_id=" + c_id + ", c_sid=" + c_sid + ", biology="
+ biology + ", physic=" + physic + ", chemistry=" + chemistry
+ "]";
}
}
TeacherBean
public class Teacher {
private Integer t_id;
private String username;
private String password;
public Integer getT_id() {
return t_id;
}
public void setT_id(Integer t_id) {
this.t_id = t_id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Teacher [t_id=" + t_id + ", username=" + username
+ ", password=" + password + "]";
}
}
Course.xml
<resultMap type="many.one.entiry.Course" id="CourseResult">
<id column="c_id" jdbcType="INTEGER" property="c_id" />
<result column="c_sid" jdbcType="INTEGER" property="c_sid" />
<result column="c_biology" jdbcType="VARCHAR" property="biology" />
<result column="c_physic" jdbcType="VARCHAR" property="physic" />
<result column="c_chemistry" jdbcType="VARCHAR" property="chemistry" />
</resultMap>
teacher.xml
<resultMap type="many.one.entiry.Teacher" id="TeacherResult">
<id column="t_id" jdbcType="INTEGER" property="t_id" />
<id column="t_name" jdbcType="VARCHAR" property="username" />
<result column="t_password" jdbcType="VARCHAR" property="password" />
</resultMap>
association標簽是用來配置一對一表查詢的,collection是配置一對多表查詢的。
一對一查詢中mybatis會將查詢結果封裝到相應的對象中,如teacher對象,而一對多將返回一個List集合如List<courseList>.
總結
在我三周的暑假夏令營的學習中,第一次感受到身為一個程序員的壓力,996的工作模式讓我一度喘不過氣來同時帶來的也有自身的技術的巨大提升。
這次學習我收獲最大的就是學會了Mybatis框架的使用和向Android端的數據傳值。以前我們的做法使用JDBC來連接數據庫,這樣的做法是最基本的但是帶來的就是代碼的重復。如果使用jdbc代碼就要穿插在DAO層的代碼中,只是一兩個dao方法倒無所謂,但是如果上十個甚至更多呢?無疑就會出現一大堆的重復代碼,不好編寫更不利于以后的代碼維護。但使用了Mybatis框架后就可以很好的解決這個問題,實現了連接數據庫的代碼與DAO層的完全分離,dao層只負責提供方法,這樣就很好的利于以后的維護,大大減少了代碼量。Mybatis不僅包含了數據庫的連接操作更有對數據庫增刪改查的語法操作,本身提供了大量標簽也可以自己提供自定義標簽。mybatis的難點之一就是多表的配置,即一對多或多對一的情況,在我學習中我更喜歡的是多對一的配置,因為它比較直觀和簡單。在思考問題時我們可以換一個角度解決問題一對多從令一個角度去看它也是多對一的體現,所以在項目中我使用的都是多對一的配置。完全掌握一個技術最好的方法就是去看它的源代碼,但是我水平有限很多都看不懂包含了動態代理反射等機制,所以對于mybatis我也只是一個會用不理解其根本的水平。向android傳值有兩種方式即xml和json,剛開始我是想使用xml的方式但是老師說用json容易拓展和更普遍。所以又去學習了json的使用,其實json也沒有想象中那么難也是對java基本數據類型進行轉換變成一種新的數據模式即json。真正難的是如何從服務端傳值到Android,開始我在網上各個論壇尋找方法,看了很多例子還是不理解,后來我發現其實和服務端向網站頁面傳值的本是一樣的。向Android傳值只是多了將數據轉換成json打包到url路徑中即可,response響應后直接返回數據。明白了這一點后就很容易解決問題了,結合書本上和網上的例子,在加上學長的指點很快就解決了問題。
本次夏令營令我感觸很深的是老師上課所教的內容是很表面很簡單基礎的內容,在實際項目中如果只是掌握這些基礎實在是寸步難行,況且我們這次所合作的只是一個很小的項目而已,更不用說以后真正出去工作了。所以大學真正培養的是自學能力與拓展能力,當老師剛交給我們任務時我感到即緊張又害怕,因為我覺得當時我根本完成不了。在項目之前通過慕課網、技術論壇快速吸收的提升自己的技術,然而急于求成讓我只能學會模仿而不會拓展。但也只能硬著頭皮上,遇到問題再說。剛開始做的一兩天,技術的缺失讓我寸步難行常常十幾行代碼都要用上一個小時甚至更長的時間,bug更是層出不窮,真的是很窩火感覺自己之前的知識都是白學沒用的。幸好我堅持了下來,我知道這只是暫時的學習不可能能一步登天,從最初的按步照搬逐漸可以改編到自己的程序中使用,也明白了每一行代碼的意義。在接下來的學習中,我要進一步提升自學能力提升自己。