springboot整合Redis


一、新建項目,並添加所須要的jar包:javascript

分析:html

(1)在springboot中已經繼承了Redis,就是說一旦咱們啓動項目,它是能夠根據properties配置文件中的配置信息自動建立Jedis對象的java

(2)咱們想要的是本身定義配置信息的名稱,再根據本身定義的配置信息配置一個有關配置信息的類,最後根據這個類來建立一個咱們想要的Jedis對象。node

(3)springboot項目在加載的時候,因爲springboot沒法從配置文件中獲取想要的信息,因此不會自動建立屬於springboot的Jedis對象,而是根據咱們自定義mysql

的配置信息進行建立一個Jedis對象jquery

(4)在使用Jedis對象的時候,咱們給咱們的Jedis對象加上了@Bean註解,在要使用Jedis的類中使用@Autowired註解,因此spring中的BeanFactory工廠自動建立對象,web

,且是單例的;此處直接在@Autowire的註解下注入的是(3)中的對象,也就是根據咱們自定義信息建立的對象ajax

springboot-parent
spring-boot-web-start
mysql驅動包
druid(德魯伊)鏈接池
springboot和mybatis的整合包
thymeleaf模板jar包
thymeleaf忽略語法的jar包

springboot和redis的整合包
jedis的包:
jedis就是經過Java實現對redis集羣的增刪改查,就是操做redis數據庫
redis最終只支持5種數據格式:
String類型是最經常使用的
若是須要把User對象存入到redis中===>須要把User對象轉換爲json字符串===>再把字符串存入到redis中
json的jar包
configuration-processer包(爲了使用其中的@ConfigurationProperties()註解,在下文中的RedisProperties類中所使用)


 1 <!-- springboot的jar -->
 2 <parent>
 3     <groupId>org.springframework.boot</groupId>
 4     <artifactId>spring-boot-starter-parent</artifactId>
 5     <version>1.5.10.RELEASE</version>
 6 </parent>
 7 
 8 <dependencies>
 9     <!--
10         springboot-starter-web 11     -->
12     <dependency>
13         <groupId>org.springframework.boot</groupId>
14         <artifactId>spring-boot-starter-web</artifactId>
15     </dependency>
16     <!--
17         springboot-mybatis整合包 18     -->
19     <dependency>
20         <groupId>org.mybatis.spring.boot</groupId>
21         <artifactId>mybatis-spring-boot-starter</artifactId>
22         <version>1.3.0</version>
23     </dependency>
24     <!--
25  mysql的驅動包 26     -->
27     <dependency>
28         <groupId>mysql</groupId>
29         <artifactId>mysql-connector-java</artifactId>
30         <version>5.1.38</version>
31     </dependency>
32     <!--
33  druid鏈接池 34     -->
35     <dependency>
36         <groupId>com.alibaba</groupId>
37         <artifactId>druid</artifactId>
38         <version>1.1.10</version>
39     </dependency>
40     <!--
41  html的thymeleaf模板 42     -->
43     <dependency>
44         <groupId>org.springframework.boot</groupId>
45         <artifactId>spring-boot-starter-thymeleaf</artifactId>
46     </dependency>
47     <!--
48  redis的jar包以及jedis的jar包 49     -->
50     <dependency>
51         <groupId>redis.clients</groupId>
52         <artifactId>jedis</artifactId>
53         <version>2.9.0</version>
54     </dependency>
55     <!--
56  redis和springboot的整合包 57     -->
58     <dependency>
59         <groupId>org.springframework.data</groupId>
60         <artifactId>spring-data-redis</artifactId>
61     </dependency>
62     <!--
63  fastjson包 64     -->
65     <dependency>
66         <groupId>com.fasterxml.jackson.core</groupId>
67         <artifactId>jackson-databind</artifactId>
68         <version>2.8.1</version>
69     </dependency>
70     <!--
71  添加springboot的進程jar包 72  裏面包含了properties文件的讀取(其實就是包含了@ConfigurationProperties()註解) 73     -->
74     <dependency>
75         <groupId>org.springframework.boot</groupId>
76         <artifactId>spring-boot-configuration-processor</artifactId>
77         <optional>true</optional>
78     </dependency>
79 
80     <dependency>
81         <groupId>net.sourceforge.nekohtml</groupId>
82         <artifactId>nekohtml</artifactId>
83         <version>1.9.21</version>
84     </dependency>
85 </dependencies>

 

