反射的核心就是加载类,解剖出类的各个组成部分 例如:成员变量 、方法 、构造方法!
加载类的三种方法
/提取当前类的 Class 对象。
方法1
Class claszz1=Class.forName("com.rain.demo.Person");
方法2
Class claszz2=Person.class;
方法3
Class claszz3=new Hero().getClass();
解剖类的常用方法
//返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
public Constructor<T> getConstructor(Class<?>... parameterTypes)
返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法
public Method getMethod(String name, Class<?>... parameterTypes)
//返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
public Field getField(String name)
//私有
public Field getDeclaredField(String name)
//私有
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
//返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定私有构造方法。
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
反射功能实际作用是用来开发框架如:spring
实例
Person.java
package com.rain.demo;
public class Person {
public String name="123";
public Person(){
System.out.println("person");
}
public Person(String name){
System.out.println("person name");
}
public Person(String name,int password){
System.out.println("person name password");
}
public void getString(){
System.out.println(name);
}
}
Demo1.java
package com.rain.demo;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.junit.Test;
public class Demo1 {
//反射新建类的对象
@Test
public void test1() throws NoSuchMethodException, SecurityException, ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
Class claszzClass = Class.forName("com.rain.demo.Person");
Constructor c = claszzClass.getConstructor(null);
Person p = (Person)c.newInstance(null);
System.out.println(p.name);
}
@Test
public void test2() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException{
//提取当前类的 Class 对象。
Class claszzClass1=Class.forName("com.rain.demo.Person");
//返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
Constructor c =claszzClass1.getConstructor(String.class);
//使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,
Person p = (Person)c.newInstance("xxxx");
System.out.println("test2");
System.out.println(p.name);
}
@Test
public void test3() throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException{
Person p = new Person();
Class claszzClass3=Class.forName("com.rain.demo.Person");
//
Method method = claszzClass3.getMethod("getString", null); //方法名 参数
method.invoke(p, null);
}
}
JSP动作元素在请求处理阶段实例化一个javaBean,并且提供了设置获取方法
在model中创建javaBean,(其实就是java中的类)关于此概念解释 -> 传送门
创建好Javabean 在jsp中请求调用的方法
在浏览器打开 http://127.0.0.1:8080/Test/person.jsp
Spring MVC就是一个MVC框架,个人觉得Spring MVC annotation式的开发比Struts2方便,可以直接代替上面的Struts(当然Struts的做为一个非常成熟的MVC,功能上感觉还是比Spring强一点,不过Spring MVC已经足够用了)。当然spring mvc的执行效率比struts高,是因为struts的值栈影响效率.以下是记录springMVC开发环境配置
首先下载jar包 :下载地址:http://repo.spring.io/release/org/springframework/spring/
spring 项目启动必须的依赖包 commons-logging-1.1.jar
第一步:在lib文件中添加jar包
第二步:修改web.xml 文件:详细介绍:https://www.cnblogs.com/shinejaie/p/5244258.html
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>SpringMVC</display-name>
<!--配置所有请求的拦截器 -->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置DispatcherServlet的一个初始化参数:配置springMVC的配置文件的位置和名称-->
<!-- 这里可以省略, 默认的配置文件为: /WEB-INF/<servlet-name>-servlet.xml-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/SpringMVC-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
第三步:添加spring-servlet.xml
首先需要用内网穿透工具 : 花生壳 .NAT123. ngrok
我使用的是ngrok :https://www.ngrok.cc/
将Tomcat 端口配置为80 (修改server.xml 配置文件) 可以百度Google方法
重启Tomcat 后发现端口改变 127.0.0.1:80
注册登录ngrok后,添加隧道,在本地运行ngrok 启动脚本设置好 隧道ID,然后访问隧道的域名出现正常的页面
则构建成功 可以配合Eclipse实现联合调试!
第一步:申请公众号测试接口
第二步:添加测试用户
第三步:添加消息模板
代码:获取动态ACCESS_TOKEN (有效期7200)
$appid='wxcfd6d103e4d5b35d';
$secret='60504239fe7597a9653b6272ae149369';
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appid&secret=$secret";
$token = getJson($url);
$access = $token["access_token"];
print_r($token);
print_r("\n");
发送模板消息
一定要注意json格式 ,否则会返回POST数据格式不正确
$url ="https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=".$access;
$data1 = '{
"touser":"o4f0Wv5nRBQMCzZ1AsDlq_9OsOrU",
"template_id":"HMnswJkdFHz_ZcINVzpuYE88PGMH20j4Rybr9BVfcjA",
"url":"http://www.rainfly.cn",
"data":{"frist":{"value":"提醒事件已经到了!","color":"#ff0000"}}
}';
function send_post($url, $post_data) {
$postdata = http_build_query($post_data);
$options = array(
'http' => array(
'method' => 'POST',
'header' => 'Content-type:application/x-www-form-urlencoded',
'content' => $post_data,
'timeout' => 15 * 60 // 超时时间(单位:s)
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
//file_put_contents('access.json', $result);
//print_r($result);
//return $result;
}
send_post($url, $data1);
测试截图
当用户调用一个 Servlet 时,就会创建一个 Servlet 实例,每一个用户请求都会产生一个新的线程,适当的时候移交给 doGet 或 doPost 方法。init() 方法简单地创建或加载一些数据,这些数据将被用于 Servlet 的整个生命周期。
由于常驻内存继而创建新的进程会出现资源的同步互斥现象;
Servlet: 同CGI程序 用来处理当前HTTP server交互数据
测试源码:
web.xml 文件中 指明项目访问路径 servlet-pattren 打开Tomcat 通过多开多个浏览器进行访问查看全局变量i的数值
全局变量在多线程访问时不断改变
需要将多个线程访问的资源加上锁,现在这种做法是给Servlet对象加了一把锁,保证任何时候都只有一个线程在访问该Servlet对象里面的资源,这样就不存在线程安全问题了
synchronized (this) { //Java中每个对象都有一把锁,这里的this指的就是servlet对象
response.setContentType("text/html");
i++;
String s=i+"";
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO: handle exception
e.printStackTrace();
}
response.getWriter().write(s);
}
首先需要安装pcntl_ 拓展
PHP -M 查看是否存在这两个文件
测试文件 test.php
<?php
header('content-type:text/html;charset=utf-8' );
// 必须加载扩展
if (!function_exists("pcntl_fork")) {
die("pcntl extention is must !");
}
$ppid = posix_getpid();
$pid = pcntl_fork();
printf("\n");
if ($pid == -1) {
throw new Exception('fork子进程失败!');
} elseif ($pid > 0) {
cli_set_process_title("我是父进程,我的进程id是{$ppid}."); //父进程名称
while (true)
{
echo "我是父进程 ID =".$ppid;
printf("\n");
sleep(3);
}
} else {
$cpid = posix_getpid();
cli_set_process_title("我是{$ppid}的子进程,我的进程id是{$cpid}.");//子进程名称
while (true)
{
echo "我是子进程 ID=".$cpid;
printf("\n");
sleep(3);
}
}
?>
运行PHP index.php就可以看到脚本线程的效果了
近期项目需要,研究一下GatewayWorker一款开源PHP。
使用数据库进行记录。
配置好开发环境。 http://doc2.workerman.net/326102
操作数据库 需要创建 /Config/Db.PHP 进行配置端口
配置文件如下:
<?php
namespace Config;
class Db
{
public static $db = array(
'host' => '127.0.0.1',
'port' => 3306,
'user' => 'root',
'password' => 'root',
'dbname' => 'db',
'charset' => 'utf8',
);
}
之所以在 /Config/Db.PHP 的namespace下面操作 是由于 /Lib/Db.PHP 文件中函数
public static function instance($config_name)
{
if (!isset(DbConfig::$$config_name)) {
echo "\\Config\\Db::$config_name not set\n";
throw new Exception("\\Config\\Db::$config_name not set\n");
}
if (empty(self::$instance[$config_name])) {
// $config_name 实际传递过来的字符串 组成了 $db 一个变量进行赋值
$config= DbConfig::$$config_name;
self::$instance[$config_name] = new DbConnection($config['host'], $config['port'],
$config['user'], $config['password'], $config['dbname']);
}
return self::$instance[$config_name];
}
继而在Event.PHP 文件中可以访问数据库进行操作
public static function onConnect($client_id) {
//通过config 连接数据库成功
$db = Db::instance('db');
//数据库插入语句
$db->query("INSERT INTO Persons VALUES ( 'admin', 'pass', 'w', 15)");
Gateway::sendToAll("$client_id login\n");
}
其中Event.PHP 需要包含
use \GatewayWorker\Lib\Db;
需求:编译安装QT 5.8.0 ARM +linux 版本
环境:Ubuntu 14.04 32bit
个人需要编译安装了 i386-linux-Qt5.8.0,
第一步:
下载文件
Qt官网下载:http://download.qt.io/archive/qt/
qt-opensource-linux-x64-5.8.0.run 这种类型是编译好的可以运行的x64位的i386的版本。
我们需要进入 single/ 内qt-everywhere-opensource-src-5.8.0.tar.xz 直接下载源码
我之前已经安装好了交叉编译工具
第二步
解压文件
找个英文目录,把qt-everywhere-opensource-src-5.8.0.tar.gz放进去。
用终端解压:tar -zxvf qt-everywhere-opensource-src-5.8.0.tar.gz
最好别右击“提取到此处”,这个解压好像和命令解压不同。
第三步:
修改编译配置文件:
vim qt-everywhere-opensource-src-5.8.0/qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf
(注意我的改动)
#
# qmake configuration for building with arm-linux-gnueabi-g++
#
MAKEFILE_GENERATOR = UNIX
CONFIG += incremental
QMAKE_INCREMENTAL_STYLE = sublib
include(../common/linux.conf)
include(../common/gcc-base-unix.conf)
include(../common/g++-unix.conf)
QT_QPA_DEFAULT_PLATFORM = linux #eglfs
QMAKE_CFLAGS += -O2 -march=armv7-a
QMAKE_CXXFLAGS += -O2 -march=armv7-a
# modifications to g++.conf
QMAKE_CC = arm-linux-gnueabi-gcc
QMAKE_CXX = arm-linux-gnueabi-g++
QMAKE_LINK = arm-linux-gnueabi-g++
QMAKE_LINK_SHLIB = arm-linux-gnueabi-g++
# modifications to linux.conf
QMAKE_AR = arm-linux-gnueabi-ar cqs
QMAKE_OBJCOPY = arm-linux-gnueabi-objcopy
QMAKE_NM = arm-linux-gnueabi-nm -P
QMAKE_STRIP = arm-linux-gnueabi-strip
load(qt_config)
注意:
这里指定了编译arm版qt所使用的编译器,与后期QtCreator项目的编译器是一样的。
如果你是用的是arm-none-linux-gnueabi-gcc,那么每一项都需要修改为arm-none-linux-gnueabi-。
#这里提前解释一下,第三步中已经指定好了编译器版本,所以第四步不需要指定了。
#第四步中的-xplatform linux-arm-gnueabi-g++是对应qmake.conf所在的文件夹,代表了编译的Qt库的版本。
第四步:
配置编译参数,用./configre -help 可以查看参数。
我的配置是(去除掉了一些用不到的选项):
./configure -release -opensource -confirm-license -xplatform linux-arm-gnueabi-g++ -prefix /usr/local/qt5.8-nomake examples -no-opengl -no-iconv -silent -qpa linuxfb -no-gtk -qt-libjpeg -qt-libpng
注意:
1、-xplatform linux-arm-gnueabi-g++ ,指定了编译Arm版的QT库;
2、-prefix后面的配置为qt库需要安装的位置,这个需要根据你的安装位置自己指定。(如果不指定默认的安装位置是 /usr/local/Qtxxx)
第五步:
如果上面配置没有问题,接下来make:
$make
或者
$make -j2 /CPU 几个核可以使用“-j几”,核多编的快*/
第六步:
安装:$sudo make install
在这里加sudo是因为,安装时会将库文件复制到上面第四步配置的安装目录( /usr/local/qt5.8)。
usr目录是需要root权限的。
好了,这是编译Qt5.8.0的过程。
编译平台插件:
由于Qt5以后,删除了嵌入式的QWS(Qt windows system-Qt窗体系统)换成QPA(Qt Platform Abstration -Qt平台抽象),平台插件在qt-everywhere-opensource-src-5.8.0/qtbase/src/plugins/platforms/下面。
有各种平台的插件,基于frambuffer的插件是lunuxfb这个文件夹下,其他的还有android、ios、winrt、windows等等,需要什么平台的编译就是了。
平台是基于Windows 10 x64、QT 5.8.0 编译环境
数据库操作要点 注意数据库
1.要将mysql中 mysql\libmysql.dll文件复制到\Qt\Qt5.8.0\5.8\mingw53_32\bin中
2.
// 打开MySQL
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL"); //需要打开那个数据库,必须选择驱动
db.setHostName("localhost"); //查看帮助文档
db.setDatabaseName("mydata");
db.setUserName("root");
db.setPassword("");
3.
在此文章之前已经使用和分析过mosquito作为 broker开放 1883和9001端口的MQTT功能,现在测试使用emqtt,且深入研究websocket的作用实现。
测试环境是 Ubuntu14.04 x64 位直接下载
安装步骤:
# 启动emqttd
./bin/emqttd start
# 检查运行状态
./bin/emqttd_ctl status
# 停止emqttd
./bin/emqttd stop
web控制台默认端口 18083(阿里云服务器需要在安全策略组中开放端口)
启动成功后登陆后台:查看websocket连接是否成功,检查端口8083和1883是否打开
具体配置emqtt: http://www.emqtt.com/docs/v2/config.html#
搭建完成后调试websocket功能;
本地搭建好web服务器: http://www.rainfly.cn/?post=257
加入调试文件
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.min.js" type="text/javascript"></script>
<title>websocket</title>
<script type="text/javascript">
client = new Paho.MQTT.Client("60.205.191.68", Number(8083), "");//建立客户端实例
function MqttConnect() {
client.connect({onSuccess:onConnect});//连接服务器并注册连接成功处理事件
function onConnect() { // 连接成功的回调函数
console.log("onConnected");
client.subscribe("rain");//订阅主题
}
}
client.onConnectionLost = onConnectionLost;//注册连接断开处理事件
function onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0) {
console.log("onConnectionLost:"+responseObject.errorMessage);
console.log("连接已断开");
}
}
//接收消息
client.onMessageArrived = onMessageArrived;//注册消息接收处理事件
function onMessageArrived(message) {
//console.log("收到消息:"+message.payloadString);
console.log("收到消息:"+message.payloadBytes[0]);
}
//发送消息
message = new Paho.MQTT.Message("hello");
message.destinationName = "rain";
client.send(message);
</script>
</head>
<body>
<div id="sse">
<a href="javascript:MqttConnect()">运行 WebSocket</a>
</div>
</body>
</html>
通过加入断点进行调试