java&matlab

This commit is contained in:
yinkanglong_lab
2021-03-09 20:12:44 +08:00
parent 07485a7f54
commit 99855cd76c
145 changed files with 6292 additions and 0 deletions

2
Java/JDK阅读/java.md Normal file
View File

@@ -0,0 +1,2 @@
\|
具体应该参考相应的jdk进行了解相应的方法。这里只说明类的主要作用和自己的相关理解以及部分常用的方法。

View File

@@ -0,0 +1,370 @@
**引**
如果对什么是线程、什么是进程仍存有疑惑请先Google之因为这两个概念不在本文的范围之内。
用多线程只有一个目的那就是更好的利用cpu的资源因为所有的多线程代码都可以用单线程来实现。说这个话其实只有一半对因为反应“多角色”的程序代码最起码每个角色要给他一个线程吧否则连实际场景都无法模拟当然也没法说能用单线程来实现比如最常见的“生产者消费者模型”。
很多人都对其中的一些概念不够明确,如同步、并发等等,让我们先建立一个数据字典,以免产生误会。
- 多线程:指的是这个程序(一个进程)运行时产生了不止一个线程
- 并行与并发:
- 并行多个cpu实例或者多台机器同时执行一段处理逻辑是真正的同时。
- 并发通过cpu调度算法让用户看上去同时执行实际上从cpu操作层面不是真正的同时。并发往往在场景中有公用的资源那么针对这个公用的资源往往产生瓶颈我们会用TPS或者QPS来反应这个系统的处理能力。
![a468b2694253.png](media/7932f8d9c5acc2d3a1896b4c3233612e.png)
并发与并行
- 线程安全经常用来描绘一段代码。指在并发的情况之下该代码经过多线程使用线程的调度顺序不影响任何结果。这个时候使用多线程我们只需要关注系统的内存cpu是不是够用即可。反过来线程不安全就意味着线程的调度顺序会影响最终结果如不加事务的转账代码
void transferMoney(User from, User to, float amount){
to.setMoney(to.getBalance() + amount); from.setMoney(from.getBalance() -
amount); }
- 同步Java中的同步指的是通过人为的控制和调度保证共享资源的多线程访问成为线程安全来保证结果的准确。如上面的代码简单加入@synchronized关键字。在保证结果准确的同时,提高性能,才是优秀的程序。线程安全的优先级高于性能。
好了,让我们开始吧。我准备分成几部分来总结涉及到多线程的内容:
1. 扎好马步:线程的状态
2. 内功心法:每个对象都有的方法(机制)
3. 太祖长拳:基本线程类
4. 九阴真经:高级多线程控制类
**扎好马步:线程的状态**
先来两张图:
![5b75b44e972c.png](media/c5008c69466298cf4ed608e4f6b569f0.png)
线程状态
![7101e6588094.png](media/995e20b243fa0e000d51589ebb780e75.png)
线程状态转换
各种状态一目了然,值得一提的是"blocked"这个状态:
线程在Running的过程中可能会遇到阻塞(Blocked)情况
1. 调用join()和sleep()方法sleep()时间结束或被打断join()中断,IO完成都会回到Runnable状态等待JVM的调度。
2. 调用wait(),使该线程处于等待池(wait blocked
pool),直到notify()/notifyAll(),线程被唤醒被放到锁定池(lock blocked pool
)释放同步锁使线程回到可运行状态Runnable
3. 对Running状态的线程加同步锁(Synchronized)使其进入(lock blocked pool
),同步锁被释放进入可运行状态(Runnable)。
此外在runnable状态的线程是处于被调度的线程此时的调度顺序是不一定的。Thread类中的yield方法可以让一个running状态的线程转入runnable。
**内功心法:每个对象都有的方法(机制)**
synchronized, wait, notify 是任何对象都具有的同步工具。让我们先来了解他们
![0771d68cb2ba.png](media/51d56de3dfb3391d64c34cc5121e3bd0.png)
monitor
他们是应用于同步问题的人工线程调度工具。讲其本质首先就要明确monitor的概念Java中的每个对象都有一个监视器来监测并发代码的重入。在非多线程编码时该监视器不发挥作用反之如果在synchronized
范围内,监视器发挥作用。
wait/notify必须存在于synchronized块中。并且这三个关键字针对的是同一个监视器某对象的监视器。这意味着wait之后其他线程可以进入同步块执行。
当某代码并不持有监视器的使用权时如图中5的状态即脱离同步块去wait或notify会抛出java.lang.IllegalMonitorStateException。也包括在synchronized块中去调用另一个对象的wait/notify因为不同对象的监视器不同同样会抛出此异常。
再讲用法:
- synchronized单独使用
- 代码块如下在多线程环境下synchronized块中的方法获取了lock实例的monitor如果实例相同那么只有一个线程能执行该块内容
![copycode.gif](media/51e409b11aa51c150090697429a953ed.gif)
复制代码
public class Thread1 implements Runnable { Object lock; public void run() {
synchronized(lock){ ..do something } } }
![copycode.gif](media/51e409b11aa51c150090697429a953ed.gif)
复制代码
- 直接用于方法:
相当于上面代码中用lock来锁定的效果实际获取的是Thread1类的monitor。更进一步如果修饰的是static方法则锁定该类所有实例。
public class Thread1 implements Runnable { public synchronized void run() { ..do
something } }
- synchronized, wait, notify结合:典型场景生产者消费者问题
![copycode.gif](media/51e409b11aa51c150090697429a953ed.gif)
复制代码
/\*\* \* 生产者生产出来的产品交给店员 \*/ public synchronized void produce() {
if(this.product \>= MAX_PRODUCT) { try { wait();
System.out.println("产品已满,请稍候再生产"); } catch(InterruptedException e) {
e.printStackTrace(); } return; } this.product++;
System.out.println("生产者生产第" + this.product + "个产品."); notifyAll();
//通知等待区的消费者可以取出产品了 } /\*\* \* 消费者从店员取产品 \*/ public
synchronized void consume() { if(this.product \<= MIN_PRODUCT) { try { wait();
System.out.println("缺货,稍候再取"); } catch (InterruptedException e) {
e.printStackTrace(); } return; } System.out.println("消费者取走了第" +
this.product + "个产品."); this.product--; notifyAll();
//通知等待去的生产者可以生产产品了}
![copycode.gif](media/51e409b11aa51c150090697429a953ed.gif)
复制代码
**volatile**
多线程的内存模型main memory主存、working
memory线程栈在处理数据时线程会把值从主存load到本地栈完成操作后再save回去(volatile关键词的作用每次针对该变量的操作都激发一次load
and save)。
![6cfda7042c67.png](media/54db549dedb71c1ac0e24d21fa81faf4.png)
volatile
针对多线程使用的变量如果不是volatile或者final修饰的很有可能产生不可预知的结果另一个线程修改了这个值但是之后在某线程看到的是修改之前的值。其实道理上讲同一实例的同一属性本身只有一个副本。但是多线程是会缓存值的本质上volatile就是不去缓存直接取值。在线程安全的情况下加volatile会牺牲性能。
**太祖长拳:基本线程类**
基本线程类指的是Thread类Runnable接口Callable接口
Thread 类实现了Runnable接口启动一个线程的方法
MyThread my = new MyThread(); my.start();
**Thread类相关方法**
![copycode.gif](media/51e409b11aa51c150090697429a953ed.gif)
复制代码
//当前线程可转让cpu控制权让别的就绪状态线程运行切换public static
Thread.yield() //暂停一段时间public static Thread.sleep()
//在一个线程中调用other.join(),将等待other执行完后才继续本线程。 public join()
//后两个函数皆可以被打断public interrupte()
![copycode.gif](media/51e409b11aa51c150090697429a953ed.gif)
复制代码
**关于中断**它并不像stop方法那样会中断一个正在运行的线程。线程会不时地检测中断标识位以判断线程是否应该被中断中断标识值是否为true。终端只会影响到wait状态、sleep状态和join状态。被打断的线程会抛出InterruptedException。
Thread.interrupted()检查当前线程是否发生中断返回boolean
synchronized在获锁的过程中是不能被中断的。
中断是一个状态interrupt()方法只是将这个状态置为true而已。所以说正常运行的程序不去检测状态就不会终止而wait等阻塞方法会去检查并抛出异常。如果在正常运行的程序中添加while(!Thread.interrupted())
,则同样可以在中断后离开代码体
**Thread类最佳实践**
写的时候最好要设置线程名称 Thread.name并设置线程组
ThreadGroup目的是方便管理。在出现问题的时候打印线程栈 (jstack -pid)
一眼就可以看出是哪个线程出的问题,这个线程是干什么的。
**如何获取线程中的异常**
![5b7f8df6e8d3.png](media/429f749d3870e8c9a198746da0d0ca6e.png)
不能用try,catch来获取线程中的异常
**Runnable**
与Thread类似
**Callable**
future模式并发模式的一种可以有两种形式即无阻塞和阻塞分别是isDone和get。其中Future对象用来存放该线程的返回值以及状态
ExecutorService e = Executors.newFixedThreadPool(3);
//submit方法有多重参数版本及支持callable也能够支持runnable接口类型.Future
future = e.submit(new myCallable()); future.isDone() //return true,false 无阻塞
future.get() // return 返回值,阻塞直到该线程运行结束
**九阴真经:高级多线程控制类**
以上都属于内功心法接下来是实际项目中常用到的工具了Java1.5提供了一个非常高效实用的多线程包:*java.util.concurrent*,
提供了大量高级工具,可以帮助开发者编写高效、易维护、结构清晰的Java多线程程序。
**1.ThreadLocal类**
用处保存线程的独立变量。对一个线程类继承自Thread)
当使用ThreadLocal维护变量时ThreadLocal为每个使用该变量的线程提供独立的变量副本所以每一个线程都可以独立地改变自己的副本而不会影响其它线程所对应的副本。常用于用户登录控制如记录session信息。
实现每个Thread都持有一个TreadLocalMap类型的变量该类是一个轻量级的Map功能与map一样区别是桶里放的是entry而不是entry的链表。功能还是一个map。以本身为key以目标为value。
主要方法是get()和set(T a)set之后在map里维护一个threadLocal -\>
aget时将a返回。ThreadLocal是一个特殊的容器。
**2.原子类AtomicInteger、AtomicBoolean……**
如果使用atomic wrapper
class如atomicInteger或者使用自己保证原子的操作则等同于synchronized
//返回值为booleanAtomicInteger.compareAndSet(int expect,int update)
该方法可用于实现乐观锁考虑文中最初提到的如下场景a给b付款10元a扣了10元b要加10元。此时c给b2元但是b的加十元代码约为
![copycode.gif](media/51e409b11aa51c150090697429a953ed.gif)
复制代码
if(b.value.compareAndSet(old, value)){ return ; }else{ //try again // if that
fails, rollback and log}
![copycode.gif](media/51e409b11aa51c150090697429a953ed.gif)
复制代码
**AtomicReference**
对于AtomicReference 来讲也许对象会出现属性丢失的情况即oldObject ==
current但是oldObject.getPropertyA != current.getPropertyA。
这时候AtomicStampedReference就派上用场了。这也是一个很常用的思路即加上版本号
**3.Lock类**
lock: 在java.util.concurrent包内。共有三个实现
ReentrantLock ReentrantReadWriteLock.ReadLock ReentrantReadWriteLock.WriteLock
主要目的是和synchronized一样
两者都是为了解决同步问题,处理资源争端而产生的技术。功能类似但有一些区别。
区别如下:
![copycode.gif](media/51e409b11aa51c150090697429a953ed.gif)
复制代码
lock更灵活可以自由定义多把锁的枷锁解锁顺序synchronized要按照先加的后解顺序
提供多种加锁方案lock 阻塞式, trylock 无阻塞式, lockInterruptily 可打断式,
还有trylock的带超时时间版本。 本质上和监视器锁即synchronized是一样的
能力越大,责任越大,必须控制好加锁和解锁,否则会导致灾难。 和Condition类的结合。
性能更高,对比如下图:
![copycode.gif](media/51e409b11aa51c150090697429a953ed.gif)
复制代码
![93b31bfed934.png](media/4c9b2a5287c91f386c9db0ba1920904b.png)
synchronized和Lock性能对比
**ReentrantLock**
可重入的意义在于持有锁的线程可以继续持有,并且要释放对等的次数后才真正释放该锁。
使用方法是:
1.先new一个实例
static ReentrantLock r=new ReentrantLock();
2.加锁
r.lock()或r.lockInterruptibly();
此处也是个不同后者可被打断。当a线程lock后b线程阻塞此时如果是lockInterruptibly那么在调用b.interrupt()之后b线程退出阻塞并放弃对资源的争抢进入catch块。如果使用后者必须throw
interruptable exception 或catch
3.释放锁
r.unlock()
必须做何为必须做呢要放在finally里面。以防止异常跳出了正常流程导致灾难。这里补充一个小知识点finally是可以信任的经过测试哪怕是发生了OutofMemoryErrorfinally块中的语句执行也能够得到保证。
**ReentrantReadWriteLock**
可重入读写锁(读写锁的一个实现)
ReentrantReadWriteLock lock = new ReentrantReadWriteLock() ReadLock r =
lock.readLock(); WriteLock w = lock.writeLock();
两者都有lock,unlock方法。写写写读互斥读读不互斥。可以实现并发读的高效线程安全代码
**4.容器类**
这里就讨论比较常用的两个:
BlockingQueue ConcurrentHashMap
**BlockingQueue**
阻塞队列。该类是java.util.concurrent包下的重要类通过对Queue的学习可以得知这个queue是单向队列可以在队列头添加元素和在队尾删除或取出元素。类似于一个管
特别适用于先进先出策略的一些应用场景。普通的queue接口主要实现有PriorityQueue优先队列有兴趣可以研究
BlockingQueue在队列的基础上添加了多线程协作的功能
![7b06b8d86db8.png](media/6cb91c2845273c5693a564bab023d4e3.png)
BlockingQueue
除了传统的queue功能表格左边的两列之外还提供了阻塞接口put和take带超时功能的阻塞接口offer和poll。put会在队列满的时候阻塞直到有空间时被唤醒take在队
列空的时候阻塞,直到有东西拿的时候才被唤醒。用于生产者-消费者模型尤其好用,堪称神器。
常见的阻塞队列有:
ArrayListBlockingQueue LinkedListBlockingQueue DelayQueue SynchronousQueue
**ConcurrentHashMap**
高效的线程安全哈希map。请对比hashTable , concurrentHashMap, HashMap
**5.管理类**
管理类的概念比较泛,用于管理线程,本身不是多线程的,但提供了一些机制来利用上述的工具做一些封装。
了解到的值得一提的管理类ThreadPoolExecutor和 JMX框架下的系统级管理类
ThreadMXBean
**ThreadPoolExecutor**
如果不了解这个类应该了解前面提到的ExecutorService开一个自己的线程池非常方便
![copycode.gif](media/51e409b11aa51c150090697429a953ed.gif)
复制代码
ExecutorService e = Executors.newCachedThreadPool(); ExecutorService e =
Executors.newSingleThreadExecutor(); ExecutorService e =
Executors.newFixedThreadPool(3); //
第一种是可变大小线程池,按照任务数来分配线程, //
第二种是单线程池相当于FixedThreadPool(1) // 第三种是固定大小线程池。 //
然后运行e.execute(new MyRunnableImpl());
![copycode.gif](media/51e409b11aa51c150090697429a953ed.gif)
复制代码
该类内部是通过ThreadPoolExecutor实现的掌握该类有助于理解线程池的管理本质上他们都是ThreadPoolExecutor类的各种实现版本。请参见javadoc
![8a70ba646843.png](media/ec7fd9666c2bd70bfc26c6c2a1f7538a.png)
ThreadPoolExecutor参数解释
翻译一下:
![copycode.gif](media/51e409b11aa51c150090697429a953ed.gif)
复制代码
corePoolSize:池内线程初始值与最小值,就算是空闲状态,也会保持该数量线程。
maximumPoolSize:线程最大值,线程的增长始终不会超过该值。
keepAliveTime当池内线程数高于corePoolSize时经过多少时间多余的空闲线程才会被回收。回收前处于wait状态
unit 时间单位可以使用TimeUnit的实例如TimeUnit.MILLISECONDS
workQueue:待入任务Runnable的等待场所该参数主要影响调度策略如公平与否是否产生饿死(starving)
threadFactory:线程工厂类有默认实现如果有自定义的需要则需要自己实现ThreadFactory接口并作为参数传入。

View File

@@ -0,0 +1 @@
以功能为单位进行记录。主要说明实现某个具体功能时用到的相关类。以及类的主要用法。

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,56 @@
# DAO模式的原理说明
DAO(Data Access
Object)是一个数据访问接口,数据访问:顾名思义就是与数据库打交道,夹在业务逻辑与数据库资源中间。
在核心J2EE模式中DAO的定义是为了建立一个健壮的J2EE应用应该将所有对数据源的访问操作抽象封装在一个公共API中。用程序设计的语言来说就是建立一个接口接口中定义了此应用程序中将会用到的所有事务方法。在这个应用程序中当需要和数据源进行交互的时候则使用这个接口并且编写一个单独的类来实现这个接口在逻辑上对应这个特定的数据存储。
DAO层本质上就是MVC中的Model部分的具体实现。相当于整个工程的javabean实现了对数据库的增删查改。
![dao.jpg](media/896ddc649ace2c4d5b318d11c887ece9.jpeg)
# DAO模式的具体实现
\-VO类提供javabean表示数据库中的一条记录主要有getter和setter方法
\-DAO类提供了DAOmodel的接口供控制器调用
\-DAOimplement实现了DAO类提供的外部接口主要是通过jdbc链接数据库实现了数据库的增删查改操作。
\-DAOFactory通过工厂类获取一个DAO的实例化对象。
在当前的工程中分别对应一下包:
.domain
.dao
.dao.impl
.service.impl
这四个类分别代daobean,dao接口,dao的jdbc实现,dao的工厂类在这里实现工程需要的所有的数据库的操作提供给其他部分调用。
最根本的事通过jdbcUtils提供了访问数据库的链接
逻辑结构非常清晰明显
# 最后说明dao的工作原理
![dao2.jpg](media/0df06acb323561f7014fed6f60125206.jpeg)
关于到的层级在此说明
数据库数据存储
\|-jdbc提供数据库的链接
\|-daoBean数据保存
\|-daoImpl的具体实现
\|-dao提供数据库访问的接口
\|-daoFactory实例化数据库的接口提供具体的数据操作
控制器数据操作需求

View File

@@ -0,0 +1,9 @@
java本身就是一个依赖各种库来构建工程的语言实际上需要自己写的东西并不多就是调用各种已经编辑好的库来实现各自的功能。
大部分库都是由jre/jdk内部自带的java库提供的。包括各种不同的版本导入的时候必须要注意可能是1.61.71.8等。
在做javaEE开发过程中部分依赖的网络编程的库org.apache.\*是由Tomcat服务器插件提供的
在实现软件测试的过程中junit4相关的库是由第三方插件提供也就是说在构建工程的时候下载了eclemma插件提供了org.junit.\*库和junit.\*库。并且提供了net.mooctest.plugin.\*库实现与mooctest的网站的交互。
所以在构建工程过程中必须得考虑相关库的导入。可能是来自于jdk/jre的官方标准库也可能是来自于其他特定功能的库tomcat也许是来自相关插件的库如adt插件、eclemma插件、junit4插件等。

View File

@@ -0,0 +1,15 @@
服务器端:
java Servlet
资源配置文件
与前端结合:
jspjava脚本直接在前端页面jsp嵌入前端脚本实现动态化。
jspjsp标签使用jsp标签来实现基础的控制
jspEL表达式使用简化的表达式实现动态数据获取
jsptag标签包括标准标签库和自定义标签库的使用。

View File

@@ -0,0 +1,11 @@
jsp代码编写属于后端因为前端开发看不懂JSP代码他们追求的是网页效果。而JSP其实就是JAVA代码来拼接前端页面而已本身也是Servlet因此JAVA
WEB工程师也要学习一些HTMLJSCSS等实际开法中前端工程师写好网页Java
web开发人员负责填写JSP脚本也可以反过来后端定义好标签库让前端以标签的方式来写代码。但近年来大部分项目都是用Ajax来调用后端接口了做到前后分离直接写JSP的少了。
作者:清浅池塘
链接https://www.zhihu.com/question/52695070/answer/228804504
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

View File

@@ -0,0 +1,11 @@
## JSP的内置对象
request对象
通过from表单能够发送GET和POST方法的Request。
request.getParameter("name"):得到键值对的值
request.setCharacterEncoding(utf-8);解决编码问题
getProtocol

View File

@@ -0,0 +1,120 @@
# -*- coding: utf-8 -*-
import queue
import re
import urllib2
import time
import urllib2
headers=("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36")
opener=urllib2.build_opener()
opener.addheaders=[headers]
#global the opener
urllib2.install_opener(opener)
listurl=[]
#use the procy server
def use_proxy(proxy_addr,url):
try:
import urllib2
data = urllib2.urlopen(url).read().decode('utf-8')
return data
except urllib2.URLError as e:
if hasattr(e,"code"):
print(e.code)
if hasattr(e,"reason"):
print(e.reason)
time.sleep(10)
except Exception as e:
print("exception:"+str(e))
time.sleep(1)
# get the picture
def craw(url,number):
html1=urllib2.urlopen(url).read().decode('utf-8')
html1=html1
pat1='<tr><td class="contentstyle54611">(.*?)</body></html>'
result1=re.compile(pat1,re.S).findall(html1)
result1=result1[0]
pat2='<IMG border="0" src="(.*?).jpg"'
imagelist=re.compile(pat2,re.S).findall(result1)
x=1;
for imageurl in imagelist:
imagename="E:/hello/"+str(x)+str(number)+".jpg"
imageurl = imageurl.replace('../../', "")
imageurl = "http://zdhxy.nwpu.edu.cn/" + imageurl+'.jpg'
try:
urllib2.urlretrieve(imageurl,filename=imagename)
except urllib2.URLError as e:
if hasattr(e, "code"):
print(e.code)
if hasattr(e, "reason"):
print(e.reason)
x+=1;
#get the content through the link
def getcontent(listurl,proxy):
i=0
#set local files's html code
html1='''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://
www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>computer</title>
</head>
<body>'''
fh=open("E:/hello/2.html","wb")
fh.write(html1.encode("utf-8"))
fh.close()
fh=open("E:/hello/2.html","ab")
for i in range(0,len(listurl)):
for j in range(0,len(listurl[i])):
try:
url=listurl[i][j]
url=url.replace("\"","")
url = url.replace('../', "")
url="http://jsj.nwpu.edu.cn/"+url
data2=use_proxy(proxy,url)
craw(url,j)
titlepat='<title>(.*?)</title>'
contentpat='<tr><td class="contentstyle54611">(.*?)</body></html>'
title=re.compile(titlepat).findall(data2)
content=re.compile(contentpat,re.S).findall(data2)
thistitle=" "
thiscontent=" "
if(title!=[]):
thistitle=title[0]
if(content!=[]):
thiscontent=content[0]
dataall="<p>title is :"+thistitle+"</p><p>content is :"+thiscontent+"</p><br>"
fh.write(dataall.encode("utf-8"))
print(""+str(i)+"第个网站"+str(j)+"次处理")
except urllib2.URLError as e:
if hasattr(e, "code"):
print(e.code)
if hasattr(e, "reason"):
print(e.reason)
time.sleep(10)
except Exception as e:
print("exception:" + str(e))
time.sleep(1)
fh.close()
html2='''</body>
</html>
'''
fh=open("E:/hello/2.html","ab")
fh.write(html2.encode("utf-8"))
fh.close()
proxy="123.145.128.139:8118"
pagestart=1
pageend=2
url="http://jsj.nwpu.edu.cn/index/xyxw.htm"
data1=use_proxy(proxy,url)
listurlpat='<a class="c54630" href="(.*?)"'
listurl.append(re.compile(listurlpat,re.S).findall(data1))
getcontent(listurl,proxy)
#print(title);
#listurl=getlisturl(key,pagestart,pageend,proxy)
#getcontent(listurl,proxy)

View File

@@ -0,0 +1,157 @@
JDBC操作数据库的基本步骤
1加载注册数据库驱动到JVM
2建立获取数据库连接。
3创建获取数据库操作对象。
4定义操作的SQL语句。
5执行数据库操作。
6获取并操作结果集。
7关闭对象回收数据库资源关闭结果集--\>关闭数据库操作对象--\>关闭连接)。
**[java]** [view plain](http://blog.csdn.net/hpu_a/article/details/51354867)
[copy](http://blog.csdn.net/hpu_a/article/details/51354867)
1. **package** com.yangshengjie.jdbc;
2. **import** java.sql.Connection;
3. **import** java.sql.DriverManager;
4. **import** java.sql.ResultSet;
5. **import** java.sql.SQLException;
6. **import** java.sql.Statement;
7.
8. **public** **class** JDBCTest {
9. /\*\*
10. \* 使用JDBC连接并操作mysql数据库
11. \*/
12. **public** **static** **void** main(String[] args) {
13. // 数据库驱动类名的字符串
14. String driver = "com.mysql.jdbc.Driver";
15. // 数据库连接串
16. String url = "jdbc:mysql://127.0.0.1:3306/jdbctest";
17. // 用户名
18. String username = "root";
19. // 密码
20. String password = "mysqladmin";
21. Connection conn = **null**;
22. Statement stmt = **null**;
23. ResultSet rs = **null**;
24. **try** {
25. // 1、加载数据库驱动
成功加载后会将Driver类的实例注册到DriverManager类中
26. Class.forName(driver );
27. // 2、获取数据库连接
28. conn = DriverManager.getConnection(url, username, password);
29. // 3、获取数据库操作对象
30. stmt = conn.createStatement();
31. // 4、定义操作的SQL语句
32. String sql = "select \* from user where id = 100";
33. // 5、执行数据库操作
34. rs = stmt.executeQuery(sql);
35. // 6、获取并操作结果集
36. **while** (rs.next()) {
37. System.out.println(rs.getInt("id"));
38. System.out.println(rs.getString("name"));
39. }
40. } **catch** (Exception e) {
41. e.printStackTrace();
42. } **finally** {
43. // 7、关闭对象回收数据库资源
44. **if** (rs != **null**) { //关闭结果集对象
45. **try** {
46. rs.close();
47. } **catch** (SQLException e) {
48. e.printStackTrace();
49. }
50. }
51. **if** (stmt != **null**) { // 关闭数据库操作对象
52. **try** {
53. stmt.close();
54. } **catch** (SQLException e) {
55. e.printStackTrace();
56. }
57. }
58. **if** (conn != **null**) { // 关闭数据库连接对象
59. **try** {
60. **if** (!conn.isClosed()) {
61. conn.close();
62. }
63. } **catch** (SQLException e) {
64. e.printStackTrace();
65. }
66. }
67. }
68. }
69. }

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -0,0 +1 @@
不能用过度的MVC框架的知识来理解简单的jsp页面怎么说现在写的jsp的级别就是将这些内容组合起来一个页面与另一个页面杂糅式的交互。起始php与python这种直接接触框架的学习反而非常不好。有时间多做东西救火啊提高效率。才能有更多的理解。

View File

@@ -0,0 +1,55 @@
# 序列化
对序列化的理解
JAVA序列化是指把JAVA对象转换为字节序列的过程。JAVA反序列化是吧字节恢复为JAVA对象。
应用:当两个进程进行远程通信时,可以相互发送各种类型的数据。包括文本、图片、音频、视频,这些数据都是以二进制序列的形式在网络上传送。
两个JAVA进程通信的时候也可以传送对象将JAVA序列化为字节序列装载为字节流然后进行传送。.接收端将字节流反序列化为JAVA对象。
作用:实现了数据的持久化,通过序列化,能够将数据永久的保存到硬盘上。利用序列化可以实现数据流的输入输出和远程通信。
实现方法:
java.io.ObjectOuptutStream:对象输出流writeObject()
java.io.ObjectInputStream:对象输入流readObject()
对象能被序列化的要求
implement了Serializable接口通过默认的方法进行序列化
implement了Serializable接口并且实现了相应的方法然后通过自己的方式进行序列化和反序列化
序列化的步骤:
步骤一:创建一个对象输出流,它可以包装一个其它类型的目标输出流,如文件输出流:
ObjectOutputStream out = new ObjectOutputStream(new
fileOutputStream(“D:\\\\objectfile.obj”));
步骤二通过对象输出流的writeObject()方法写对象:
out.writeObject(“Hello”);
out.writeObject(new Date());
反序列化的步骤:
步骤一:创建一个对象输入流,它可以包装一个其它类型输入流,如文件输入流:
ObjectInputStream in = new ObjectInputStream(new
fileInputStream(“D:\\\\objectfile.obj”));
步骤二通过对象输出流的readObject()方法读取对象:
String obj1 = (String)in.readObject();
Date obj2 = (Date)in.readObject();
# transient关键字说明
可以理解为瞬态、不可序列化。
简单的说truansient 变量就是在对象序列化的过程中没有被序列化变量。

View File

@@ -0,0 +1,27 @@
![968033-20160622111445922-1688525852.png](media/033dc67bcd465edb89b52cc8d9bdd5c1.png)
使用appium的原理及过程说明:
运行测试脚本的电脑我们称为Client。
打开Appium就开启了Appium Server默认监听4723端口。
Appium
Server接收到Client命令测试脚本翻译成测试机器可以理解的语言然后发送给测试机器运行。
测试机器运行结束后再把测试结果返回给Appium Server之后Appium
Server再把测试结果返回给Client。
![appium.jpg](media/4f52e7856884d1457ab7d1867caab247.jpeg)
1.appium是c/s模式的
2.appium是基于webdriver协议添加对移动设备自动化api扩展而成的所以具有和webdriver一样的特性比如多语言支持
3.webdriver是基于http协议的第一连接会建立一个session会话并通过post发送一个json告知服务端相关测试信息
4.对于android来说4.2以后是基于uiautomator框架实现查找注入事件的4.2以前则是instrumentation框架的并封装成一个叫Selendroid这玩意提供服务
5.客户端只需要发送http请求实现通讯意味着客户端就是多语言支持的
6.appium服务端是node.js写的所以你安装的时候无论哪个平台都是先装node

View File

@@ -0,0 +1,96 @@
WEB-INF web.xml
文件用来配置整个工程。
\<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4"\>
\<servlet\>
\<servlet-name\>FirstServlet\</servlet-name\>
\<servlet-class\>lesson.j2ee.ex1.FirstServlet\</servlet-class\>
\</servlet\>
\<servlet-mapping\>
\<servlet-name\>FirstServlet\</servlet-name\>
\<url-pattern\>/Serv1\</url-pattern\>
\</servlet-mapping\>
\</web-app\>
也许讲过但是感觉从来没有学过怎么开发知识知道Javaservlet的一些基础理论知识真的需要学习一下这方面的东西了。如何真正的使用Java开发一个工程。
Servlet通过回调函数管理自己的生命周期
init()-\>初始化
sevice()-\>提供servlet服务。
\-doGet()用于相应GET方法的函数HTTPSevlet类中实现
\-doPost()用于响应POST方法的函数HTTPSevlet类中实现
\-doHead()用于响应HEAD方法的函数HTTPSevlet类中实现。
destroy()-\>销毁
getServletConfig()用来获取Servlet配置信息。
getSeviceInfo()用来获取其他信息。
关于Servlet的继承关系必须知道每一级继承都实现了什么玩意。
Servlet \<-- GenericServlet \<-- HttpServlet \<--- MyServlet
关于servlet中常用到的两个对象
ServletConfig对象
每个servlet都有一个ServletConfig对象用于向servlet传递部署时的信息用于访问ServletContext其参数在DD中配置
ServletContext对象
每个web应用都有一个ServletContext用于访问web应用的参数在DD中配置用于获取服务器信息存放其它公用信息
请求与响应
ServletRequest \<--- HTTPServletRequest \<--- realRequest
SerbletResponse \<---- HTTPSerbletResponse \<---realResponse
java
与你写的python还是有很多不同的面向对象思想比较深刻。所以每次设计到一个内容首先了解有哪些类-对象,
每个类-对象由哪些属性 每个类-对象有那些方法;
因为每个类的功能和作用比较固定,所以属性和方法一般是与此功能相关的,笔记哦啊容易记忆。
已经涉及到的对象
HttpServlet -对象,每次请求会实例化。
Request -对象
Response -对象
ServletConfig - 对象
SerletContext - 对象
还是第一次真正的用到cookie那么思考一下如何使用cookie。
用户携带cookie值如果有的话请求一个网页。
服务器端读取cookie值如果存在cookie值则添加到页面当中。
当前用的这个东西存在一定的弊端。直接通过cookie获取当前用户的身份。

View File

@@ -0,0 +1,27 @@
感觉配置环境的过程中,对这些东西一知半解。
1\. 首先安装eclipsejdk/jreadt插件完成eclipse开发Android环境的基础设备。
2.
安装了node.js并配置了相关的环境使得系统能够编译并运行node.js的代码。然而跟我们的工程有什么联系一点都不知道。
经过了解得知安装node的原因是因为node的服务器端是由node.js写的也就是说node并不是用来进行编译客户端的代码的而是用来运行appium的服务器端程序的。
3.
安装Appium软件这玩意不是系统插件是一个调试的监视工具吧。具体怎么运作也不知道。
经过了解得知这个东西封装了对各种移动设备框架的调试方法通过服务器端连接客户端和移动设备。客户端通过url的形式访问服务器端完成对移动设备的调试。
4\. APPium调试过程依赖的jar包包括测试类库
Selenum类库(selenium.jar)
Appium类库client.jar)不知道是干啥用的
5\. 关联了相关的文件apk appt appt.exe)不知道是干啥用的
6\. 启动了Android模拟器或者连接了真机。
7\. 启动Appium工具并通过junit的方式对软件进行调试。
总之今天最大的收获可能就是对eclipse自动构建java工程结构有了更多的了解。