二、在springboot框架中,已經整合了Redis,能夠直接使用。
  此處根據springboot整合Redis的源碼來實現本身的Redis,緣由:springboot自帶的Redis已經很是完善,一旦出錯,很難找到錯誤的地方
  例如:當服務器的IP變更,端口號的問題等,能夠經過在本身的配置類中打斷點等方法判斷錯誤的地方

三、在config中配置application.properties配置信息:
 1 server.port=8081
 2 server.context-path=/
 3 
 4 spring.datasource.driver-class-name=com.mysql.jdbc.Driver  5 spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?userSSL=false
 6 spring.datasource.username=root  7 spring.datasource.password=123456
 8 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource  9 
10 mybatis.type-aliases-package=com.aaa.liu.redis.model 11 mybatis.mapper-locations=classpath:mapper/*Mapper.xml 12 
13 #開始自定義配置 14 # 配置redis集羣的端口號和IP 15 spring.redis.nodes=192.168.134.130:6380,192.168.134.130:6381,192.168.134.130:6382,192.168.134.130:6383,192.168.134.130:6384,192.168.134.130:6385 16 # 配置了redistribution的最大鏈接數 17 spring.redis.maxAttempts=1000 18 # 配置了redis最大超時時間 19 spring.redis.commandTimeout=500000 20 # 配置了redis的失效時間 21 spring.redis.expire=1000 22 
23 # 定義圖書的key值 24 book_key=bookKey1 25 
26 # 配置thymeleaf模板(不配置也能夠,直接使用) 27 # 配置thymeleaf緩存:默認值true,須要手動修改成false 28 spring.thymeleaf.cache=false 29 # 配置不嚴謹的html 30 spring.thymeleaf.mode=LEGACYHTML5

 


四、在Java中新建一個config包,在包中新建RedisPro類,將剛剛application.properties的配置信息引入此類中:
 1 package com.aaa.liu.redis.config;  2 
 3 import org.springframework.boot.context.properties.ConfigurationProperties;  4 import org.springframework.stereotype.Component;  5 
 6 /**
 7  * @Author 劉其佳  8  * @DateTime 2019/8/28 19:49  9  * @Project_Name SpringBootRedis 10  * 11  * 一、@Component:把RedisProperties做爲spring的一個組件 12  * 做用是 把Redis所須要配置和鏈接信息封裝進RedisProperties類中 13  * 該組件可拆分 14  * 配置該組件類的做用是從application.properties文件中讀取自定義的信息 15  * 二、@ConfigurationPrperties:做用是把application.properties中的屬性讀進RedisProperties類中 16  * 當使用該註解的時候必需要使用spring-boot-configuration-processor的jar包 17  * prefx="spring.redis";做用是選中在application.properties文件中的 屬性名 進行對用(必須一致) 18  * 三、原本按理說在此類中定義屬性事後,只有get方法,不該該有set方法,由於不能別其餘類修改 19  * 但如果真的不放入set方法的話,在使用此類時,沒法傳遞進來參數(屬性是私有的) 20  * !!!因此最終仍是要有set方法,只要注意其餘的類在調用RedisProperties類中的屬性的時候, 21  * 必定不能修改!!! 22  * 23  */
24 
25 @Component 26 /**
27  * 全部以spring.redis開頭的配置信息 28  */
29 @ConfigurationProperties(prefix = "spring.redis") 30 public class RedisProperties { 31 
32     /**
33  * 下列屬性對應application.properties文件中的自定義的配置: 34  * redis集羣的節點 35  * 最大鏈接數 36  * 最大超時時間 37  * 失效時間 38      */
39     private String nodes; 40     private String maxAttempts; 41     private String commandTimeout; 42     private String expire; 43 
44     public String getNodes() { 45         return nodes; 46  } 47 
48     public void setNodes(String nodes) { 49         this.nodes = nodes; 50  } 51 
52     public String getMaxAttempts() { 53         return maxAttempts; 54  } 55 
56     public void setMaxAttempts(String maxAttempts) { 57         this.maxAttempts = maxAttempts; 58  } 59 
60     public String getCommandTimeout() { 61         return commandTimeout; 62  } 63 
64     public void setCommandTimeout(String commandTimeout) { 65         this.commandTimeout = commandTimeout; 66  } 67 
68     public String getExpire() { 69         return expire; 70  } 71 
72     public void setExpire(String expire) { 73         this.expire = expire; 74  } 75 }

 


