1. 程式人生 > >2017.4.19 慕課網-通過自動回覆機器人學習mybatis

2017.4.19 慕課網-通過自動回覆機器人學習mybatis

開發前的分析

1.技能前提

JSP JSTL EL JS/JQUERY

Servlet JavaBean

JDBC(後期再用mybatis,這樣體會更深) MYSQL

2.需求分析和模組劃分

(1)基本功能

1 接收發送指令
2 根據指令自動回覆對應的功能

(2)模組劃分

1 回覆內容維護
2 回覆內容列表3 對話功能
4 回覆內容刪除

開發:JSP+Servlet+JDBC

new -> web project -> 輸入project name為MicroMessage

step1:確認程式能跑起來

(1)ListServlet

 1  package com.imooc.servlet;
2 3 /** 4 * 列表頁面初始化控制 5 */ 6 public class ListServlet extends httpServlet { 7 @Override 8 protected void doGet(HttpServletRequest req, HttpServletResponse resp) 9 throws ServletException, IOExcepiton{ 10 req.getRequestDispatcher("/WEB-INF/jsp/back/list.jsp").forward(req,resp);
11 } 12 13 @Override 14 protected void doPost(HttpServletRequest req, HttpServletResponse resp) 15 throws ServletException, IOExcepiton{ 16 this.doGet(req,resp); 17 } 18 }

(2)web.xml中加入servlet的配置

1 <servlet>     
2      <servlet-name>ListServlet</
servlet-name> 3 <servllet-class>com.imooc.Servlet.ListServlet</servlet-class> 4 </servlet> 5 <servlet-mapping> 6 <servlet-name>ListServlet</servlet-name> 7 <url-pattern>/List.action</url-pattern> 8 </servlet-mapping>

(3)/WEB-INF/jsp/back/list.jsp

注意jsp檔案放在WEB-INF下,這樣必須經過後臺才能訪問到jsp。

如果放在WebRoot下(和WEB-INF平級)是能夠被直接訪問到的,除非設定了jsp攔截。

另外,關於jsp中如何使用專案的根目錄:

1 <% 
2 String path = request.getContextPath();
3 Sring basePath = request.getScheme()+"://"+request.getServiceName+":"+request.getServicePort()+path+"/"
4 %>

(4)/WebRoot/resources/css|images

在jsp檔案中引用css:

1 <head>
2     <meta .../>
3     <title ../>
4     <link href="<%= basePath =%>css/all.css" rel="stylesheet" type="text/css"/>
5 </head>

(5)執行程式碼

訪問路徑:localhost:8080/MicroMessage/List.action 。可以成功顯示靜態頁面。

step2:從資料庫中取資料

(1)建表

1 資料庫名:micro_message。
2 表名:message
3 賬號:root
4 密碼:root

(2)建立JavaBean

 1 package com.imooc.bean;
 2 
 3 /**
 4 *與訊息表對應的實體類
 5 */
 6 public class Message{
 7     private String id;
 8     private String command;
 9     private String description;
10     private String content;
11     //getter和setter略。
12 }

(3)Servlet中增加讀取資料的程式碼

 1 package com.imooc.servlet;
 2  
 3  /**
 4  * 列表頁面初始化控制
 5  */
 6  public class ListServlet extends httpServlet {
 7     @Override
 8     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
 9       throws ServletException, IOExcepiton{
10         try{
11         Class.forName("com.mysql.jdbc.Driver");
12         Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/micro_message","root","root");
13         String sql = "select ID,COMMAND,DESCRIPTION,CONTENT from MESSAGE"; //這裡不要寫select *
14         PreparedStatement statement = conn.prepareStatement(sql);16         ResultSet rs = statement.executeQuery();
17         List<Message> messageList = new ArrayList<Message>();
18         while(rs.next()){
19           Message message = new Message();
20           messageList.add(message);
21           message.setId(rs.getString("ID"));
22           message.setCommand(rs.getString("COMMAND"));
23           message.setDescription(rs.getString("DESCRIPTION"));
24           message.setContent(rs.getString("CONTENT"));
25         }
26         req.setAttribute("messageList",messageList);
27     }catch(ClassNotFoundException e){
28         e.printStackTrace();
29     }catch(SQLException e){
30          e.printStackTrace();
31     }
32      req.getRequestDispatcher(“/WEB-INF/jsp/back/list.jsp”).forward(req,resp);
33      }
34      
35     @Override
36     protected void doPost(HttpServletRequest req, HttpServletResponse resp)
37       throws ServletException, IOExcepiton{
38          this.doGet(req,resp);
39      }
40  }

(4)list.jsp中獲取值

這裡用到了jstl(c:forEach,c:if),所以要加上庫:<%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core” %>。其中的uri可以從/META-INF/c.tld中複製。c.tld有一個<uri>標籤,值就是http://java.sun.com/jsp/jstl/core。

