tomcat配置SSL环境

生成安全证书:

1.java环境:因为SUN公司提供了制作证书的工具keytool。在JDK 1.4以后的版本中都包含了这一工具,它的位置为<JAVA_HOME>\bin\keytool.exe。

2.创建证书的命令:

Cmd代码
  1. keytool -genkeypair -alias “tomcat” -keyalg “RSA” -keystore “f:\tomcat.keystore”

参数的意思如下:

1505117109-4382-e190-3065-9e30-7633e955be16

这里密码我输的是tomcat,名字与姓氏为域名,其它的根据具体情况输入f38ff7b2-cfa7-3b70-b2ff-fa3588b462e7

 

以上命令将生产一对非对称密钥和自我签名的证书f:\tomcat.keystore.

将证书保存到你要存放的地方,我的保存在D:\Tools\Web\ssl\tomcat.keystore

注意:“名字与姓氏”应该是域名,输成了姓名,和真正运行的时候域名不符,会出问题

—————————————————————————————————————————

配置tomcat:

定位到tomcat的安装目录,找到conf下的server.xml文件

找到如下已经被注释的代码:

Xml代码
<!– <Connector port=”8443″ protocol=”org.apache.coyote.http11.Http11NioProtocol”
maxThreads=”150″ SSLEnabled=”true” scheme=”https” secure=”true” keystoreFile=”/root/shangdao.keystore” keystorePass=”111111″
clientAuth=”false” sslProtocol=”TLS” /> –>

去掉注释,修改为:

Xml代码
<Connector port=”8443″ protocol=”org.apache.coyote.http11.Http11NioProtocol”
maxThreads=”150″ SSLEnabled=”true” scheme=”https” secure=”true” keystoreFile=”/root/shangdao.keystore” keystorePass=”111111″
clientAuth=”false” sslProtocol=”TLS” />

这里,密码和证书的位置根据个人的具体环境而设置,属性参数如下所述:

属性 描述
clientAuth 如果设为true,表示Tomcat要求所有的SSL客户出示安全证书,对SSL客户进行身份验证
keystoreFile 指定keystore文件的存放位置,可以指定绝对路径,也可以指定相对于<CATALINA_HOME>(Tomcat安装目录)环境变量 的相对路径。如果此项没有设定,默认情况下,Tomcat将从当前操作系统用户的用户目录下读取名为“.keystore”的文件。
keystorePass 指定keystore的密码,如果此项没有设定,在默认情况下,Tomcat将使用“changeit”作为默认密码。
sslProtocol 指定套接字(Socket)使用的加密/解密协议,默认值为TLS,用户不应该修改这个默认值。
ciphers 指定套接字可用的用于加密的密码清单,多个密码间以逗号(,)分隔。如果此项没有设定,在默认情况下,套接字可以使用任意一个可用的密码。

访问支持ssl的web站点:

启动tomcat,在浏览器中输入:https://localhost:8443/。

QQ截图20170911161055

Java使用websocket实现聊天室简单功能

最近有个项目需要实现视频流的信息交换处理,但是之前一直都没有写过有关的代码,所以就想到了websocket接口。

java创建一个socket非常简单,繁琐的可能是日常的业务信息处理,下面看下一段代码:

import model.User;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by alan.luo on 2017/9/10.
 */

@ServerEndpoint(value = "/websocket2")
public class TestWebSocket {

    @OnOpen
    public void onOpen(Session session, EndpointConfig endpointConfig) {
        sendMsg(session,"Welcome back.");

        //push list.
        User user = new User();
        user.setId(Integer.parseInt(session.getId()));

        Map<String,List<String>> map = session.getRequestParameterMap();
        user.setUserName(map.get("userName").get(0));
        user.setSession(session);

        //has client come in,so server must be save the session to the application.class.
        Application.getInstance().putSession(user);
    }

    @OnMessage
    public void onMessage(Session session,String message){
        System.out.println("++++++++++:"+message);

        //if has user push message to the server.then server will each all the client and send message too.
        for (User user:Application.getInstance().getUsers()){
            sendMsg(user.getSession(),user.getUserName() + " say:"+message);
        }

    }

    @OnClose
    public void onClose(Session session, CloseReason closeReason){
        List<User> list = Application.getInstance().getUsers();
        //pop list.
        for (int i = 0;i<list.size();i++){
            if (Integer.parseInt(session.getId()) == list.get(i).getId()){
                list.remove(i);
                Application.getInstance().setUsers(list);
                break;
            }
        }
    }

    @OnError
    public void onError(Session session, Throwable thr) {
        System.out.println("+++++++++onError"+thr.getMessage());
    }