View File

@@ -0,0 +1,30 @@
下面来介绍将小数值舍入为整数的几个方法Math.ceil()、Math.floor()和Math.round()。
这三个方法分别遵循下列舍入规则:
Math.ceil()执行向上舍入,即它总是将数值向上舍入为最接近的整数;
Math.floor()执行向下舍入,即它总是将数值向下舍入为最接近的整数;
Math.round()执行标准舍入,即它总是将数值四舍五入为最接近的整数(这也是我们在数学课上学到的舍入规则)。
下面来看几个例子:
Math.ceil(25.9) //26
Math.ceil(25.5) //26
Math.ceil(25.1) //26
Math.ceil(25.0) //25
Math.round(25.9) //26
Math.round(25.5) //26
Math.round(25.1) //25
Math.floor(25.9) //25
Math.floor(25.5) //25
Math.floor(25.1) //25

View File

@@ -0,0 +1,117 @@
## 新的事件监听机制
-----
* 之前是定义一个组件对象(事件源),队组建对象绑定一个监听器对象,在监听器对象中有监听同一事件不同动作的函数,函数内部对事件进行处理。从监听器的角度对事件和动作进行处理。
* 现在是直接将静态事件绑定到事件源上通过process函数运行运行事件发生时的处理方式。而且这些静态事件是已经存在于awtEvent类中的。
```
package EventHandle;
import java.awt.*;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
/**
* @author 宙斯
* 准确的说这并不是先前的事件监听机制吧。它不存在指明的监听器。
* 应该更像一种组件自带的事件匹配功能。
* 具体步骤:
* 打开某一类型的事件匹配功能。
* 使用process函数运行某个事件
* 当事件发生时通过事件的ID匹配具体的动作。
* 匹配后设置相应的处理方式。
*/
public class baseEvent extends Frame{
private int x = 0,y = 0,flag = 0;
private Image img;
private int dx = 0,dy = 0;
public static void main(String[] args) {
baseEvent bE = new baseEvent();
}
public baseEvent(){
super();
setSize(500,500);
this.setVisible(true);
Toolkit tk = Toolkit.getDefaultToolkit();
img = tk.getImage("first.png");
//相当于添加了对Component事件的监听器似乎监听器类在底层已经直接绑定。
enableEvents(AWTEvent.COMPONENT_EVENT_MASK);
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
enableEvents(AWTEvent.MOUSE_EVENT_MASK);
repaint();
}
//直接调用底层的事件处理函数
public void processComponentEvent(ComponentEvent e){
if(e.getID() == ComponentEvent.COMPONENT_MOVED){
System.out.println(e.getSource());
System.out.println(e.getID());
}
}
public void processWindowEvent(WindowEvent e){
if(e.getID() == WindowEvent.WINDOW_CLOSING){
System.exit(0);
}
}
/*
public void processMouseEvent(MouseEvent e){
if(e.getID() == MouseEvent.MOUSE_PRESSED){
System.out.println("pressed");
if((e.getX()>= x)&&(e.getX()<=x+100)&&(e.getY()>=y)&&(e.getY()<=y+100)){
flag = 1;
System.out.println(e.getX()+"..."+e.getY());
}
}
if((e.getID()==MouseEvent.MOUSE_RELEASED)&&(flag == 1)){
x = e.getX();
y = e.getY();
repaint();
flag = 0;
}
}
*/
public void processMouseEvent(MouseEvent e){
if(e.getID() == MouseEvent.MOUSE_PRESSED){
System.out.println("pressed");
if((e.getX()>= x)&&(e.getX()<=x+100)&&(e.getY()>=y)&&(e.getY()<=y+100)){
dx = e.getX()-x;
dy = e.getY()-y;
flag = 1;
System.out.println(e.getX()+"..."+e.getY());
}
}
if(e.getID()== MouseEvent.MOUSE_MOVED&&flag ==1){
x = e.getX()-dx;
y = e.getY()-dy;
System.out.println(e.getX()+"..."+e.getY());
repaint();
}
if((e.getID()==MouseEvent.MOUSE_RELEASED)&&(flag == 1)){
flag = 0;
}
}
public void paint(Graphics g){
g.drawImage(img, x, y,100,100, this);
}
}
```