五、仍然在config包中新建類:RedisConfiguration,將RedisProperties類注入進來:
 1 package com.aaa.liu.redis.config;  2 
 3 import org.springframework.beans.factory.annotation.Autowired;  4 import org.springframework.boot.autoconfigure.SpringBootApplication;  5 import org.springframework.boot.context.properties.EnableConfigurationProperties;  6 import org.springframework.context.annotation.Bean;  7 import org.springframework.context.annotation.Configuration;  8 import redis.clients.jedis.HostAndPort;  9 import redis.clients.jedis.JedisCluster; 10 
11 import java.util.HashSet; 12 import java.util.Set; 13 
14 /**
15  * @Author 劉其佳 16  * @DateTime 2019/8/28 20:34 17  * @Project_Name SpringBootRedis 18  */
19 
20 /**
21  * 此處加上註解@Configuration或者@SpringBootApplication 22  * 23  * 由於在SpringBootApplication是一個組合註解 24  * 進入其中能夠看到@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan 25  * 再次進入@SpringBootConfiguration能夠看到@Configuration 26  * 所以SpringBootConfiguration是EnableAutoConfiguration、ComponentScan和Configuration的組合註解 27  * 28  * 在較低版本的SpringBoot中: 29  * @Configuration是啓用基於Java的配置 30  * @ComponentScan是啓用組件掃描。 31  * @EnableAutoConfiguration是啓用SpringBoot的自動配置功能 32  * 引用自:https://blog.csdn.net/qq_37939251/article/details/83058065
33  */
34 
35 /**
36  * 經過SpringBootApplication/Configuration註解將RedisConfiguration類標識爲springboot的配置類 37  * 38  * 使用Jedis的jar包操做Redis集羣數據庫 39  * 一、Redis:標識了Redis是單節點模式(只有一臺Redis) 40  * 源碼中:protected static class RedisConfiguration {} 41  * 二、RedisCluster:標識了Redis的Redis集羣模式 42  * 源碼中:protected final RedisClusterConfiguration getClusterConfiguration() {} 43  * 本次只配置集羣版的Redis 44  * 45  * @Bean: 至關於applicationContext.xml中的<bean id=""> class="JedisCluster.class"</bean> 46  * 47  * @EnableConfirgurationProperties({RedisProperties.class})是源碼中使用的註解 48  * 在本類中咱們使用@Autowired來代替掉 49  */
50 @SpringBootApplication 51 public class RedisConfiguration { 52  @Autowired 53     private RedisProperties redisProperties; 54 
55  @Bean 56     public JedisCluster getJedisCluster(){ 57         //一、獲取到application.properties文件中的Redis集羣的節點信息
58         String nodes=redisProperties.getNodes(); 59         //二、使用split來將多個node進行拆分
60         String[] nodeArray = nodes.split(","); 61         //三、建立一個set集合,以HostAndPort對象做爲泛型
62         Set<HostAndPort> hostAndPortSet=new HashSet<HostAndPort>(); 63         //四、遍歷剛剛獲得的節點數組
64         for (String node : nodeArray) { 65             //五、繼續使用split將node拆分紅IP和端口號(host、port)
66             String[] hostAndPortArray = node.split(":"); 67             //六、建立HostAndPort對象,並將獲得的IP和端口號做爲構造方法的參數傳入
68             HostAndPort hostAndPort=new HostAndPort(hostAndPortArray[0],Integer.parseInt(hostAndPortArray[1])); 69             //七、把每個HostAndPort對象裝進Set集合中
70  hostAndPortSet.add(hostAndPort); 71  } 72         //八、返回一個JedisCluster對象
73         return new JedisCluster(hostAndPortSet,Integer.parseInt(redisProperties.getCommandTimeout()),Integer.parseInt(redisProperties.getMaxAttempts())); 74  } 75 }

 