另外,這裡還加上了偶數行有背景色的效果。因為status從0開始,所以實際上是表格的基數行

 1 <%@ taglib prefix=“c” uri=“http://java.sun.com/jsp/jstl/core”%>
 2 <c:forEach items=“${messageList}” var=“message” varStatus=“status”>
 3     
 4     <tr <c:if test=“${status.index%2!=0}”> style='background-color:#ECF6EE;’ </c:if> >
 5 >
 6         <td><input type=“checkbox”/></td>
 7         <td>${status.index+1}</td>
 8         <td>${message.command}</td>
 9         <td>${message.description}</td>
10         <td>
11             <a href=‘#’>修改</a>&nbsp;&nbsp;&nbsp;
12             <a href=‘#’>刪除</a>
13         </td>
14     </tr>
15 </c:forEach>

(5)執行

重啟專案(注意Servlet的生命週期,只例項化一次,所以必須要重啟才能生效。但是debug模式下eclipse會為servlet重新載入)訪問地址***,可以看到查出來的資料,和背景色效果。

step3:加查詢條件command和description

(1)在jsp中新增action,併為查詢框的input命名

 1 <form action="<%= basePath =%>List.action" id="mainForm" method="post">
 2 ...
 3     <td>
 4         <input name="command" type="text" class="allInput" value=""/>
 5     </td>
 6     <td>
 7         <input name="description" type="text" class="allInput" value=""/>
 8     </td>
 9 ..
10 </form>