View File

@@ -0,0 +1,14 @@
# 多线程共享受限资源
----
## &gt;多线程共享受限资源存在的问题
----
* **这个描述???**
当你坐在桌子旁边时,手里有有一把叉子,准备插起盘子里最后一块十五,当叉子碰到十五的时候,它忽然消失了。
* **解决方法**
给这个资源加锁,每个线程访问这个资源时上锁,访问结束后开锁。

View File

@@ -0,0 +1,48 @@
# 多线程理论补充
------
## &gt;让步机制
-----
* **yield**
thread.yield()线程执行这个函数会主动放弃执行的优先级但只是暗示别的线程能够抢到更多的资源没有确定的机制保证cpu资源一定被其他线程使用。
## &gt;休眠机制
---
* **sleep**
thread.sleep(30)线程停止执行30ms可能会跑出异常此线程调用interrupt方法中断了线程的执行。
## &gt;优先权机制
----
* **setPriority()**
thread.setPriority()通过thread类中的常量对优先级进行设定。thread.getPriority()能够获取当前线程的优先级。
## &gt;后台进程
-----
* **后台线程守护线程thread.setDaemon()**
程序运行时在后台提供的一种通用的线程当所有的非后台线程结束时后台线程守护线程自动终止。必须在线程启动之前调用方法setDaemon()将线程设置成后台线程。isDeamon判断是否为后台线程。
## &gt;加入线程
----
* **t.join(a)**
t线程此时将被挂起直到a线程结束才会被执行。当a线程结束时t.isAlive()返回为假,线程恢复。
## &gt;编码变体
-----
* **implements Runnable**
通过实现接口Runnable来达到作为线程类的方法。必须实现run方法。
* **建立有响应的用户界面**
让运算作为一个独立的线程在后台独立运行。

