專案開發常用技術總結
最近整理了一些開發中常用的技術,分享一下個人的心得,如有不對之處,歡迎指出。
目錄
1.shiro許可權控制在專案中的使用
1.jsp頁面匯入shiro標籤庫
<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
標籤庫定義在shiro-web.jar包下的META-INF/shiro.tld中定義。
2.常用shiro標籤
hasRole標籤
<shiro:hasRole name="admin">
<span> 擁有角色admin
</shiro:hasRole>
如果當前Subject有角色將顯示span內容。
hasAnyRoles標籤
<shiro:hasAnyRoles name="admin,user">
<span>擁有角色admin</span>
</shiro:hasAnyRoles>
如果當前Subject有任意一個角色(或的關係)將顯示span內容。
lacksRole標籤
<shiro:lacksRole name="abc">
<span>沒有
</shiro:lacksRole>
如果當前Subject沒有角色abc將顯示span內容。
hasPermission標籤
<shiro:hasPermission name="user:create">
<span>擁有許可權user:create</span>
</shiro:hasPermission>
如果當前Subject有許可權將顯示span內容。
lacksPermission標籤
<shiro:lacksPermission name=
<span>沒有有許可權user:create</span>
</shiro:lacksPermission>
如果當前Subject沒有許可權將顯示span內容。
在java後臺程式碼中如何通過shrio根據使用者的角色不同對資料進行過濾,需要結合shiro的subject物件和實體類中sqlMap進行sql語句的拼接來達到資料的過濾
Java程式碼
xml中sql拼接
注意:在原來的jeesite框架中每個實體類都繼承了BaseEntity基類,而基類中已經加入了Map型別的sqlMap,所以每個繼承了BaseEntity類都可以直接呼叫 getSqlMap方法若沒有需自己重寫
@JsonIgnore
@XmlTransient
public Map<String, String> getSqlMap() {
if (sqlMap == null){
sqlMap = Maps.newHashMap();
}
return sqlMap;
}
public void setSqlMap(Map<String, String> sqlMap) {
this.sqlMap = sqlMap;
}
2.java反射技術比較實體類欄位的不同
Java程式碼:
1.存放不同資訊的類
public class ChangeInfo extends DataEntity<ChangeInfo> {
private static final long serialVersionUID = 1L;
private String title; // 改變標題 (變數名)
private String name; // 變更項的名稱 (中文名)
private String type; // 變更顯示型別(1:顯示content內容 2: 顯示前後(oldInfo,newInfo)變更資訊)
private String content; // 提示內容
private String oldInfo; // 之前內容
private String newInfo; // 之後內容
}
2.設定需要比較的物件的欄位名稱
public List<ChangeInfo>compareDetails(Object obj){
//存放新舊物件改變的內容
List<ChangeInfo> list = new ArrayList<ChangeInfo>();
//新的物件
Object newVersion = obj;
//舊的物件
Object oldVersion = XXXService.get(newVersion.getLastVersionId());
//需要比較的欄位
String[]opDiffNameArray={"XX編碼","XX名稱","XX要求","XX目的","XX範圍","XX使用前","XX使用過程中","XX使用過程後","XX注意事項"};
//對應的類中的成員變數
String[]opDiffArray={"code","name","requirement","purpose","range","beforeUse","inUse","afterUse","notice"};
contrastObj(newVersion, oldVersion, opDiffArray, opDiffNameArray, list);
return list;
}
3.利用反射技術比較實體類的欄位值
public void contrastObj(Object pojo1, Object pojo2, String[] diffMemberArray, String[] diffMemberName, List<ChangeInfo> diffList) {
Map<String, Object> diffMap = new HashMap<String, Object>();
//map儲存中英文對應
for (int i = 0; i < diffMemberArray.length; i++) {
diffMap.put(diffMemberArray[i], diffMemberName[i]);
}
//英文List
List<String> diffMember = Arrays.asList(diffMemberArray);
try {
Class clazz = pojo1.getClass();
//獲取obj1的所有欄位
Field[] fields = pojo1.getClass().getDeclaredFields();
//遍歷obj1所有欄位
for (Field field : fields) {
//如果該欄位不再Map中遍歷下一個欄位
if (!diffMember.contains(field.getName())) {
continue;
}
//利用反射獲取對應欄位的get,set方法
PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz); //獲取get方法
Method getMethod = pd.getReadMethod();
Object o1 = null;
Object o2 = null;
if (pojo1 != null) {
//呼叫obj1的對應欄位的get方法
o1 = getMethod.invoke(pojo1);
}
if (pojo2 != null) {
//呼叫obj2的對應欄位的get方法
o2 = getMethod.invoke(pojo2);
}
String str1 = "";
String str2 = "";
//如果物件是日期型別格式化
if (o1 instanceof Date) {
str1 = new SimpleDateFormat("yyyy-MM-dd").format(o1);
str2 = new SimpleDateFormat("yyyy-MM-dd").format(o2);
} else if (o1 instanceof String) {
str1 = (String) o1;
str2 = (String) o2;
} else {
continue;
}
//判斷返回的物件不相等
if ((str1 != null && !str1.equals(str2)) || (str2 != null && !str2.equals(str1))) {
ChangeInfo change = new ChangeInfo();
//欄位英文名稱
change.setTitle(field.getName());
//中文名稱
change.setName((String) diffMap.get(field.getName()));
//舊資訊
change.setOldInfo(str2);
//新資訊
change.setNewInfo(str1);
diffList.add(change);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
3.jeesite框架Apache Commons Email的使用
1.匯入相關依賴
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-email</artifactId>
<version>1.2</version>
</dependency>
2.建立.ftl檔案
<html>
<head>
<meta http-equiv="content-type" content="text/html;chartset=utf-8" ;>
</head>
<body>
<h1>${subject}</h1>
<p>${content}</p>
</body>
</html>
3.註冊個人郵箱開啟pop3/smpt服務(以新浪郵箱舉列)
4.修改sendMailUtils類
① 配置郵箱地址
private static MailLogDao mailLogDao=SpringContextHolder.getBean(MailLogDao.class);
// private static final String smtphost = "192.168.1.70";
private static final String from = "[email protected]";
private static final String fromName = "XXX";
private static final String charSet = "utf-8";
private static final String username = "[email protected]";
private static final String password = "xxxx";
② 配置smtp地址
static {
// 126
hostMap.put("smtp.126", "smtp.126.com");
// qq
hostMap.put("smtp.qq", "smtp.qq.com");
// 163
hostMap.put("smtp.163", "smtp.163.com");
// sina
hostMap.put("smtp.sina", "smtp.sina.com.cn");
}
③ 根據郵箱號獲取smtp地址
public static String getHost(String email) throws Exception {
Pattern pattern = Pattern.compile("\\[email protected](\\w+)(\\.\\w+){1,2}");
Matcher matcher = pattern.matcher(email);
String key = "unSupportEmail";
if (matcher.find()) {
key = "smtp." + matcher.group(1);
}
if (hostMap.containsKey(key)) {
return hostMap.get(key);
} else {
throw new Exception("unSupportEmail");
}
}
④ 根據郵箱號獲取smtp埠號
public static int getSmtpPort(String email) throws Exception {
Pattern pattern = Pattern.compile("\\[email protected](\\w+)(\\.\\w+){1,2}");
Matcher matcher = pattern.matcher(email);
String key = "unSupportEmail";
if (matcher.find()) {
key = "smtp.port." + matcher.group(1);
}
if (hostMap.containsKey(key)) {
return Integer.parseInt(hostMap.get(key));
} else {
return 25;
}
}
⑤ 填寫郵箱內容
public static void sendEmail(Tenant tenant)throws MessagingException {
String subject="註冊通知!";
String content="您好"+"</br>"+"歡迎註冊XX"+"</br>;
Map<String, Object> map = new HashMap<String, Object>();
map.put("subject", subject);
map.put("content", content);
String templatePath = "mailtemplate/test.ftl";
sendFtlMail(tenant.getEmail(), subject, templatePath, map);
}
⑥ 呼叫郵箱傳送方法
/**
* 傳送模板郵件
*
* @param toMailAddr 收信人地址
* @param subject email主題
* @param templatePath 模板地址
* @param map 模板map
*/
public static void sendFtlMail(String toMailAddr, String subject,
String templatePath, Map<String, Object> map) {
Template template = null;
Configuration freeMarkerConfig = null;
HtmlEmail hemail = new HtmlEmail();
try {
hemail.setHostName(getHost(from));
hemail.setSmtpPort(getSmtpPort(from));
hemail.setCharset(charSet);
hemail.addTo(toMailAddr);
hemail.setFrom(from, fromName);
hemail.setAuthentication(username, password);
hemail.setSubject(subject);
hemail.setSSL(Boolean.TRUE); // 設定是否使用SSL email.setSslSmtpPort("465")
freeMarkerConfig = new Configuration();
freeMarkerConfig.setDirectoryForTemplateLoading(new File(
getFilePath()));
// 獲取模板
template = freeMarkerConfig.getTemplate(getFileName(templatePath),
new Locale("Zh_cn"), "UTF-8");
// 模板內容轉換為string
String htmlText = FreeMarkerTemplateUtils
.processTemplateIntoString(template, map);
System.out.println(htmlText);
hemail.setMsg(htmlText);
hemail.send();
System.out.println("email send true!");
} catch (Exception e) {
e.printStackTrace();
System.out.println("email send error!");
}
}
4.jeesite框架excel表的匯入匯出
- 匯入pom.xml依賴
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>${poi.version}</version>
</dependency>
2.實體類新增ExcelFiled註解
注:只有新增@ExcelField註解才能在匯入匯出的時候將欄位對映
- 匯出Excel表資料
- 下載Excel模板
5 匯入excel表資料
5.json物件和字串的相互轉換
5.1 jsp頁面中json物件和字串的轉換
使用json中的parser方法轉換;
var str='{"name":"fendouer", "age":23}'; //這是一個json字串''
var ob=JSON.parse(str) ; //返回一個新物件
console.log(ob.name)
把json中的stringify物件轉換成字串
var obj={"student":[{"name":"cyl","age":"21"},{"name":"hyj","age":"23"}]}; //這是一個json物件
var str=obj.student[0].name;
var newstr=JSON.stringify(str); //返回一個新字串
console.log(newstr);
在Firefox,chrome,opera,safari,ie9,ie8等高階瀏覽器直接可以用JSON物件的stringify()和parse()方法。
JSON.stringify(obj) 將JSON物件轉為字串。
JSON.parse(string) 將字串轉為JSON物件格式。
擴充套件 :jquery外掛支援的轉換方式:
jQuery 3.0開始,$.parseJSON已經過時(不建議使用)。要將字串解析成JSON物件,請使用原生的JSON.parse方法來代替。
5.2 java程式碼中json物件和字串的轉換
/** * json字串轉化為物件 */
String jsonString ="{name:'Antony',age:'12',sex:'male',telephone:'88888'}";
Staff staff = JSON.parseObject(jsonString, Staff.class); System.out.println(staff.toString());
/** * 物件轉化為json字串 */
String jsonStr = JSON.toJSONString(staff);
System.out.println(jsonStr);
6.JackJson的objectMapper的json物件化
Java下常見的Json類庫有Gson、JSON-lib和Jackson等,Jackson相對來說比較高效,在專案中主要使用Jackson進行JSON和Java物件轉換,下面給出一些Jackson的JSON操作方法。
1、準備工作
Jackson有1.x系列和2.x系列,2.x系列有3個jar包需要下載:
jackson-core-2.2.3.jar(核心jar包)
jackson-annotations-2.2.3.jar(該包提供Json註解支援)
jackson-databind-2.2.3.jar
一個maven依賴就夠了
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>
JSON序列化和反序列化使用的User類
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2. java物件轉json字串
/**
* ObjectMapper是JSON操作的核心,Jackson的所有JSON操作都是在ObjectMapper中實現。
* ObjectMapper有多個JSON序列化的方法,可以把JSON字串儲存File、OutputStream等不同的介質中。
* writeValue(File arg0, Object arg1)把arg1轉成json序列,並儲存到arg0檔案中。
* writeValue(OutputStream arg0, Object arg1)把arg1轉成json序列,並儲存到arg0輸出流中。
* writeValueAsBytes(Object arg0)把arg0轉成json序列,並把結果輸出成位元組陣列。
* writeValueAsString(Object arg0)把arg0轉成json序列,並把結果輸出成字串。
*/
User user = new User();
user.setName("zhangsan");
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(user);
System.out.println(json);
//輸出結果:{"name":"zhangsan"}
3.JSON字串轉java物件
String json = "{\"name\":\"zhangsan\"}";
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(json, User.class);
4.json註解
Jackson提供了一系列註解,方便對JSON序列化和反序列化進行控制,下面介紹一些常用的註解。
@JsonIgnore 此註解用於屬性上,作用是進行JSON操作時忽略該屬性。
@JsonFormat 此註解用於屬性上,作用是把Date型別直接轉化為想要的格式,如@JsonFormat(pattern = "yyyy-MM-dd HH-mm-ss")。
@JsonProperty 此註解用於屬性上,作用是把該屬性的名稱序列化為另外一個名稱,如把trueName屬性序列化為name, @JsonProperty("name")。
7.Websocket的基本使用
1.pom.xml檔案新增依賴jar包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${spring.version}</version>
</dependency>
2.服務註冊
**
* 註解配置模式
* Created by 86557 on 2017/4/19.
*/
@Configuration
@EnableWebSocket
@EnableWebMvc
public class WebSocketConfig implements WebSocketConfigurer {
public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
// 用來註冊WebSocket Server實現類,第二個引數是訪問WebSocket的地址
webSocketHandlerRegistry.addHandler(new AnalysisWebSocketHandler(), "/myHandler").addInterceptors(new HandshakeInterceptor());
webSocketHandlerRegistry.addHandler(new AnalysisWebSocketHandler(), "/sockjs/myHandler").addInterceptors(new HandshakeInterceptor()).withSockJS();
}
}
注:前端會發起一個webSocket連線請求,而webSockeConfig會接收到這個請求,接收請求之後webSocketConfig類建立兩個類的物件一個是HandshakeInterceptor類,一個是AnalysisWebSocketHandler類,HandshakeInterceptor類用於webSocket建立連線之前的握手,
AnalysisWebSocketHandler類用於處理webSocket連線之後的業務邏輯處理。
3.握手
public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor {
private Logger logger = LoggerFactory.getLogger(getClass());
/**
*
* @param request
* @param response
* @param wsHandler
* @param attributes
* @return
* @throws Exception
*/
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse
response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws
Exception {
if (getSession(request) != null) {
ServletServerHttpRequest servletRequest =
(ServletServerHttpRequest) request;
HttpServletRequest httpServletRequest =
servletRequest.getServletRequest();
Subject subject = SecurityUtils.getSubject();
SystemAuthorizingRealm.Principal principal =
(SystemAuthorizingRealm.Principal) subject.getPrincipal();
if (principal == null) {
//沒有獲取登陸使用者資訊,握手失敗
return false;
}
attributes.put("userId", principal.getId());
}
return super.beforeHandshake(request, response, wsHandler,
attributes);
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse
response, WebSocketHandler wsHandler, Exception ex) {
super.afterHandshake(request, response, wsHandler, ex);
}
private HttpSession getSession(ServerHttpRequest request) {
if (request instanceof ServletServerHttpRequest) {
ServletServerHttpRequest serverRequest =
(ServletServerHttpRequest) request;
return serverRequest.getServletRequest().getSession(false);
}
return null;
}
}
注 WebSocket握手攔截器用來攔截和處理客戶端和伺服器端分別在握手前和握手後的事件,我們這裡新增這個攔截器是為了清晰的知道什麼時候以及是否握手成功。
4.webscoket處理類
@Service
public class AnalysisWebSocketHandler extends TextWebSocketHandler {
private static final Map<String, List<WebSocketSession>> users;
private static SystemService systemService = SpringContextHolder.getBean(SystemService.class);
private static NotifyDao notifyDao=SpringContextHolder.getBean(NotifyDao.class);
static {
users=new HashMap<>();
}
// 在afterConnectionEstablished連線建立成功之後,記錄使用者的連線標識,便於後面發信息,這裡我是記錄將id記錄在Map集合中。
@Override
public void afterConnectionEstablished(WebSocketSession session) throws
Exception {
super.afterConnectionEstablished(session);
String userId = MapUtils.getString(session.getAttributes(),
"userId");
//記錄連線的session
if(users.containsKey(userId)) {
users.get(userId).add(session);
}else{
List<WebSocketSession>socketSessionList=Lists.newArrayList();
socketSessionList.add(session);
users.put(userId, socketSessionList);
}
}
/**
* 前臺js呼叫ws.send(requestData)函式會觸發此函式,一般業務邏輯在此處理
* @param session
* @param message
* @throws Exception
*/
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage
message) throws Exception {
try {
session.sendMessage(new TextMessage( JSON.toJSONString(searchNotify(session))));
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void handleTransportError(WebSocketSession session, Throwable
exception) throws Exception {
super.handleTransportError(session, exception);
System.out.println("handleTransportError");
String userId = MapUtils.getString(session.getAttributes(),
"userId");
users.get(userId).remove(session);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus
status) throws Exception {
super.afterConnectionClosed(session, status);
System.out.println("afterConnectionClosed");
String userId = MapUtils.getString(session.getAttributes(),
"userId");
users.get(userId).remove(session);
}
}
注: 這個類處理來之瀏覽器(客戶端)的WebSocket請求。在這個例子中,我們建立一個叫AnalysisWebSocketHandler的類,並讓它繼承TextWebsocketHandler類。然後重寫父類方法handlerTextMessage(),每當客戶端傳送資訊過來,都會由這個函式接收並處理。這個函式會把服務端處理的資料返回給客戶端。
5.前端websocket客戶端配置
function connectWS() {
var url = 'ws://' + window.location.host + "${pageContext.request.contextPath}/myHandler";
if (!url) {
alert('Select whether to use W3C WebSocket or SockJS');
return;
}
if (url.indexOf("sockjs") != -1) {
ws = new SockJS(url);
} else {
if ('WebSocket' in window) {
ws = new WebSocket(url);//ws://localhost:8080/myHandler
} else {
ws = new SockJS(url);
}
}
ws.onopen = function () {
console.log("websocket已開啟");
sendMsg();
};
ws.onmessage = function (event) {
console.log("websocket 收到訊息:");
var responseData = $.parseJSON(event.data);
if (responseData.resultStatus == '1') {
if (responseData.count.length > 5) {
alert('未登入或登入超時。請重新登入,謝謝!');
top.location = "${ctx}";
} else if (responseData.count != '0') {
if ($("#notifyLi:hidden").length != 0) {
$("#notifyLi").show();
}
$("#unReadNotifys").html(responseData.count);
} else {
$("#notifyLi").hide();
}
} else if (responseData.resultStatus == '0') {
alert(responseData.message);
window.location.reload(true);
} else {
window.location.reload(true);
}
};
ws.onclose = function (event) {
console.log("websocket 關閉");
};
ws.onerror = function (event) {
console.log("websocket出錯");
};
}
6.webSocket的應用背景
決定手頭的工作是否需要使用WebSocket技術的方法很簡單:
- 你的應用提供多個使用者相互交流嗎?
- 你的應用是展示伺服器端經常變動的資料嗎?
如果你的回答是肯定的,那麼請考慮使用WebSocket。如果你仍然不確定,並想要更多的靈感,這有一些殺手鐗的案例。
①社交訂閱
對社交類的應用的一個裨益之處就是能夠即時的知道你的朋友正在做什麼。雖然聽起來有點可怕,但是我們都喜歡這樣做。你不會想要在數分鐘之後才能知道一個家庭成員在餡餅製作大賽獲勝或者一個朋友訂婚的訊息。你是線上的,所以你的訂閱的更新應該是實時的。
②多玩家遊戲
網路正在迅速轉變為遊戲平臺。在不使用外掛(我指的是Flash)的情況下,網路開發者現在可以在瀏覽器中實現和體驗高效能的遊戲。無論你是在處理DOM元素、CSS動畫,HTML5的canvas或者嘗試使用WebGL,玩家之間的互動效率是至關重要的。我不想在我扣動扳機之後,我的對手卻已經移動位置。
③協同編輯/程式設計
我們生活在分散式開發團隊的時代。平時使用一個文件的副本就滿足工作需求了,但是你最終需要有一個方式來合併所有的編輯副本。版本控制系統,比如Git能夠幫助處理某些檔案,但是當Git發現一個它不能解決的衝突時,你仍然需要去跟蹤人們的修改歷史。通過一個協同解決方案,比如WebSocket,我們能夠工作在同一個文件,從而省去所有的合併版本。這樣會很容易看出誰在編輯什麼或者你在和誰同時在修改文件的同一部分。
④點選流資料
分析使用者與你網站的互動是提升你的網站的關鍵。HTTP的開銷讓我們只能優先考慮和收集最重要的資料部分。然後,經過六個月的線下分析,我們意識到我們應該收集一個不同的判斷標準——一個看起來不是那麼重要但是現在卻影響了一個關鍵的決定。與HTTP請求的開銷方式相比,使用Websocket,你可以由客戶端傳送不受限制的資料。想要在除頁面載入之外跟蹤滑鼠的移動?只需要通過WebSocket連線傳送這些資料到伺服器,並存儲在你喜歡的NoSQL資料庫中就可以了(MongoDB是適合記錄這樣的事件的)。現在你可以通過回放使用者在頁面的動作來清楚的知道發生了什麼。
⑤股票基金報價
金融界瞬息萬變——幾乎是每毫秒都在變化。我們人類的大腦不能持續以那樣的速度處理那麼多的資料,所以我們寫了一些演算法來幫我們處理這些事情。雖然你不一定是在處理高頻的交易,但是,過時的資訊也只能導致損失。當你有一個顯示盤來跟蹤你感興趣的公司時,你肯定想要隨時知道他們的價值,而不是10秒前的資料。使用WebSocket可以流式更新這些資料變化而不需要等待。
⑥體育實況更新
現在我們開始討論一個讓人們激情澎湃的愚蠢的東西——體育。我不是運動愛好者,但是我知道運動迷們想要什麼。當愛國者在打比賽的時候,我的妹夫將會沉浸於這場比賽中而不能自拔。那是一種瘋狂痴迷的狀態,完全發自內心的。我雖然不理解這個,但是我敬佩他們與運動之間的這種強烈的聯絡,所以,最後我能做的就是給他的體驗中降低延遲。如果你在你的網站應用中包含了體育新聞,WebSocket能夠助力你的使用者獲得實時的更新。
⑦多媒體聊天
視訊會議並不能代替和真人相見,但當你不能在同一個屋子裡見到你談話的物件時,視訊會議是個不錯的選擇。儘管視訊會議私有化做的“不錯”,但其使用還是很繁瑣。我可是開放式網路的粉絲,所以用WebSockets getUserMedia API和HTML5音視訊元素明顯是個不錯的選擇。WebRTC的出現順理成章的成為我剛才概括的組合體,它看起來很有希望,但其缺乏目前瀏覽器的支援,所以就取消了它成為候選人的資格。
⑧基於位置的應用
越來越多的開發者借用移動裝置的GPS功能來實現他們基於位置的網路應用。如果你一直記錄使用者的位置(比如執行應用來記錄運動軌跡),你可以收集到更加細緻化的資料。如果你想實時的更新網路資料儀表盤(可以說是一個監視運動員的教練),HTTP協議顯得有些笨拙。借用WebSocket TCP連結可以讓資料飛起來。
⑨線上教育
上學花費越來越貴了,但網際網路變得更快和更便宜。線上教育是學習的不錯方式,尤其是你可以和老師以及其他同學一起交流。很自然,WebSockets是個不錯的選擇,可以多媒體聊天、文字聊天以及其它優勢如與別人合作一起在公共數字黑板上畫畫。
8.webService的基本使用
1.webService介紹
W3C組織對其的定義如下,它是一個軟體系統,為了支援跨網路的機器間相互操作互動而設計。Web Service服務通常被定義為一組模組化的API,它們可以通過網路進行呼叫,來執行遠端系統的請求服務。簡單的說:WebService即Web服務,它是一種跨程式語言和跨作業系統平臺的遠端呼叫技術。
Web服務:基於HTTP和XML的技術,HTTP是網際網路上應用最為廣泛的一種網路協議,而XML是跨平臺的基礎。 跨程式語言和跨操作平臺:就是說服務端程式採用java編寫,客戶端程式則可以採用其他程式語言編寫,反之亦然!跨作業系統平臺則是指服務端程式和客戶端程式可以在不同的作業系統上執行。 遠端呼叫:就是一臺計算機a上的一個程式可以呼叫到另外一臺計算機b上的一個物件的方法,譬如,銀聯提供給商場的pos刷卡系統,商場的POS機轉賬呼叫的轉賬方法的程式碼其實是跑在銀行伺服器上。再比如,amazon,天氣預報系統,淘寶網,校內網,百度等把自己的系統服務以webservice服務的形式暴露出來,讓第三方網站和程式可以呼叫這些服務功能,這樣擴充套件了自己系統的市場佔有率。
2.webService的三要素
WebService的三要素是:
SOAP (Simple Object Access Protocol):簡易物件訪問協議,soap用來描述傳遞資訊的格式。
WSDL (WebServices Description Language):Web服務描述語言,用來描述如何訪問具體的介面。
UDDI (Universal Description Discovery and Integration):通用描述、發現及整合,用來管理、分發、查詢webService。
3.呼叫原理
實現一個完整的Web服務包括以下步驟:
◆ Web服務提供者設計實現Web服務,並將除錯正確後的Web服務通過Web服務中介者釋出,並在UDDI註冊中心註冊; (釋出)
◆ Web服務請求者向Web服務中介者請求特定的服務,中介者根據請求查詢UDDI註冊中心,為請求者尋找滿足請求的服務; (發現)
◆ Web服務中介者向Web服務請求者返回滿足條件的Web服務描述資訊,該描述資訊用WSDL寫成,各種支援Web服務的機器都能閱讀;(發現)
◆ 利用從Web服務中介者返回的描述資訊生成相應的SOAP訊息,傳送給Web服務提供者,以實現Web服務的呼叫;(繫結)
◆ Web服務提供者按SOAP訊息執行相應的Web服務,並將服務結果返回給Web服務請求者。(繫結)
4.自定義webService服務端併發布服務編寫客戶端測試
①編寫服務介面
public interface WebServiceInterface { |
②編寫介面實現類
@WebService |
③編寫服務釋出類
public class WebServiceServer { //引數1:服務被訪問的url ip+埠號+服務名 //引數2:實現類 new WebServiceInterfaceImpl()); //檢視WebService服務是否啟動 url+?wsdl //http://l27.0.0.1:9999/queryPhone?wsdl是否能顯示 } |
④ 驗證服務是否釋出成功
⑤執行wsimport生成客戶端程式碼
⑥ 編寫客戶端呼叫服務端程式碼
public class WebServiceClient { |