首先準備環(huán)境:SpringMVC4.0、WebSocket、Tomcat7.0,具體配置就不說了,網(wǎng)上有。
目的:在控制層(Controller)實現(xiàn)springmvc和websocket的統(tǒng)一接口映射,即websocket訪問后臺也可以像springmvc訪問Controller方法一樣
實現(xiàn)原理:定義一個主要的websocket處理類,在這個websocket的基礎下進行接口分發(fā)和參數(shù)映射。
具體方法:
1.通過字符串或JSON(方便映射前端的js對象)來傳遞訪問的路徑,也就是調用Controller的某個方法。RequestMappingHandlerMapping對象持有Controller的所有配置接口和方法信息,遍歷接口信息,匹配到前端的訪問路徑就可以進行調用了。
2.參數(shù)映射有很多方案,最簡單的統(tǒng)一用Map傳參,Controller的接口也支持,這樣就實現(xiàn)了接口的通用。
下面是主要的websocket消息處理類
- @SuppressWarnings("unchecked")
- public class MainHandler extends TextWebSocketHandler{
-
- @Autowired
- private RequestMappingHandlerMapping requestMappingHandlerMapping;
-
-
- @Override
- public void handleTextMessage(WebSocketSession session,
- TextMessage message) throws Exception {
- // TODO Auto-generated method stub
- String msg = message.getPayload();
- Map<RequestMappingInfo, HandlerMethod> map = requestMappingHandlerMapping.getHandlerMethods();
- Object result = null;
-
- String url = msg;
- Map<String, Object> parameter = new HashMap<String, Object>();
- Pattern pattern = Pattern.compile("^\\{(\"\\w+\":\\S+,{0,1})+\\}$");
- if(pattern.matcher(msg).matches()){
- JSONObject json = JSONObject.fromObject(message.getPayload());
- if(json.get("url") != null){
- url = String.valueOf(json.get("url"));
- if(json.get("params") != null){
- parameter = (Map<String, Object>) json.get("params");
- }
- }
- }
-
- for (Map.Entry<RequestMappingInfo, HandlerMethod> m : map.entrySet()) {
- RequestMappingInfo info = m.getKey();
- HandlerMethod method = m.getValue();
- PatternsRequestCondition p = info.getPatternsCondition();
- if(p.getPatterns().size() > 0 && p.getPatterns().toArray()[0].equals(url)){
- String url_pt = String.valueOf(p.getPatterns().toArray()[0]);
- String methodName = url_pt.substring(url_pt.lastIndexOf('/')+1);
- Class<?> cls = method.getMethod().getDeclaringClass();
- Object controller = cls.newInstance();
- boolean success = true;
- try{
- result = cls.getDeclaredMethod(methodName, Map.class).invoke(controller, parameter);
- }catch(Exception e){
- success = false;
- }
- if(!success){
- try{
- result = cls.getDeclaredMethod(methodName).invoke(controller);
- }catch(Exception e){
- success = false;
- }
- }
- if(!success) result = "未找到指定方法或方法參數(shù)不匹配";
- break;
- }
-
- }
-
- if(result != null){
- session.sendMessage(new TextMessage(String.valueOf(result).getBytes()));
- }
-
- }
-
-
- }
前端發(fā)送:
- WSClient.fn.pushMsgEvent = function(msgEvent){
- if(typeof msgEvent == "function") this.msgPool.push(_opts.msgEvent);
- return this.msgPool;
- }
細節(jié)說明:
1.一般來說,SpringMVC和WebSocket的接口整合是在service層,SpringMVC的Controller層通常不做任何業(yè)務處理或少量處理,只負責提供接口。個人實現(xiàn)這套方案只是想通過注解的形式來定義WebSocket的接口,順便通用一下
2.如果Controller的接口參數(shù)不想用Map,則可以重載一個參數(shù)為Map的函數(shù),如下:
- @RequestMapping("/test")
- public @ResponseBody List test(HttpServletRequest request){
- return test(request.getParameterMap());
- }
-
- public @ResponseBody List test(Map map){
- System.out.println(map);
- List<String> tmp = new ArrayList<String>();
- tmp.add("1222");
- tmp.add("2333");
- return tmp;
- }
3.后續(xù)補充...
|