(2)ListServlet中處理查詢引數

 2         req.setCharacterEncoding(“UTF-8"); //不加這句的話,在查詢框裡輸入中文,下面getParameter得到的值會是亂碼
 3         String command = req.getParameter("command");//和jsp中查詢框input的name匹配
 4         String description = req.getParameter("description");
4 try{
5   Class.forName("com.mysql.jdbc.Driver"); 6   Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/micro_message","root","root"); 7   StringBuilder sql = new StringBuilder(“select ID,COMMAND,DESCRIPTION,CONTENT from MESSAGE where 1==1"); 8   List<String> paramList = new ArrayList<String>(); 9   if(command != null && !"".equals(command.trim())){ 10     sql.append(" and COMMAND=?"); //注意這裡有個空格,否則拼接完成後有語法錯誤。 11   } 12   if(description != null && !"".equals(description.trim())){ 13     sql.append(“ and DESCRIPTION like '%'?'%'”);//mysql的模糊查詢格式 14   } 15   PreparedStatement statement = conn.prepareStatement(sql.toString()); 16   for(int i=0; i<paramList.size();i++){ 17     statement.setString(i+1,paramList.get(i)); //sql中?的位置從1開始 18   } 19   statement.executeQuery();
20 ...
21 }

(3)讓查詢框中的引數保留

前面執行後,可以發現,當在查詢框中輸入值進行查詢後,查詢框中的值會消失。是因為這裡的value為""。

1 <input name="description" type="text" class="allInput" value=""/>

首先要將引數的值儲存在req中,這樣jsp中才能拿到值。

1 req.setCharacterEncoding(“UTF-8");
2 String command = req.getParameter(“command”);
3 String description = req.getParameter(description);
4 
5 req.setAttribute("command",command);
6 req.setAttribute("description", description);
7 try{
8   Class.forName(“com.mysql.jdbc.Driver”);
9   Connection conn = DriverManager.getConnection(“jdbc:mysql://127.0.0.1:3306/micro_message”,”root”,”root”);          
10 ...
11 }

然後將jsp中input的value設定為req中的屬性值。

1 <input name="description" type="text" class="allInput" value="${description}"/>

重構:在進行下一步開發前整理程式碼

可以看到前面的程式碼,註釋少,內容都放在一個方法裡。所以需要對程式碼進行重構。根據功能進行層次劃分。

step1:dao層

 1 package com.immoc.dao;
 2 /**
 3 *和message表相關的資料庫操作
 4 */
 5 public class MessageDao{
 6     public List<Message> queryMessageList(String command,String description){
 7        List<Message> messageList = new ArrayList<Message>();
 8        try{
 9             Class.forName("com.mysql.jdbc.Driver");
10 ...
11 while(){...}
23 }catch(ClassNotFoundException e){ 24 e.printStackTrace(); 25 }catch(SQLException e){ 26 e.printStackTrace(); 27 } 28 return meesageList;
29 }
29 }

step2:service層

 1 package com.immoc.service
 2 /**
 3 *列表相關的業務功能
 4 */
 5 public class ListService{
 6     public List<Message> queryMessageList(String command, String description){
 7         MessageDao messageDao = new MessageDao();
 8         return messageDao.queryMessageList(command,description);
 9     }
10 }

step3: Servlet

 1 package com.imooc.servlet;
 2  
 3  /**
 4  * 列表頁面初始化控制
 5  */
 6  public class ListServlet extends httpServlet {
 7     @Override
 8     protected void doGet(HttpServletRequest req, HttpServletResponse resp)
 9       throws ServletException, IOExcepiton{
10 //接受頁面的值
10 req.setCharacterEncoding("UTF-8"); 11 String command = req.getParameter("command"); 12 String description = req.getParameter("description”); 13 //向頁面傳值 14 req.setAttribute("command",command); 15 req.setAttribute("description", description);
15 //查詢訊息列表並傳給頁面
16 ListService listService = new ListService(); 17 req.setAttribute("messageList”,listService.queryMessageList(command,description));
18 //向頁面跳轉
18 req.getRequestDispatcher(“/WEB-INF/jsp/back/list.jsp”).forward(req,resp); 19 } 20 ... 21 }

step4:執行測試。

mybatis

step1:下載mybatis

注意:mybatis-**-SNAPSHOT是正在開發的版本,不要下載使用。下載mybatis-**.zip後,也下載一下mybatis的source code。因為source code裡有一個test資料夾,裡面是一些演示程式碼,會有幫助。

下載完成後,將mybatis-**.jar放至專案的lib目錄下。

step2:mybatis的主配置檔案

從source code中拷貝檔案:src\test\java\org\apache\ibatis\submitted\complex_property\Configuration.xml 放到專案中

 1 <configuration>
 2 <environments>
 3     <environment>
 4         <transactionManager type=“JDBC”>
 5              <property name=“” value=“”/>
 6         </transactionManager>
 7         <dataSource type=“UNPOOLED”>
 8             <property name=“driver” value=“com.mysql.jdbc.Driver”/>
 9             <property name=“url” value=“adbc:mysql://127.0.0.1:3306/micro_message”/>
10             <property name=“username” value=“root”/>
11             <property name=“password” value=“root”/>
12         </dataSource>
13     </environment>
14 </enviroments>
15 ...
16 </configuration>

step3:讀取mybatis的配置檔案

1.幾個問題

Dao層的真實需求?

物件能與資料庫互動;能執行sql語句。

mybatis如何像dao層提供需求的?

通過SqlSession。

SqlSession的作用?

1 向SQL語句傳入引數
2 執行SQL語句
3 獲取執行SQL語句的結果
4 事務的控制

如何獲得SqlSession?

1 通過配置檔案獲取資料庫連線相關資訊
2 通過配置資訊構建SqlSessionFactory
3 通過SqlSessionFactory開啟資料庫會話(SqlSession就是一次與資料庫互動的會話)

2.db層(真正與資料庫互動的層)

 1 package com.imooc.db;
 2 
 3 /**
 4 *訪問資料庫類
 5 */
 6 public class DBAcess{
 7     public SqlSession getSqlSession() throws IOException{
 8         //通過配置檔案獲取資料庫連線資訊
 9         Resources.getResourceAsReader(“com/imooc/config/Configuration.xml”);//src是根路徑
10         //通過配置資訊構建SqlSessionFactory
11         SqlSessionFactoryBuilder sqlSessionFactoryBuilder = SqlSessionFactoryBuilder().build(reader);
13         //通過SqlSessionFactory開啟一個數據庫會話
14         SqlSession sqlSession = SqlSessionFactory.openSession();
15         return sqlSession;
16     }
17 }

3.增加mybatis的對映檔案

(1)在mybatis的主配置檔案里加載對映檔案Message.xml

1 <configuration>
2 ...
3 <mappers>
4     <!—-同樣從src下開始算起—->
5     <mapper resource=“com/imooc/config/sqlxml/Message.xml”/>
6 </mappers>
7 </configuration>  

(2)Message.xml

名稱空間:必須有,否則讀取配置檔案會報錯。

<select/update/delete id=" "> 中id的值在同一個namespace下同一個標籤下必須唯一。

<resultMap type="" id=""> 中:

type的值為對應的JavaBean,必須填寫全路徑或者定義的別名。id的值為<select/update/delete resultMap="">中resultMap的值,表明是與哪個sql語句相對應的resultMap。

<resultMap>的子標籤中:

<id column"">中填寫的是主鍵的欄位名。<result column="">填寫的是普通的列名。property中填寫的是JavaBean中屬性名。

(3)mybatis的OGNL

上面的<if test=""> </if>等是OGNL表示式。不是mybatis專有的。但是在mybatis裡有特性?(這句話不確定)

(ps:前面jsp檔案中的<c:if>是EL表示式。)

step4:修改dao層程式碼

 1 public class MessageDao{
 2     public List<Messag> queryMessageList(String command,String description){
 3     List<Message> messageList = new ArrayList<Message>();
 4     DBAccess dbAccess = new DBAccess();
 5         SqlSession sqlSession = null;
 6     try{
 7         sqlSession = dbAccess.getSqlSession();
 8         Message message = new Message();
 9         message.setCommand(command);
10         message.setDescription(description);
11         messageList = sqlSession.selectList(“Message.queryMessageList”,message); //Message.xml中的sql語句的namespase.id
12     }catch(IOException e){
13         e.printStackTrace();
14     }finally{
15         if(sqlSession != null){
16             sqlSession.close();
17         }
18     }  
19 return messageList;
19 }

step5: 執行測試,ok。