    /**
     * send message to session.
     * @param session
     * @param message
     */
    protected void sendMsg(Session session,String message){
        System.out.println(message);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            session.getBasicRemote().sendText(message+" >"+sdf.format(new Date()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

当有客户端进入,则把客户端保存到application这个实例中,application是自定义的一个类,实现了单例,所以保存进去是最合适的,当有消息进入时,server将从application读取session list 并且遍历全部session and send the message。

Application实例的代码:

import model.User;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by alan.luo on 2017/9/10.
 */
public class Application {

    private List<User> users;
    private static Application app;

    public Application(){
        users = new ArrayList<>();
    }

    public static Application getInstance(){
        if (app == null){
            app = new Application();
        }
        return app;
    }

    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }

    public void putSession(User s){
        this.users.add(s);
    }

}

User实体类的代码:

package model;

import javax.websocket.Session;

/**
 * Created by alan.luo on 2017/9/6.
 */
public class User {
    private int id;

    private String userName;

    private String userPassword;

    private Session session;

    public Session getSession() {
        return session;
    }

    public void setSession(Session session) {
        this.session = session;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserPassword() {
        return userPassword;
    }

    public void setUserPassword(String userPasswd) {
        this.userPassword = userPasswd;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", userPassword='" + userPassword + '\'' +
                '}';
    }
}

可能会有错误,那是因为需要配置一下web.xml

<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>/websocket2</url-pattern>
</servlet-mapping>

 

剩下的就是javascript客户端的代码了:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <p><input type="text" id="userName" value="" placeholder="输入名字进入聊天室"></p>
</div>
<div>
    <textarea rows="16" cols="40" id="content"></textarea>
</div>
<div>
    <input type="text" id="message" value="" placeholder="输入内容"/>
    <button type="button" id="send">send</button>
</div>
<div>

    <button type="button" id="connect">connect</button>
    <button type="button" id="destroy">destroy</button>
</div>
<script>

        var connect = document.getElementById("connect");
        var content = document.getElementById("content");
        var message = document.getElementById("message");
        var destroy = document.getElementById("destroy");
        var send = document.getElementById("send");
        var userName = document.getElementById("userName");
        var socket = null;

        connect.addEventListener("click",function () {
            console.log("connect")
            if(userName.value.length <= 2){
                return false;
            }
            socket = new WebSocket("ws://localhost:8080/websocket2?userName="+userName.value);

            socket.onopen = function (p1) {
                console.log("onopen",p1)
            }

            socket.onclose = function (p1) {
                console.log("onclose",p1)
            }
            socket.onerror = function (p1) {
                console.log("onerror",p1)
            }
            socket.onmessage = function (p1) {
                console.log("onmessage",p1)
                content.innerHTML = (content.innerHTML + p1.data + "\n")
            }
        });
        destroy.addEventListener("click",function () {
            console.log("destroy")
            socket.close();
        });
        send.addEventListener("click",function () {
            console.log("send")
            socket.send(message.value);
            message.value = "";
        });


</script>

</body>
</html>

最后上传一张效果图吧:

QQ截图20170910223850

解决spring mvc跨域的问题

java开发网站是很繁琐的事情,特别是写前端,每次运行都需要进行编译,所以需要配置跨域访问:

服务端

首先要创建一个CrossDomainFilter类,类继承了Servlet Filter接口,如下代码:

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by alan.luo on 2017/9/5.
 */
public class CrossDomainFilter extends Compact implements Filter {


    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {

        try {
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            HttpServletResponse httpResponse = (HttpServletResponse) response;

            // 跨域
            String origin = httpRequest.getHeader("Origin");
            if (origin == null) {
                httpResponse.addHeader("Access-Control-Allow-Origin", "http://localhost/");

            } else {
                httpResponse.addHeader("Access-Control-Allow-Origin", origin);
            }
            httpResponse.addHeader("Access-Control-Allow-Headers", "Origin, x-requested-with, Content-Type, Accept,X-Cookie");
            httpResponse.addHeader("Access-Control-Allow-Credentials", "true");
            httpResponse.addHeader("Access-Control-Allow-Methods", "GET,POST,PUT,OPTIONS,DELETE");
            if ( httpRequest.getMethod().equals("OPTIONS") ) {
                httpResponse.setStatus(HttpServletResponse.SC_OK);
                return;
            }
            filterChain.doFilter(request, response);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void destroy() {
    }
}

类方法主要是配置response的响应信息,告诉客户端,可以传递什么及使用什么方法过来。

接下来就是配置xml文件,打开web.xml文件,在过滤代码中加入以下代码:

<!-- 允许跨域 -->
<filter>
    <filter-name>CrossDomainFilter</filter-name>
    <filter-class>com.test.com.CrossDomainFilter</filter-class>
    <init-param>
        <param-name>targetFilterLifecycle</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CrossDomainFilter</filter-name>
    <url-pattern>/*</url-pattern><!-- 配置允许跨域访问的的url-pattern -->
</filter-mapping>

到这里服务器就已经配置完毕了。

客户端

客户端直接使用ajax发起请求就可以:

  /**
   * 发起ajax请求
   * @param url 请求地址
   * @param data 请求参数(object)对象
   * @param fnScuss 成功回调的函数
   * @param fnError 失败回调的函数
   * @returns {{get: get, post: post}}
   */
  ajax: function (url, data, fnScuss, fnError) {
      
      var _cacheKey = app.md5(url+JSON.stringify(data));
      var _cache = null;
      var _isCanCache = app.isCanCache(url);
      url = this.constant.DOMAIN + url;

      var http = function (method,header) {
          if (method == null){
              method = "POST";
          }
          if(header == null){
              header = new Object();
          }
     
          $.ajax({
              url: url,
              data: data,
              dataType: "json",
              type: method,
              headers: header,
      beforeSend: function(xhr) {
         xhr.withCredentials = true;
      },
      crossDomain:true,
              success: function (e) {

                  if (typeof fnScuss == "function") {
                      //储存缓存
                      if (e.code == "1" && _isCanCache == true){
                          //app.cache.set(_cacheKey,e)
                      }
                      fnScuss(e);
                  }
              },
              error: function (e) {
                  if (typeof fnError == "function") {
                      fnError(e);
                  }
              }

          })
      };

      return {
          get: function () {
              //缓存判断
              if (_isCanCache == true){
                  _cache = app.cache.get(_cacheKey)
                  if (_cache != null && typeof fnScuss == "function"){
                      fnScuss(_cache);
                      return true;
                  }
              }

              http("GET");
          },
          post: function (isJson) {
              //缓存判断
              if (_isCanCache == true){
                  _cache = app.cache.get(_cacheKey)
                  if (_cache != null && typeof fnScuss == "function"){
                      fnScuss(_cache);
                      return true;
                  }
              }
              var header = new Object();
              if (isJson == true){
                  header['Content-Type'] = "application/json";
              }
              http("POST",header);
          },
          delete:function () {
              http("DELETE");
          },
          put:function () {
              http("PUT");
          }
      }

  },

 

app.event("#getToken", "click", function () {
    app.ajax("/project/api/getToken", {type:"1"}, function (e) {
        app.log(e);
        if (e.code == 1) {
            
        }
    }).post();
});

8种JavaScript思维导图

一、JavaScript思维导图之<变量>的学习

1489070795-9656-iom1i-lObTO-fuAAHnyukxd68504

二、    JavaScript思维导图之<函数基础>
1489070801-1544-iom1i-ldrzs8OUAAHstqsTcNk032

三、JavaScript思维导图之<基本dom操作>

1489070801-4695-iom1i-lnHjavFSAAMn6lGXylQ249

四、JavaScript思维导图之<流程语句>

1489070801-8094-ioL1i-lvLj4-aTAAMKdP9yCsY163

五、JavaScript思维导图之<数组>

1489070790-4496-ioL1i-l8DRZUXgAAPWo3NI-Qs124

六、    JavaScript思维导图之<运算符>

1489070802-5922-iom1i-l9PhBYSbAAaDvXV6gn8492

七、JavaScript思维导图之<正则表达式>

1489070801-3756-ioL1i-l-3j86f9AAOl8EVC5pk459

八、JavaScript思维导图之<字符串函数>

1489070802-6387-iom1i-mAOj-rjrAAWrNNAmaW4766

redis队列例子详解

测试的时候我用的是Win环境,目前Redis官方是没有Redis环境安装包下载,但是庆幸的是微软有团队在维护Redis WinX64环境的版本,下面是下载网址:

Redis Windows环境下载:
https://github.com/MSOpenTech/redis/releases

下载直接执行redis-server.exe即可

还需要PHP-redis.dll的插件,下载复制到ext目录下,并且在php.ini增加一行:

extension=php_redis.dll

使用的代码非常简单,以下是一个简单的使用类,如果实用在正式环境中,可能要需要进行优化:

class RedisEx{

private $_redis = null;
private $_host = “127.0.0.1”;
private $_prot = 6379;

function __construct(){
self::_connect();
}

public function push($key,$val){
self::_connect();

if($key&&$val){
return $this->_redis->lPush($key,$val);
}
return null;
}

public function pop($key) {
self::_connect();

return $this->_redis->rPop($key);
}

private function _connect(){
if(!$this->_redis){
$this->_redis = new Redis();
$this->_redis->connect($this->_host,$this->_prot);
}
}
}

 

有了处理类,那么我们需要写一个操作代码:

<?php
/**
* http://test.com/1.php?a=POST&key=key1&val=a0000001//加入队列
* http://test.com/1.php?a=GET&key=key1//取出队列
* @var unknown
*/
$action = $_GET[‘a’];

$redisEx = new RedisEx();

if(strtoupper($action) == ‘POST’){
$key = $_GET[‘key’];
$val = $_GET[‘val’];

$res = $redisEx->push($key, $val);

echo $res;

}elseif (strtoupper($action) == ‘GET’){

$key = $_GET[‘key’];

$res = $redisEx->pop($key);

echo $res;
}

echo ‘succ';

 

12319

关于深蓝

仅仅是一个对编程很有爱好的人.
Copyright © 2008-2016 lanxinbase.com Rights Reserved. | 粤ICP备14086738号 |