六、在Service層中新建RedisService
 1 package com.aaa.liu.redis.service;  2 
 3 import org.springframework.beans.factory.annotation.Autowired;  4 import org.springframework.stereotype.Service;  5 import redis.clients.jedis.JedisCluster;  6 
 7 /**
 8  * @Author 劉其佳  9  * @DateTime 2019/8/28 21:39 10  * @Project_Name SpringBootRedis 11  * 在之前的UserService中注入UserMapper,對數據庫進行操做 12  * 如今的RedisService中注入JedisCluster,對Redis數據庫進行操做 13  */
14 @Service 15 public class RedisService { 16 
17  @Autowired 18     private JedisCluster jedisCluster; 19 
20     /**
21  * 在Redis數據庫中的增刪查(沒有修改)分別爲: 22  * set del get 23  * 在下面分別定義 24      */
25 
26     /**
27  * @author 劉其佳 28  * @description 29  * 向Redis數據庫中存入String類型的數據 30  * set的時候返回值是"ok" 31  * @param * param *:key 32  * @date 2019/8/28 33  * @return java.lang.String 34  * @throws
35     */
36     public String set(String key,String value){ 37         return jedisCluster.set(key,value); 38  } 39 
40     /**
41  * @author 劉其佳 42  * @description 43  * 從Redis數據庫中經過key取出數據 44  * @param * param *:key 45  * @date 2019/8/28 46  * @return java.lang.String 47  * @throws
48     */
49     public String get(String key){ 50         return jedisCluster.get(key); 51  } 52 
53     /**
54  * @author 劉其佳 55  * @description 56  * 一、在此處的參數key是一個可變參 57  * 二、在Redis中刪除的返回值是Integer類型 58  * 在Java中被轉成了Long類型 59  * @param * param *:key 60  * @date 2019/8/28 61  * @return java.lang.Long 62  * @throws
63     */
64     public Long del(String key){ 65         return jedisCluster.del(key); 66  } 67 
68     /**
69  * @author 劉其佳 70  * @description 71  * 經過key設置失效時間(單位是秒) 72  * @param * param *:key 73  * param *:seconds 74  * @date 2019/8/28 75  * @return java.lang.Long 76  * @throws
77     */
78     public Long expire(String key,Integer seconds){ 79         return jedisCluster.expire(key,seconds); 80  } 81 }

 

查詢圖書信息的service:
 1 /**
 2  * @author 劉其佳  3  * @description  4  * 注意:service層不容許注入service  5  * 由於在applicationContext.xml中配置事務後,事務都是在service中的  6  * 當service注入另外一個事務時,會形成事務串線(若是線程是並行的沒有問題)  7  * applicationContext.xml配置文件中進行註解掃描:  8  * controller:必需要在springmvc中進行掃描  9  * service:必需要在spring中進行掃描 10  * 11  * @param * param *:null 12  * @date 2019/8/28 13  * @return
14  * @throws
15     */
16     public Map<String ,Object> selectAllBooks(RedisService redisService){ 17         /**
18  * 一、從Redis中查詢全部圖書信息 19  * 二、判斷從Redis中是否查詢出數據 20  * 三、沒有查詢到的話再從數據庫中查詢數據 21  * 四、判斷是否從數據庫中查詢到數據 22  * 五、若查詢到數據,則返回結果,而且將數據放入Redis中 23  * 六、利用try...catch判斷是否存入Redis中 24  * 七、若沒有存入Redis中,要作出處理,此處爲再次往Redis中存放一次 25          */
26         Map<String,Object> resultMap=new HashMap<String, Object>(); 27         //一、
28         String bookString=redisService.get(bookKey); 29         //二、
30         if(null==bookString||"".equals(bookString)){ 31             //三、
32             List<Book> bookList = bookMapper.selectAll(); 33             //四、
34             if(bookList.size()>0){ 35                 //六、
36                 try { 37                     //五、
38  redisService.set(bookKey, JSONUtil.toJsonString(bookList)); 39                     //將從數據庫中查詢到的數據存入resultMap中
40  resultMap.put(StatusEnum.SUCCESS.getCodeName(), StatusEnum.SUCCESS.getCode()); 41  resultMap.put(StatusEnum.SUCCESS.getResultName(),bookList); 42                 } catch (Exception e) { 43                     //七、
44  redisService.set(bookKey, JSONUtil.toJsonString(bookList)); 45                     //若是仍是沒有將數據放入Redis中,此時咱們將resultMap裏面的code換成404,可是用戶仍是可以查詢到數據
46  resultMap.put(StatusEnum.FAILED.getCodeName(),StatusEnum.FAILED.getCode()); 47  resultMap.put(StatusEnum.FAILED.getResultName(),bookList); 48  e.printStackTrace(); 49                     return resultMap; 50  } 51             }else { 52                 //說明數據庫中沒有數據,放入500
53  resultMap.put(StatusEnum.ERROR.getCodeName(),StatusEnum.ERROR.getCode()); 54  } 55         }else { 56             //!!!可能會存在Redis中的數據與數據庫中的數據不一致的狀況 57             //因此此處從Redis中獲取到數據後與從數據庫中查詢到的數據作出一個判斷(長度是否一致)
58             List<Book> bookList = JSONUtil.toList(bookString, Book.class); 59             List<Book> bookList1 = bookMapper.selectAll(); 60             if(bookList.size()==bookList1.size()){ 61                 //將查詢從Redis中查詢到的數據存入到resultMap 62                 //由於是從Redis中查詢到的數據,此處給轉回正常狀態下的List集合類型的數據, 63                 //正好從數據庫中查詢到的數據也是List,保持一致
64  resultMap.put(StatusEnum.SUCCESS.getCodeName(), StatusEnum.SUCCESS.getCode()); 65                 resultMap.put(StatusEnum.SUCCESS.getResultName(),JSONUtil.toList(bookString,Book.class)); 66         }else { 67                 //發現數據不一致時,丟棄Redis中的數據,並將數據庫中的數據存入Redis中
68  redisService.set(bookKey,JSONUtil.toJsonString(bookList)); 69  resultMap.put(StatusEnum.SUCCESS.getCodeName(), StatusEnum.SUCCESS.getCode()); 70  resultMap.put(StatusEnum.SUCCESS.getResultName(),bookList1); 71  } 72 
73  } 74         return resultMap; 75     }

 

