操屁眼的视频在线免费看,日本在线综合一区二区,久久在线观看免费视频,欧美日韩精品久久综

新聞資訊

    于html5的Websocket網頁即時通訊技術,前端開發采用ExtJS前端框架

    JavaEE框架:Mybatis、SpringMVC

    先去官網下載ExtJS框架的資料文件:

    https://www.sencha.com/products/extjs/evaluate/

    可以參考中文翻譯過來的官網查看API:

    http://extjs-doc-cn.github.io/ext4api/

    下載集成的jar:


    websocket.css:

    @CHARSET "UTF-8";
    .l-im-message-warn {
     font-family: "微軟雅黑";
     cursor: default;
     width: 100%;
     padding: 5px 0px 5px 25px;
     -webkit-user-select : none;
     background: url("../images/information.png") no-repeat 5;
    }
    .l-im-message {
     font-family: "微軟雅黑";
     cursor: default;
     width: 100%;
    }
    .l-im-message-over {
     background-color: rgba(233, 233, 233, 0.5);
    }
    .l-im-message-selected {
     background-color: rgba(250, 218, 90, 0.5);
    }
    .l-im-message-header {
     font-size: 12px;
     padding: 5px 0px 5px 10px;
    }
    .l-im-message-header-self {
     color: green;
    }
    .l-im-message-header-remote {
     color: blue;
    }
    .l-im-message-body {
     font-size: 12px;
     padding: 2px 0px 2px 20px;
    }
    .user-win {
     background-image: url( ../images/user_win.png )
     !important;
    }
    .user-online {
     background-image: url( ../images/group.png )
     !important;
    }
    .user {
     background-image: url( ../images/user.gif )
     !important;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    

    websocket.js:

    var websocket;
    var isCreatw = false;
    var title="\";
    var win;
    var input;
    var isQj = true;
    var toUser="";
    function toUserMsg(toU){
     if((!isQj && toUser == toU) || toU == user){
     win.setTitle(title + " (已連接) 【現在全局對話】");
     isQj = true;
     toUser = "";
     }else{
     win.setTitle(title + " (已連接) 【現在單獨與"+toU+"對話】");
     isQj = false;
     toUser = toU;
     }
    }
     function creatw() {
     if(isCreatw){
     alert("已經啟動");
     return;
     }else{
     isCreatw = true;
     }
     //創建用戶輸入框
     input = Ext.create('Ext.form.field.HtmlEditor', {
     region : 'south',
     height : 120,
     enableFont : false,
     enableSourceEdit : false,
     enableAlignments : false,
     listeners : {
     initialize : function() {
     Ext.EventManager.on(me.input.getDoc(), {
     keyup : function(e) {
     if (e.ctrlKey === true
     && e.keyCode == 13) {
     e.preventDefault();
     e.stopPropagation();
     send();
     }
     }
     });
     }
     }
     });
     //創建消息展示容器
     var output = Ext.create('MessageContainer', {
     region : 'center'
     });
     var dialog = Ext.create('Ext.panel.Panel', {
     region : 'center',
     layout : 'border',
     items : [input, output],
     buttons : [{
     text : '發送',
     handler : send
     }]
     });
     //初始話WebSocket
     function initWebSocket() {
     if (window.WebSocket) {
     websocket = new WebSocket(encodeURI('ws://'+wimadress));
     websocket.onopen = function() {
     //連接成功
     win.setTitle(title + ' (已連接) 【現在全局對話】');
     websocket.send('admin'+user);
     }
     websocket.onerror = function() {
     //連接失敗
     win.setTitle(title + ' (連接發生錯誤)');
     }
     websocket.onclose = function() {
     //連接斷開
     win.setTitle(title + ' (已經斷開連接)');
     }
     //消息接收
     websocket.onmessage = function(message) {
     var message = JSON.parse(message.data);
     //接收用戶發送的消息
     if (message.type == 'message') {
     output.receive(message);
     } else if (message.type == 'get_online_user') {
     //獲取在線用戶列表
     var root = onlineUser.getRootNode();
     Ext.each(message.list,function(user){
     var node = root.createNode({
     id : user,
     text : user,
     iconCls : 'user',
     leaf : true
     });
     root.appendChild(node);
     });
     } else if (message.type == 'user_join') {
     //用戶上線
     var root = onlineUser.getRootNode();
     var user = message.user;
     var node = root.createNode({
     id : user,
     text : user,
     iconCls : 'user',
     leaf : true
     });
     root.appendChild(node);
     } else if (message.type == 'user_leave') {
     //用戶下線
     var root = onlineUser.getRootNode();
     var user = message.user;
     var node = root.findChild('id',user);
     root.removeChild(node);
     }
     }
     }
     };
     //在線用戶樹
     var onlineUser = Ext.create('Ext.tree.Panel', {
     title : '在線用戶',
     rootVisible : false,
     region : 'east',
     width : 150,
     lines : false,
     useArrows : true,
     autoScroll : true,
     split : true,
     iconCls : 'user-online',
     store : Ext.create('Ext.data.TreeStore', {
     root : {
     text : '在線用戶',
     expanded : true,
     children : []
     }
     })
     });
     title = "歡迎您:" + user;
     //展示窗口
     win = Ext.create('Ext.window.Window', {
     title : title + ' (未連接)',
     layout : 'border',
     iconCls : 'user-win',
     minWidth : 650,
     minHeight : 460,
     width : 650,
     animateTarget : 'websocket_button',
     height : 460,
     items : [dialog,onlineUser],
     border : false,
     listeners : {
     render : function() {
     initWebSocket();
     }
     }
     });
     win.show();
     win.on("close",function(){
     websocket.send('LeaveAdmin');
     isCreatw = false;
     });
     //發送消息
     function send() {
     var content = input.getValue();
     if(toUser != ""){content = "admin886"+toUser+"admin888" + content;}
     var message = {};
     if (websocket != null) {
     if (input.getValue()) {
     Ext.apply(message, {
     from : user,
     content : content,
     timestamp : new Date().getTime(),
     type : 'message'
     });
     websocket.send(JSON.stringify(message));
     //output.receive(message);
     input.setValue('');
     }
     } else {
     Ext.Msg.alert('提示', '您已經掉線,無法發送消息!');
     }
     }
    };
    //用于展示用戶的聊天信息
    Ext.define('MessageContainer', {
     extend : 'Ext.view.View',
     trackOver : true,
     multiSelect : false,
     itemCls : 'l-im-message',
     itemSelector : 'div.l-im-message',
     overItemCls : 'l-im-message-over',
     selectedItemCls : 'l-im-message-selected',
     style : {
     overflow : 'auto',
     backgroundColor : '#fff'
     },
     tpl : [
     '<div class="l-im-message-warn">?歡迎使用即時通訊系統。</div>',
     '<tpl for=".">',
     '<div class="l-im-message">',
     '<div class="l-im-message-header l-im-message-header-{source}">{from} {timestamp}</div>',
     '<div class="l-im-message-body">{content}</div>', '</div>',
     '</tpl>'],
     messages : [],
     initComponent : function() {
     var me = this;
     me.messageModel = Ext.define('Leetop.im.MessageModel', {
     extend : 'Ext.data.Model',
     fields : ['from', 'timestamp', 'content', 'source']
     });
     me.store = Ext.create('Ext.data.Store', {
     model : 'Leetop.im.MessageModel',
     data : me.messages
     });
     me.callParent();
     },
     //將服務器推送的信息展示到頁面中
     receive : function(message) {
     var me = this;
     message['timestamp'] = Ext.Date.format(new Date(message['timestamp']),
     'H:i:s');
     if(message.from == user){
     message.source = 'self';
     }else{
     message.source = 'remote';
     }
     me.store.add(message);
     if (me.el.dom) {
     me.el.dom.scrollTop = me.el.dom.scrollHeight;
     }
     }
    });
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    

    業務代碼編寫:

    ChatServer.java

    package com.appms.websocket;
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.net.UnknownHostException;
    import java.util.Date;
    import net.sf.json.JSONObject;
    import org.java_websocket.WebSocket;
    import org.java_websocket.WebSocketImpl;
    import org.java_websocket.framing.Framedata;
    import org.java_websocket.handshake.ClientHandshake;
    import org.java_websocket.server.WebSocketServer;
    /**
     * 即時通訊
     */
    public class ChatServer extends WebSocketServer{
     public ChatServer(int port) throws UnknownHostException {
     super(new InetSocketAddress(port));
     }
     public ChatServer(InetSocketAddress address) {
     super(address);
     }
     /**
     * 觸發連接事件
     */
     @Override
     public void onOpen( WebSocket conn, ClientHandshake handshake ) {
     }
     /**
     * 觸發關閉事件
     */
     @Override
     public void onClose( WebSocket conn, int code, String reason, boolean remote ) {
     userLeave(conn);
     }
     /**
     * 客戶端發送消息到服務器時觸發事件
     */
     @Override
     public void onMessage(WebSocket conn, String message){
     message = message.toString();
     if(null != message && message.startsWith("admin")){
     this.userjoin(message.replaceFirst("admin", ""),conn);
     }if(null != message && message.startsWith("LeaveAdmin")){
     this.userLeave(conn);
     }if(null != message && message.contains("admin886")){
     String toUser = message.substring(message.indexOf("admin886")+8, message.indexOf("admin888"));
     message = message.substring(0, message.indexOf("admin886")) +"[私信] "+ message.substring(message.indexOf("admin888")+8, message.length());
     ChatServerPool.sendMessageToUser(ChatServerPool.getWebSocketByUser(toUser),message);//向所某用戶發送消息
     ChatServerPool.sendMessageToUser(conn, message);//同時向本人發送消息
     }else{
     ChatServerPool.sendMessage(message.toString());//向所有在線用戶發送消息
     }
     }
     public void onFragment( WebSocket conn, Framedata fragment ) {
     }
     /**
     * 觸發異常事件
     */
     @Override
     public void onError( WebSocket conn, Exception ex ) {
     ex.printStackTrace();
     if( conn != null ) {
     //some errors like port binding failed may not be assignable to a specific websocket
     }
     }
     /**
     * 用戶加入處理
     * @param user
     */
     public void userjoin(String user, WebSocket conn){
     JSONObject result = new JSONObject();
     result.element("type", "user_join");
     result.element("user", "<a onclick=\"toUserMsg('"+user+"');\">"+user+"</a>");
     ChatServerPool.sendMessage(result.toString()); //把當前用戶加入到所有在線用戶列表中
     String joinMsg = "{\"from\":\"[系統]\",\"content\":\""+user+"上線了\",\"timestamp\":"+new Date().getTime()+",\"type\":\"message\"}";
     ChatServerPool.sendMessage(joinMsg); //向所有在線用戶推送當前用戶上線的消息
     result = new JSONObject();
     result.element("type", "get_online_user");
     ChatServerPool.addUser(user,conn); //向連接池添加當前的連接對象
     result.element("list", ChatServerPool.getOnlineUser());
     ChatServerPool.sendMessageToUser(conn, result.toString()); //向當前連接發送當前在線用戶的列表
     }
     /**
     * 用戶下線處理
     * @param user
     */
     public void userLeave(WebSocket conn){
     String user = ChatServerPool.getUserByKey(conn);
     boolean b = ChatServerPool.removeUser(conn); //在連接池中移除連接
     if(b){
     JSONObject result = new JSONObject();
     result.element("type", "user_leave");
     result.element("user", "<a onclick=\"toUserMsg('"+user+"');\">"+user+"</a>");
     ChatServerPool.sendMessage(result.toString()); //把當前用戶從所有在線用戶列表中刪除
     String joinMsg = "{\"from\":\"[系統]\",\"content\":\""+user+"下線了\",\"timestamp\":"+new Date().getTime()+",\"type\":\"message\"}";
     ChatServerPool.sendMessage(joinMsg); //向在線用戶發送當前用戶退出的消息
     }
     }
     public static void main( String[] args ) throws InterruptedException , IOException {
     WebSocketImpl.DEBUG = false;
     int port = 8887; //端口
     ChatServer s = new ChatServer(port);
     s.start();
     System.out.println( "服務器的端口" + s.getPort() );
     }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    

    ChatServerPool.java:

    package com.appms.websocket;
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import org.java_websocket.WebSocket;
    /**
     * 即時通訊
     */
    public class ChatServerPool {
     private static final Map<WebSocket,String> userconnections = new HashMap<WebSocket,String>();
     /**
     * 獲取用戶名
     * @param session
     */
     public static String getUserByKey(WebSocket conn){
     return userconnections.get(conn);
     }
     /**
     * 獲取WebSocket
     * @param user
     */
     public static WebSocket getWebSocketByUser(String user){
     Set<WebSocket> keySet = userconnections.keySet();
     synchronized (keySet) {
     for (WebSocket conn : keySet) {
     String cuser = userconnections.get(conn);
     if(cuser.equals(user)){
     return conn;
     }
     }
     }
     return null;
     }
     /**
     * 向連接池中添加連接
     * @param inbound
     */
     public static void addUser(String user, WebSocket conn){
     userconnections.put(conn,user); //添加連接
     }
     /**
     * 獲取所有的在線用戶
     * @return
     */
     public static Collection<String> getOnlineUser(){
     List<String> setUsers = new ArrayList<String>();
     Collection<String> setUser = userconnections.values();
     for(String u:setUser){
     setUsers.add("<a onclick=\"toUserMsg('"+u+"');\">"+u+"</a>");
     }
     return setUsers;
     }
     /**
     * 移除連接池中的連接
     * @param inbound
     */
     public static boolean removeUser(WebSocket conn){
     if(userconnections.containsKey(conn)){
     userconnections.remove(conn); //移除連接
     return true;
     }else{
     return false;
     }
     }
     /**
     * 向特定的用戶發送數據
     * @param user
     * @param message
     */
     public static void sendMessageToUser(WebSocket conn,String message){
     if(null != conn && null != userconnections.get(conn)){
     conn.send(message);
     }
     }
     /**
     * 向所有的用戶發送消息
     * @param message
     */
     public static void sendMessage(String message){
     Set<WebSocket> keySet = userconnections.keySet();
     synchronized (keySet) {
     for (WebSocket conn : keySet) {
     String user = userconnections.get(conn);
     if(user != null){
     conn.send(message);
     }
     }
     }
     }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    

    寫個過濾器,在項目執行時啟動:

    package com.appms.filter;
    import java.io.IOException;
    import java.net.UnknownHostException;
    import java.util.Calendar;
    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import org.java_websocket.WebSocketImpl;
    import com.appms.base.BaseController;
    import com.appms.base.Const;
    import com.appms.utils.Tools;
    import com.appms.websocket.ChatServer;
    import com.appms.websocket.OnlineChatServer;
    public class StartFilter extends BaseController implements Filter{
     /**
     * 初始化
     */
     public void init(FilterConfig fc) throws ServletException {
     this.startWebsocketInstantMsg();
     this.startWebsocketOnline();
     }
     /**
     * 啟動即時聊天服務
     */
     public void startWebsocketInstantMsg(){
     WebSocketImpl.DEBUG = false;
     ChatServer s = null;
     try {
     String strWEBSOCKET = Tools.readTxtFile(Const.WEBSOCKET);//讀取WEBSOCKET配置,獲取端口配置
     if(null != strWEBSOCKET && !"".equals(strWEBSOCKET)){
     String strIW[] = strWEBSOCKET.split(",fh,");
     if(strIW.length == 4){
     s = new ChatServer(Integer.parseInt(strIW[1]));
     s.start();
     }
     }
     System.out.println( "websocket服務器啟動,端口" + s.getPort() );
     } catch (UnknownHostException e) {
     e.printStackTrace();
     }
     }
     /**
     * 啟動在線管理服務
     */
     public void startWebsocketOnline(){
     WebSocketImpl.DEBUG = false;
     OnlineChatServer s = null;
     try {
     String strWEBSOCKET = Tools.readTxtFile(Const.WEBSOCKET);//讀取WEBSOCKET配置,獲取端口配置
     if(null != strWEBSOCKET && !"".equals(strWEBSOCKET)){
     String strIW[] = strWEBSOCKET.split(",fh,");
     if(strIW.length == 4){
     s = new OnlineChatServer(Integer.parseInt(strIW[3]));
     s.start();
     }
     }
     System.out.println( "websocket服務器啟動,端口" + s.getPort() );
     } catch (UnknownHostException e) {
     e.printStackTrace();
     }
     }
     //計時器
     public void timer() {
     Calendar calendar = Calendar.getInstance();
     calendar.set(Calendar.HOUR_OF_DAY, 9); // 控制時
     calendar.set(Calendar.MINUTE, 0); // 控制分
     calendar.set(Calendar.SECOND, 0); // 控制秒
     Date time = calendar.getTime(); // 得出執行任務的時間
     Timer timer = new Timer();
     timer.scheduleAtFixedRate(new TimerTask() {
     public void run() {
     //PersonService personService = (PersonService)ApplicationContext.getBean("personService");
     }
     }, time, 1000*60*60*24);// 這里設定將延時每天固定執行
     }
     public void destroy() {
     // TODO Auto-generated method stub
     }
     public void doFilter(ServletRequest arg0, ServletResponse arg1,
     FilterChain arg2) throws IOException, ServletException {
     // TODO Auto-generated method stub
     }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    

    在web.xml里配置:

     <filter>
     <filter-name>startFilter</filter-name>
     <filter-class>com.appms.filter.StartFilter</filter-class>
     </filter>
    1
    2
    3
    4
    

    在jsp頁面進行調用:

     <script type="text/javascript">var wimadress="127.0.0.1:8887";</script>
     <script type="text/javascript">var oladress="127.0.0.1:8889";</script>
     <link rel="stylesheet" type="text/css" href="plugins/websocket/ext4/resources/css/ext-all.css">
     <link rel="stylesheet" type="text/css" href="plugins/websocket/css/websocket.css" />
     <script type="text/javascript" src="plugins/websocket/ext4/ext-all-debug.js"></script>
     <script type="text/javascript" src="plugins/websocket/websocket.js"></script>
     <!--引入屬于此頁面的js -->
     <script type="text/javascript" src="source/js/jquery-1.8.3.js"></script>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    

    點擊li標簽跳出聊天頁面

    ul class="am-avg-sm-1 am-avg-md-4 am-margin am-padding am-text-center admin-content-list ">
     <li onclick="creatw();"><a href="javascript:;"><span class="am-icon-btn am-icon-file-text"></span><br/>即時通訊<br/></a></li>
     <li><a href="fusioncharts/index.do" class="am-text-warning"><span class="am-icon-btn am-icon-briefcase"></span><br/>圖表統計<br/></a></li>
     <li><a href="#" class="am-text-danger"><span class="am-icon-btn am-icon-recycle"></span><br/>昨日訪問<br/>80082</a></li>
     <li><a href="#" class="am-text-secondary"><span class="am-icon-btn am-icon-user-md"></span><br/>在線用戶<br/>3000</a></li>
     </ul>
    1
    2
    3
    4
    5
    6
    

    私聊:


    群聊:


    基于ExtJS前端框架的Websocket即時通訊系統

    IT之家 11 月 30 日消息,據微軟中國 MSDN 發布,.NET 多平臺應用程序 UI (.NET MAUI) 可以使用單個代碼庫為 Windows、macOS、iOS 和 Android 構建本機客戶端應用程序,并為 Blazor 混合方案提供本機容器和控件。.NET MAUI 是 Visual Studio 中的一個框架,它抽象了已經可用的本機 UI 框架 ——WinUI for Windows、Mac Catalyst for macOS/iPadOS、iOS 和 Android。盡管它不是另一個本機 UI 框架,但仍有大量工作需要在這些設備上提供最佳開發和運行時體驗。

    .NET 團隊一直在與社區一起努力的開發,微軟致力于它的發布。遺憾的是,.NET MAUI 將無法在 11 月與 .NET 6 GA 一起發布。微軟希望在第一天就為用戶提供最佳體驗、性能和質量,為此,微軟需要推遲時間表。IT之家獲悉,微軟現在的目標是在 2022 年第二季度初推出 .NET MAUI 。

    與此同時,微軟將繼續增強 Xamarin 并推薦它用于構建生產移動應用程序,并繼續發布 .NET MAUI 的月度預覽。微軟計劃為 .NET MAUI 提供的所有功能將在 11 月 .NET 6 發布時提供,但微軟將繼續努力提高質量并解決客戶反饋。微軟鼓勵你嘗試預覽。.NET 升級助手還將支持將 Xamarin 項目升級到 .NET MAUI。

    .NET 6 RC1 是最終版本之前的版本,這意味著你可以在生產中使用它并獲得支持。這不包括 .NET MAUI 包。.NET MAUI 包的下一個版本,當 .NET 6 RC2 發布時,將在版本中顯示“預覽”。

    .NET 多平臺應用程序 UI (.NET MAUI)

    https://github.com/dotnet/maui

    .NET MAUI 預覽版 8 亮點

    .NET MAUI 的 9 月預覽版完成了一些重要的 Visual Studio 集成,即在 Visual Studio 2022 安裝程序中將 .NET MAUI 作為工作負載安裝,并將 Windows 平臺折疊到微軟的單一、多目標項目中。借助 Visual Studio 2022 預覽版 4,你現在可以通過 C# 和 XAML 使用更廣泛的熱重載支持,以及新的 XAML 實時預覽面板,以打造高效、專注的開發環境。在 .NET MAUI SDK 本身中,預覽 8 包括對應用程序啟動模式的更新、擴展處理程序的能力,以及在微軟接近功能完整性時的其他各種新控件功能。

    Visual Studio 2022 生產力

    安裝 Visual Studio 2022 時,你現在可以在使用 .NET 工作負載的移動開發中檢查 .NET MAUI(預覽版)。這將引入 .NET 6 以及可選的工作負載依賴項:Android、iOS 和 Mac Catalyst。以桌面為目標時,你還需要選擇使用 .NET、UWP 的桌面開發和使用 C++ 工作負載的桌面開發。

    安裝后,.NET MAUI 模板和 Visual Studio 的功能都可用。實時預覽將在 Visual Studio 窗口中的面板中鏡像你正在運行的應用程序,你可以??吭谧罘奖愕娜魏挝恢?。該面板支持放大和縮小以關注 UI 的每個細節,在水平和垂直軸上對齊元素的指南,并且在某些平臺上,你可以懸停并選擇 UI 元素以獲取大小和距離信息。

    XAML 熱重載現在適用于 Android、iOS(在 Windows 上通過熱重啟或遠程構建主機)和 Windows。.NET Hot Restart 也在 Android、iOS 和 Windows 上與 XAML Hot Reload 協同工作。

    創建新項目時,你現在會在 Platforms 文件夾中看到 Windows 平臺與 Android、iOS 和 Mac Catalyst 并列。要使用 Windows,首先需要安裝適用于 Visual Studio 2022 的 Windows App SDK 擴展,然后取消注釋 csproj 文件頂部的 TargetFramework 節點。在未來的版本中,默認情況下,這將通過 .NET MAUI 預安裝的擴展程序提供。

    .NET MAUI SDK 更新

    你遷移現有應用程序最顯著的更新是微軟如何實現 .NET Host Builder 模式。微軟現在與 ASP.NET 和 Blazor 如何使用創建并返回 MauiApp 的 MauiProgram 類保持一致?,F在每個平臺都調用 MauiProgram.CreateMauiApp。將現有項目與新模板或 pull request 進行比較,以查看對 Android/MainApplication.cs、iOS/AppDelegate.cs 和 macCatalyst/AppDelegate.cs 的這些更改。

    示例 MauiProgram:

    public static class MauiProgram
    {
    public static MauiApp CreateMauiApp()
    {
    var builder = MauiApp.CreateBuilder();
    builder
    .UseMauiApp<App>()
    .ConfigureFonts(fonts =>
    {
    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
    });
    return builder.Build();
    }
    }

    安卓示例 MainApplication:

    public class MainApplication : MauiApplication
    {
    public MainApplication(IntPtr handle, JniHandleOwnership ownership)
    : base(handle, ownership)
    {
    }
    protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
    }

    pull request:

    https://github.com/dotnet/maui/pull/2137

    安卓更新

    Android 12 (API 31) 現在是為 Android 構建的 .NET 6 應用程序的默認版本。要使用 Android 12,你需要手動安裝 JDK 11。一旦微軟更新 Visual Studio 中的 Android 工具以使用 JDK 11,微軟將默認將此依賴項與 .NET MAUI 捆綁在一起。在此之前,JDK 11 可能會對 Android 設計器、SDK 管理器和設備管理器產生不利影響。

    Android 項目現在默認使用 MaterialTheme。確保 Platforms/Android/MainActivity.cs 指定 @style/Maui.SplashTheme 否則你可能會在 Android 上遇到運行時錯誤。例如,查看更新的 .NET MAUI 模板。

    手動安裝 JDK 11:

    https://github.com/xamarin/xamarin-android/wiki/JDK-11-Warning

    更新的 .NET MAUI 模板:

    https://github.com/dotnet/maui/blob/main/src/Templates/src/templates/maui-mobile/Platforms/Android/MainActivity.cs

    其他變化

    其他值得注意的變化包括:

    • MinHeightRequest、MaxHeightRequest、MinWidthRequest、MaxWidthRequest 已刪除“Request”后綴,布局系統現在將它們視為真實值

    • 將行為附加到任何控件映射器的簡化方法 – #1859

    • Shell 主題樣式的各種改進

    • 為 Android #2027 和 iOS #2029 添加了 RefreshView

    • 添加絕對布局 #2136

    • 添加了從右到左 (RTL) FlowDirection #948

    • 添加 Button.Icon ImageSource #2079

    #1859:

    https://github.com/dotnet/maui/pull/1859

    #2027:

    https://github.com/dotnet/maui/pull/2027

    #2029:

    https://github.com/dotnet/maui/pull/2029

    #2136:

    https://github.com/dotnet/maui/pull/2136

    #948:

    https://github.com/dotnet/maui/pull/948

    #2079:

    https://github.com/dotnet/maui/pull/2079

    準備好了嗎?打開 Visual Studio 2022 并創建一個新項目。搜索并選擇 .NET MAUI。

    有關 .NET MAUI 入門的更多信息,請參閱微軟的文檔。

    文檔:

    https://docs.microsoft.com/zh-cn/dotnet/maui/get-started/installation

    歡迎反饋

    Visual Studio 2022 正在快速啟用 .NET MAUI 的新功能。當你在調試、部署和編輯器相關體驗方面遇到任何問題時,請使用“幫助”>“發送反饋”菜單報告你的體驗。

    請通過 dotnet/maui 在 GitHub 上與微軟互動,讓微軟了解你使用 .NET MAUI 創建新應用程序的體驗。

    要查看未來版本中的內容,請訪問微軟的產品路線圖,要了解功能完整性的狀態,請訪問微軟的狀態 wiki。

    dotnet/maui:

    https://github.com/dotnet/maui

    產品路線圖:

    https://github.com/dotnet/maui/wiki/roadmap

    狀態 wiki:

    https://github.com/dotnet/maui/wiki/status

網站首頁   |    關于我們   |    公司新聞   |    產品方案   |    用戶案例   |    售后服務   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權所有