View File

@@ -0,0 +1,40 @@
# 多线程的应用
------
## 多线程停止线程
----
* stop方法已经过时不能使用只能当run方法结束时才能终止线程。开启多线程程运行时代码通常是循环结构只要控制住线程通常可以让run方法结束。
* 应当设计可以修改的无限循环标志。跳出无限循环,则会终止线程。
* 当线程在循环内进入等待状态时及时线程的循环条件不满足必须终止线程但是无法执行到判断语句进行线程的终止此时必须使用interrupt()函数来达到要求。
* interrupt将处于冻结状态的线程强制转换到运行状态。此时wait()就会跑出我们处理已久的中断异常。
* 当没有指定的方式让冻结的线程回复到运行状态时这是需要对冻结进行清除。Thread提供了interrupt方法。
## 多线程 守护线程
-----
* 守护线程就是后台线程,也是一种依赖线程
* 特点:
当前台线程结束后,后台线程会自动终止,作为依赖线程,守护线程,不用强调结束。
* 方法:
setDemon()设置某个线程为守护线程
## 多线程join方法
----
* t1.join() t1抢夺cpu执行权主线程处于冻结状态t1优先执行。相当于顺序执行两个线程。主线程碰到谁的join就会等谁执行。
* 当A线程执行到了B线程的Join方法时A线程就会等待等B线程都执行完成A才会执行。join才会临时加入线程执行。当B线程进入wait时A线程也能继续执行。
* toString 方法能够显示线程的名称,线程的优先级,线程当前的分组(线程组谁调用就是谁的线程组的)
* 所有线程包括主线程默认是5。数越大优先级越高。MAX_PRIORITY,MIN_PRIORITY,
* yield()方法,当线程读到这里是,会释放执行权。这样会使所有的线程都有平均执行的效果。
## 什么时候会使用到多线程
----
* 当程序独立运算相互之间不相关的时候,可以用多线程封装一下,提高程序执行的速度