七、控制層的BookController:
 1 /**
 2  * @Author 劉其佳  3  * @DateTime 2019/8/28 22:25  4  * @Project_Name SpringBootRedis  5  */
 6 @RestController  7 public class BookController {  8 
 9  @Autowired 10     private BookService bookService; 11  @Autowired 12     private RedisService redisService; 13 
14     @RequestMapping("/") 15     public List<Book> selectAllBooks(){ 16         Map<String, Object> resultMap = bookService.selectAllBooks(redisService); 17         List<Book> bookList=null; 18         //若是查詢到的resultMap中的code值爲200,說明直接從Redis中查到數據了
19         if(StatusEnum.SUCCESS.getCode().equals((resultMap.get(StatusEnum.SUCCESS.getCodeName())))){ 20             bookList= (List<Book>) resultMap.get(StatusEnum.SUCCESS.getResultName()); 21             System.out.println("everything is ok!"); 22         }else { 23             //若是code值不爲200,則有兩種狀況:404即Redis錯誤; 500即mysql錯誤
24             if(StatusEnum.ERROR.getCode().equals((resultMap.get(StatusEnum.SUCCESS.getCodeName())))){ 25                 //一、result到最後也沒存進去值,數據庫都出現了問題
26                 System.out.println("數據庫出現了問題"); 27             }else{ 28                 //二、result有值,Redis出現了問題,但從數據庫查詢了數據
29                 bookList= (List<Book>) resultMap.get(StatusEnum.SUCCESS.getResultName()); 30                 System.out.println("redis出現了問題"); 31  } 32  } 33         return bookList; 34     }

 

在本次項目中爲了不魔法值問題,使用了枚舉:
新建一個包statuscode ,在其中新建類:StatusEnum
 1 package com.aaa.liu.redis.statuscode;  2 
 3 /**
 4  * @Author 劉其佳  5  * @DateTime 2019/8/29 20:08  6  * @Project_Name SpringBootRedis  7  */
 8 public enum StatusEnum {  9     SUCCESS(200,"操做失敗","code","result"), 10     FAILED(404,"操做成功","code","result"), 11     ERROR(500,"操做失敗","code","result"); 12 
13     private Integer code; 14     private String msg; 15     private String codeName; 16     private String resultName; 17 
18     /**
19  * 給枚舉賦值 20  * @param code 21  * @param msg 22  * @param codeName 23      */
24  StatusEnum(Integer code, String msg, String codeName,String resultName) { 25         this.code = code; 26         this.msg = msg; 27         this.codeName = codeName; 28         this.resultName=resultName; 29  } 30 
31     public Integer getCode() { 32         return code; 33  } 34 
35     public void setCode(Integer code) { 36         this.code = code; 37  } 38 
39     public String getMsg() { 40         return msg; 41  } 42 
43     public void setMsg(String msg) { 44         this.msg = msg; 45  } 46 
47     public String getCodeName() { 48         return codeName; 49  } 50 
51     public void setCodeName(String codeName) { 52         this.codeName = codeName; 53  } 54 
55     public String getResultName() { 56         return resultName; 57  } 58 
59     public void setResultName(String resultName) { 60         this.resultName = resultName; 61  } 62 }

 


mapper中的BookMapper查詢全部圖書:
 1 /**
 2  * @Author 劉其佳  3  * @DateTime 2019/8/27 20:19  4  * @Project_Name springbootshiro  5  */
 6 @Mapper  7 public interface BookMapper {  8     //查詢全部書籍
 9     @Select("select id,book_name bookName,book_price bookPrice from book ") 10     List<Book> selectAll(); 11 }

 

其中的注意事項已在代碼中寫出!



此處插入一個關於ajax的用法:
 1 <!DOCTYPE html>
 2 <html xmlns="http://www.w3.org/1999/xhtml"
 3       xmlns:th="http://www.thymeleaf.org"
 4       xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
 5 <head>
 6     <meta charset="UTF-8">
 7     <title>Index</title>
 8     <script type="text/javascript" src="/jquery-3.2.1.min.js"></script>
 9 </head>
10 
11 <script>
12     /**
13  * 1.頁面自動加載完成後,函數自動執行,查詢出數據並拼接處table表單,將數據放入其中 14  * */
15  $(document).ready( selectBookTest()); 16 
17  function selectBookTest(){ 18  $.ajax({ 19             type:"POST", 20             url:"selectBooks", 21             dataType:"JSON", 22  success:function (msg) { 23                 var tr=""; 24                 for(var i=0;i<msg.length;i++){ 25                     tr+="<tr><td>"+msg[i].id+"</td>"; 26                     tr+="<td>"+msg[i].bookName+"</td>"; 27                     tr+="<td>"+msg[i].bookPrice+"</td></tr>"; 28                     //不能直接使用下面的方式,不然會只有一行數據;要使用+= 29                     // tr="<tr><td>"+msg[i].id+"</td><td>"+msg[i].bookName+"</td><td>"+msg[i].bookPrice+"</td></tr>"
30  } 31                 tr+="<tr><td onclick='testBookAdd()'>添加</td></tr>"; 32                 $("#test_Book").append("<table border='1px solid black'>" +
33                     "<thead>" +
34                     "<tr >" +
35                     "<th>圖書編號</th>" +
36                     "<th>圖書名稱</th>" +
37                     "<th>圖書價格</th>" +
38                     "</tr>" +
39                     tr +
40                     "</thead>" +
41                     "</table>") 42  } 43 
44  }) 45  } 46 
47     /**
48  * 2.點擊添加按鈕,將查詢所得的數據清空,並拼接出新的form表單用以輸入要添加的數據 49      */
50  function testBookAdd() { 51         $("#test_Book").empty(); 52         $("#test_Book").append("<form id='formBook'><table border='1px solid red'>" +
53             "<tr><td>圖書名稱:</td><td><input type='text' name='bookName'/></td></tr>" +
54             "<tr><td>圖書價格:</td><td><input type='text' name='bookPrice'/></td></tr>"+
55             "<tr><td><input type='button' value='submit' onclick='bookAdd()'/></td></tr>"+
56             "</table></form>") 57  } 58 
59     /**
60  * 3.輸入完數據,使用ajax調用添加方法添加 61      */
62  function bookAdd() { 63  $.ajax({ 64             type:"POST", 65             url:"testAddBook", 66             data:$("#formBook").serialize(), 67             dataType:"json", 68  success:function (msg) { 69                 if(null==msg){ 70                     alert("添加失敗") 71                 }else{ 72                     $("#test_Book").empty(); 73  selectBookTest(); 74  } 75  } 76  }) 77  } 78 
79 </script>
80 <body>
81 
82 <div id="test_Book"></div>
83 </body>
84 
85 
86 </html>
相關文章
相關標籤/搜索