View File

@@ -0,0 +1,166 @@
# 多线程间的通讯
-----
## 多线程通讯的定义:
----
- 多个不同的线程对共同的数据进行不同的操作。
## 多线程通讯间的安全问题
-----
* 安全问题的原因
例如当多个线程对同一个数据进行不同操作时,导致各种操作的先后顺序出现混乱。
* 安全问题的解决方式
对这些线程操作数据的部分进行同步处理,使用相同的锁,将不同的部分锁起。
## 线程间通讯等待唤醒机制
-----
* 可以模仿锁的工作原理(设置标志位,记录当前是够线程占用锁内的程序,实现只能有一个线程执行锁内代码的现象)
* 步骤:
1. 设置标志位flag
2. 当标志位处于输入状态时,执行输入程序,执行完成后修改为输出状态。
3. 当标志位处于输出状态时,执行输出程序,执行完成后修改为输入状态。
## 等待唤醒机制的具体实现
----
* wait()和notify()函数必须在同步代码块或者同步函数当中使用。注意wait()会抛出中断异常。对持有监视器(锁)的线程进行操作。
* wait()和notify()的操作对象是同步中持有当前锁的线程。
* 线程的等待唤醒机制必须制定一把确定的锁。锁是任意的对象任意对象都能成为锁成为锁之后都能调用wait和notify的方法。而且这些方法都定义在Object类中。只有同一个锁上的被等待线程可以被同一个notify唤醒。等待唤醒必须是同一个锁。
## 使用新的工具类实现程序锁定和解锁
----
package painting;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author 宙斯
*
*/
public class LockerUsing {
/**
* @param args
*/
public static void main(String[] args) {
Resource2 r = new Resource2();
Produce2 pro = new Produce2(r);
Consumer2 con = new Consumer2(r);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
Thread t3 = new Thread(pro);
Thread t4 = new Thread(con);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
class Resource2{
private String name;
private int count =1;
private boolean flag = false;
private Lock lock = new ReentrantLock();//新建了一个锁对象
private Condition condition_con = lock.newCondition();//生成了一个与锁相关的控制对象
private Condition condition_pro = lock.newCondition();
public void set(String name) throws InterruptedException{
lock.lock();
try{
while(flag)
condition_pro.await();
this.name= name+"..."+count++;
System.out.println(Thread.currentThread().getName()+"生产者:"+this.name);
flag = true;
condition_con.signal();
}
finally{
lock.unlock();//异常处理当中释放锁的动过一定要被执行
}
}
public void out() throws InterruptedException{
lock.lock();
try{
while(!flag)
condition_con.await();
System.out.println(Thread.currentThread().getName()+"消费者:"+this.name);
flag = false;
condition_pro.signalAll();
}
finally{
lock.unlock();
}
}
}
class Produce2 implements Runnable{
private Resource2 res;
Produce2(Resource2 res){
this.res = res;
}
public void run()
{
while(true){
try {
res.set("商品");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class Consumer2 implements Runnable{
private Resource2 res;
Consumer2(Resource2 res){
this.res = res;
}
public void run()
{
while(true){
try {
res.out();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
* 代码的解释:
1. 单线程 -----多线程-----多线程操作同一个数据源的时候实行同步机制------带有满足条件的同步机制(睡眠唤醒机制)
2. 实现了多线程不同操作相同的程序,这个类具有模板的价值.对资源的不同操作写到资源类中并使用this资源类的锁对各种不同的操作进行上锁
3. 而非写到其他操作类中,这样能够将同步和冲突解决都封装到资源类中便于理解和操作。
4. 当线程数多于两个,比如此程序中有两个在生产两个在消费,那么标准的方式应该是通过循环判断标志位是否合格,
因为当某个线程判断满足后,但在进入之前肯能被其他线程修改标志位。
而且必须使用notifyAll()唤醒所有的线程。
5. 使用Locker及其相关类的好处
一个Locker上可以有很多condition对象执行操作也就是只唤醒对方的condition
jdk1.5实现了多线程的升级解决方案
将同步设置Synchronize替换成Lock操作可见
将Object中waitnotifynotifyAll替换成Condition对象。该对象可以Locker锁进行获取

View File

@@ -0,0 +1,5 @@
# 底层事件处理
-----
* 在java.awt学习的时候将监听器绑定到事件源上当指定事件发生时监听器会自动匹配到相应的动作执行相应的处理方式。但在底层事件处理过程中不许要监听器能够直接获取当前发生的底层事件然后进行匹配处理。

View File

@@ -0,0 +1,159 @@
RMI的定义
RPC (Remote Procedure
Call):远程方法调用,用于一个进程调用另一个进程中的过程,从而提供了过程的分布能力。
RMIRemote Method
Invocation):远程方法调用即在RPC的基础上有向前迈进了一步提供分布式对象间的通讯。允许运行在一个java
虚拟机的对象调用运行在另一个java虚拟机上对象的方法。这两个虚拟机可以是运行在相同计算机上的不同进程中也可以是运行在网络上的不同计算机中。
RMI的作用
RMI的全称宗旨就是尽量简化远程接口对象的调用。
RMI大大增强了java开发分布式应用的能力例如可以将计算方法复杂的程序放在其他的服务器上主服务器只需要去调用而真正的运算是在其他服务器上进行最后将运算结果返回给主服务器这样就减轻了主服务器的负担提高了效率但是也有其他的开销
RMI网络模型
在设计初始阶段,我们真正想要的是这样一种机制,客户端程序员以常规方式进行方法调用,而无需操心将数据发送到网络上或者解析响应之类的问题。所以才有了如下的网络模型:在客户端为远程对象安装一个代理。代理是位于客户端虚拟机中的一个对象,它对于客户端程序来说,就像是要访问的远程对象一样。客户端调用此代理时,只需进行常规的方法调用。而客户端代理则负责使用网络协议与服务器进行联系。
![8-343985609.jpeg](media/b24ac0390788e8547c3f60daee9eaacf.jpeg)
现在的问题在于代理之间是如何进行通信的?通常有三种方法:
1、CORBA通过对象请求代理架构支持任何编程语言编写的对象之间的方法调用。
2、SOAP
3、RMIJAVA的远程方法调用技术支持java的分布式对象之间的方法调用。
其中CORBA与SOAP都是完全独立于言语的可以使用C、C++、JAVA来编写而RMI只适用于JAVA。
RMI的工作原理
**术语介绍**
> 1、存根当客户端要调用远程对象的一个方法时实际上调用的是代理对象上的一个普通方法**我们称此代理对象为存根stub。**存根位于客户端机器上,而非服务器上。
> 2、参数编组存根会将**远程方法所需的参数打包成一组字节**对参数编码的过程就称为参数编组。参数编组的目的是将参数转换成适合在虚拟机之间进行传递的格式在RMI协议中对象是使用序列化机制进行编码的。
编程模型
为了介绍RMI的编程模型我下面会编写一个DEMO。远程对象表示的是一个仓库而客户端程序向仓库询问某个产品的价格。
**接口定义**
远程对象的能力是由在客户端和服务器之间共享的接口所表示的:
![copycode.gif](media/51e409b11aa51c150090697429a953ed.gif)
复制代码
package rmi; import java.rmi.Remote; import java.rmi.RemoteException; public
interface Warehouse extends Remote { double getPrice(String description) throws
RemoteException; }
远程对象的接口必须扩展Remote接口它位于java.rmi包中。接口中所有的方法必须声明抛出RemoteException异常。这是因为远程方法总是存在失败的可能所以java编程语言要求每一次远程方法的调用都必须捕获RemoteException,并且指明当调用不成功时应执行的相应处理操作。
**接口的实现**
![copycode.gif](media/51e409b11aa51c150090697429a953ed.gif)
复制代码
package rmi; import java.rmi.RemoteException; import
java.rmi.server.UnicastRemoteObject; import java.util.HashMap; import
java.util.Map; public class WarehouseImpl extends UnicastRemoteObject implements
Warehouse { private static final long serialVersionUID = 1L; private
Map\<String,Double\> prices; protected WarehouseImpl() throws RemoteException {
prices = new HashMap\<String,Double\>(); prices.put("mate7",3700.00); } public
double getPrice(String description) throws RemoteException { Double price =
prices.get(description); return price == null? 0 : price; }}
你可以看出这个类是远程方法调用的目标因为它扩展自UnicastRemoteObject这个类的构造器使得它的对象可供远程访问。
**RMI注册表:通过JNDI发布RMI服务**
1、要访问服务器上的一个远程对象时客户端必须先得到一个本地的存根对象也就是客户端机器上的代理对象。那么问题来了如何才能得到这个存根呢
2、为此JDK提供了自举注册服务bootstrap registry
service服务器程序应该使用自举注册服务来注册至少一个远程对象。
3、而要注册一个远程对象需要一个RMI URL和一个对实现对象的引用。
4、RMI
的URL以rmi:开头后接域名或IP地址host紧接着是端口号port最后是服务名service
rmi://regserver.mycompany.cmo:99/central_warehouse
如果我们是在本地发布RMI服务那么host就是“localhost”此外RMI默认的端口号是“1099”当然我们也可以自行设置只要不与其他端口重复即可。service实际上是基于同一个host与port下唯一的服务名。
发布RMI服务
1 package rmi; 2 3 import java.net.MalformedURLException; 4 import
java.rmi.AlreadyBoundException; 5 import java.rmi.Naming; 6 import
java.rmi.RemoteException; 7 import java.rmi.registry.LocateRegistry; 8 9 import
javax.naming.NamingException; 10 11 12 public class WarehouseServer 13 { 14
public static void main(String[] args) throws RemoteException, NamingException,
MalformedURLException, AlreadyBoundException 15 { 16
System.out.println("Constructing server implementation"); 17 WarehouseImpl
centralWarehouse = new WarehouseImpl(); 18 19 System.out.println("Binding server
implementation to registry"); 20 LocateRegistry.createRegistry(1099); 21
Naming.bind("rmi://localhost:1099/central_warehoues",centralWarehouse); 22 23
System.out.println("Waiting for invocations from clients ..."); 24 } 25 }
运行结果:
Constructing server implementation Binding server implementation to registry
Waiting for invocations from clients ...
1、第20行只需提供一个port就在JNDI中创建了一个注册表。
2、第21行通过bind方法绑定了RMI地址与RMI服务实现类。
3、执行这个方法后相当于自动发布了RMI服务。接下来要做的事情就是写一个RM客户端调用已发布的RMI服务。
**客户端调用RMI服务**
1 package rmi; 2 3 import java.net.MalformedURLException; 4 import
java.rmi.Naming; 5 import java.rmi.NotBoundException; 6 import
java.rmi.RemoteException; 7 import javax.naming.NamingException; 8 9 public
class WarehouseClient 10 { 11 public static void main(String[] args) throws
NamingException, RemoteException, MalformedURLException, NotBoundException 12 {
13 System.out.println("RMI registry binding:"); 14 String url =
"rmi://localhost:1099/central_warehoues"; 15 Warehouse centralWarehouse =
(Warehouse) Naming.lookup(url); 16 String descr = "mate7"; 17 double price =
centralWarehouse.getPrice(descr); 18 System.out.println(descr + ":" + price); 19
} 20 }
运行结果:
RMI registry binding: mate7:3700.0
补充说明:
> 服务调用只需要知道两个东西1、RMI请求路径2、RMI接口名
> 第15行这里用的是接口名Warehouse,而不是实现类。一定不能RMI接口的实现类否则就是本地调用了。
> 查看运行结果我们知道这次DEMO展示的远程调用成功了。
**下面我们来看下RMI的网络示意图**
![3-765464905.jpeg](media/f2f880588756d88cbf5083a94fbd41ae.jpeg)
1、借助JNDI这个所谓的命名与目录服务我们成功地发布并调用了RMI服务。实际上JNDI就是一个注册表服务端将服务对象放入到注册表中客户端从注册表中获取服务对象。
2、在服务端我们发布了RMI服务并在JNDI中进行了注册此时就在服务端创建了一个Skeleton骨架当客户端第一次成功连接JNDI并获取远程服务对象后立马在本地创建了一个Stub存根
3、远程通信实际是通过Skeleton与Stub来完成的数据是基于TCP/IP协议在“传输层”上发送的。
4、毋庸置疑理论上RMI一定比WebService要快毕竟WebService是基于http协议的而http所携带的数据是通过“应用层”来传输的。传输层较应用层更为底层越底层越快。
RMI的局限性
1、只能实现JAVA系统之间的调用而WebService可以实现跨语言实现系统之间的调用。
2、RMI使用了JAVA默认的序列化方式对于性能要求比较高的系统可能需要其他的序列化方案来解决。
3、RMI服务在运行时难免会存在故障例如如果RMI服务无法连接了就会导致客户端无法响应的现象。

View File

@@ -0,0 +1,140 @@
String与StringBuffer的区别
简单地说就是一个变量和常量的关系。StringBuffer对象的内容可以修改而String对象一旦产生后就不可以被修改重新赋值其实是两个对象。
StringBuffer的内部实现方式和String不同StringBuffer在进行字符串处理时不生成新的对象在内存使用上要优于String类。所以在实际使用时如果经常需要对一个字符串进行修改例如插入、删除等操作使用StringBuffer要更加适合一些。
String:在String类中没有用来改变已有字符串中的某个字符的方法由于不能改变一个java字符串中的某个单独字符所以在JDK文档中称String类的对象是不可改变的。然而不可改变的字符串具有一个很大的优点:编译器可以把字符串设为共享的。
StringBuffer:StringBuffer类属于一种辅助类可预先分配指定长度的内存块建立一个字符串缓冲区。这样使用StringBuffer类的append方法追加字符
比 String使用 + 操作符添加字符 到 一个已经存在的字符串后面有效率得多。因为使用 +
操作符每一次将字符添加到一个字符串中去时字符串对象都需要寻找一个新的内存空间来容纳更大的字符串这无凝是一个非常消耗时间的操作。添加多个字符也就意味着要一次又一次的对字符串重新分配内存。使用StringBuffer类就避免了这个问题。
StringBuffer是线程安全的在多线程程序中也可以很方便的进行使用但是程序的执行效率相对来说就要稍微慢一些。
StringBuffer的常用方法
StringBuffer类中的方法要偏重于对字符串的变化例如追加、插入和删除等这个也是StringBuffer和String类的主要区别。
1、append方法
public StringBuffer append(boolean b)
该方法的作用是追加内容到当前StringBuffer对象的末尾类似于字符串的连接。调用该方法以后StringBuffer对象的内容也发生改变例如
StringBuffer sb = new StringBuffer(“abc”);
sb.append(true);
则对象sb的值将变成”abctrue”。
使用该方法进行字符串的连接将比String更加节约内容例如应用于数据库SQL语句的连接例如
StringBuffer sb = new StringBuffer();
String user = “test”;
String pwd = “123”;
sb.append(“select \* from userInfo where username=“)
.append(user)
.append(“ and pwd=”)
.append(pwd);
这样对象sb的值就是字符串“select \* from userInfo where username=test and
pwd=123”。
2、deleteCharAt方法
public StringBuffer deleteCharAt(int index)
该方法的作用是删除指定位置的字符,然后将剩余的内容形成新的字符串。例如:
StringBuffer sb = new StringBuffer(“Test”);
sb. deleteCharAt(1);
该代码的作用删除字符串对象sb中索引值为1的字符也就是删除第二个字符剩余的内容组成一个新的字符串。所以对象sb的值变为”Tst”。
还存在一个功能类似的delete方法
public StringBuffer delete(int start,int end)
该方法的作用是删除指定区间以内的所有字符包含start不包含end索引值的区间。例如
StringBuffer sb = new StringBuffer(“TestString”);
sb. delete (1,4);
该代码的作用是删除索引值1(包括)到索引值4(不包括)之间的所有字符剩余的字符形成新的字符串。则对象sb的值是”TString”。
3、insert方法
public StringBuffer insert(int offset, String s)
该方法的作用是在StringBuffer对象中插入内容然后形成新的字符串。例如
StringBuffer sb = new StringBuffer(“TestString”);
sb.insert(4,“false”);
该示例代码的作用是在对象sb的索引值4的位置插入字符串false形成新的字符串则执行以后对象sb的值是”TestfalseString”。
4、reverse方法
public StringBuffer reverse()
该方法的作用是将StringBuffer对象中的内容反转然后形成新的字符串。例如
StringBuffer sb = new StringBuffer(“abc”);
sb.reverse();
经过反转以后对象sb中的内容将变为”cba”。
5、setCharAt方法
public void setCharAt(int index, char ch)
该方法的作用是修改对象中索引值为index位置的字符为新的字符ch。例如
StringBuffer sb = new StringBuffer(“abc”);
sb.setCharAt(1,D);
则对象sb的值将变成”aDc”。
6、trimToSize方法
public void trimToSize()
该方法的作用是将StringBuffer对象的中存储空间缩小到和字符串长度一样的长度减少空间的浪费。
7、构造方法
StringBuffer s0=new StringBuffer();分配了长16字节的字符缓冲区
StringBuffer s1=new StringBuffer(512);分配了512字节的字符缓冲区
8、获取字符串的长度: length()
StringBuffer s = new StringBuffer("www");
int i=s.length();
m.返回字符串的一部分值
substring(int start) //返回从start下标开始以后的字符串
substring(int start,int end) //返回从start到 end-1字符串
9.替换字符串
replace(int start,int end,String str)
s.replace(0,1,"qqq");
10.转换为不变字符串:toString()。

View File

@@ -0,0 +1,189 @@
简介
**作用:**
用来传输和存储数据
**定义:**
可扩展标记语言。
**特点:**
自行定义标签,具有自我描述性。
能够跨越各种平台
**具体应用:**
用于描述可用的web服务的WSDL
树结构
**范例**
\<?xml version="1.0"
encoding="UTF-8"?\>\<note\>\<to\>Tove\</to\>\<from\>Jani\</from\>\<heading\>Reminder\</heading\>\<body\>Don't
forget me this weekend!\</body\>\</note\>
说明第一行是XML文档声明定义了版本号和文档的编码方式。
**树结构:**
![clipboard.png](media/ab38369f8043d690b448fe8e8004a755.png)
**元素:**
起始标记、结束标记、内容(可以是字符文本、其他元素、混合物)
**属性:**
属性名=属性值
**语法规则:**
标签闭合,正确嵌套
有一个根元素
可以有树枝也可以由实体引用
XML声明可选放在第一行
XML标签对大小写敏感
属性值必须加引号,应当尽量用子元素代替属性。数据的数据存储为属性,而数据本身应当存储为元素。
id属性可以用来标识XML元素
注释方式\<!-- This is a comment --\>
部分字符使用转义字符
| &lt; | \< | less than |
|---------|----|----------------|
| &gt; | \> | greater than |
| \&amp; | & | ampersand |
| \&apos; | ' | apostrophe |
| &quot; | " | quotation mark |
命名空间
**名字冲突**
同时使用相同的名字
**限定名字**
使用名字空间。在标签之前加上前缀
> \<h:table xmlns:h="http://www.w3.org/TR/html4/"\> \<h:tr\>
> \<h:td\>Apples\</h:td\> \<h:td\>Bananas\</h:td\> \</h:tr\> \</h:table\>
使用默认的名字空间
> \<table xmlns="http://www.w3.org/TR/html4/"\> \<tr\> \<td\>Apples\</td\>
> \<td\>Bananas\</td\> \</tr\> \</table\>
XML定义方式
**XML DTD**
DTD 的目的是定义 XML 文档的结构。它使用一系列合法的元素来定义文档结构:
> \<!DOCTYPE note
> [
> \<!ELEMENT note (to,from,heading,body)\>
> \<!ELEMENT to (\#PCDATA)\>
> \<!ELEMENT from (\#PCDATA)\>
> \<!ELEMENT heading (\#PCDATA)\>
> \<!ELEMENT body (\#PCDATA)\>
> ]\>
**XML Schema**
W3C 支持一种基于 XML 的 DTD 代替者,它名为 XML Schema
> \<xs:element name="note"\>
> \<xs:complexType\>
> \<xs:sequence\>
> \<xs:element name="to" type="xs:string"/\>
> \<xs:element name="from" type="xs:string"/\>
> \<xs:element name="heading" type="xs:string"/\>
> \<xs:element name="body" type="xs:string"/\>
> \</xs:sequence\>
> \</xs:complexType\>
> \</xs:element\>
XML验证方式
对xml语法进行检查
XML显示方式
**源代码**
**CSS格式显示**
> CATALOG { background-color: \#ffffff; width: 100%; } CD { display: block;
> margin-bottom: 30pt; margin-left: 0; } TITLE { color: \#FF0000; font-size:
> 20pt; } ARTIST { color: \#0000FF; font-size: 20pt; }
> COUNTRY,PRICE,YEAR,COMPANY { display: block; color: \#000000; margin-left:
> 20pt; }
**XSLT格式显示XML**
将XML转化为对应的HTML语言
> \<?xml version="1.0" encoding="ISO-8859-1"?\>
> \<!-- Edited by XMLSpy® --\>
> \<html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
> xmlns="http://www.w3.org/1999/xhtml"\>
> \<body style="font-family:Arial;font-size:12pt;background-color:\#EEEEEE"\>
> \<xsl:for-each select="breakfast_menu/food"\>
> \<div style="background-color:teal;color:white;padding:4px"\>
> \<span style="font-weight:bold"\>\<xsl:value-of select="name"/\>\</span\>
> \- \<xsl:value-of select="price"/\>
> \</div\>
> \<div style="margin-left:20px;margin-bottom:1em;font-size:10pt"\>
> \<p\>\<xsl:value-of select="description"/\>.
> \<span style="font-style:italic"\>
> \<xsl:value-of select="calories"/\> (calories per serving)
> \</span\>.\</p\>
> \</div\>
> \</xsl:for-each\>
> \</body\>
> \</html\>

View File

@@ -0,0 +1,71 @@
1确定是数据源和数据目的输入还是输出
源:输入流 InputStream Reader
目的:输出流 OutputStream Writer
2明确操作的数据对象是否是纯文本
是:字符流ReaderWriter
否:字节流InputStreamOutputStream
3明确具体的设备。
是硬盘文件File++
读取FileInputStream,, FileReader,
写入FileOutputStreamFileWriter
是内存用数组
byte[]ByteArrayInputStream, ByteArrayOutputStream
是char[]CharArrayReader, CharArrayWriter
是StringStringBufferInputStream(已过时因为其只能用于String的每个字符都是8位的字符串),
StringReader, StringWriter
是网络用Socket流
是键盘用System.in是一个InputStream对象读取用System.out是一个OutoutStream对象打印
3是否需要转换流
就使用转换流从Stream转化为ReaderWriterInputStreamReaderOutputStreamWriter
4是否需要缓冲提高效率
是就加上BufferedBufferedInputStream, BufferedOuputStream, BuffereaReader,
BufferedWriter
5是否需要格式化输出
例:将一个文本文件中数据存储到另一个文件中。
1数据源和数据目的读取流InputStream Reader 输出OutputStream Writer
2是否纯文本这时就可以选择Reader Writer。
3设备是硬盘文件。Reader体系中可以操作文件的对象是 FileReader FileWriter。
FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("b.txt");
4是否需要提高效率加Buffer
BufferedReader bfr = new BufferedReader(new FileReader("a.txt"); );
BufferedWriter bfw = new BufferedWriter(new FileWriter("b.txt"); );
PrintStream
PrintStream在OutputStream基础之上提供了增强的功能即可以方便地输出各种类型的数据而不仅限于byte型的格式化表示形式。PrintStream的方法从不抛出IOEceptin
PrintWriter
PrintWriter提供了PrintStream的所有打印方法其方法也从不抛出IOException。
与PrintStream的区别作为处理流使用时PrintStream只能封装OutputStream类型的字节流而PrintWriter既可以封装OutputStream类型的字节流还能够封装Writer类型的字符输出流并增强其功能。

View File

@@ -0,0 +1,15 @@
**值得参考的网址**
**http://tutorials.jenkov.com/java-io/stringreader.html**
![clipboard.png](media/999fffbe3d46bc883b98ea7b5769a7da.png)
应该使用以下格式
- 作用分析
- 功能方法
- 代码示例
- 注意事项

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Some files were not shown because too many files have changed in this diff Show More