一、

1.The Proxy Pattern provides a surrogate or placeholder for another object to control access to it.

Your client object acts like it’s making remote method calls.But what it’s really doing is calling methods on a heap-local ‘proxy’ object that handles all the low-level details of network communication.

2.

3.

4.

5.

6.

二、只能在本地监控的

1.

 package headfirst.designpatterns.proxy.gumballmonitor;

 public class GumballMachine {
State soldOutState;
State noQuarterState;
State hasQuarterState;
State soldState;
State winnerState; State state = soldOutState;
int count = 0;
String location; public GumballMachine(String location, int count) {
soldOutState = new SoldOutState(this);
noQuarterState = new NoQuarterState(this);
hasQuarterState = new HasQuarterState(this);
soldState = new SoldState(this);
winnerState = new WinnerState(this); this.count = count;
if (count > 0) {
state = noQuarterState;
}
this.location = location;
} public void insertQuarter() {
state.insertQuarter();
} public void ejectQuarter() {
state.ejectQuarter();
} public void turnCrank() {
state.turnCrank();
state.dispense();
} void setState(State state) {
this.state = state;
} void releaseBall() {
System.out.println("A gumball comes rolling out the slot...");
if (count != 0) {
count = count - 1;
}
} public int getCount() {
return count;
} public void refill(int count) {
this.count = count;
state = noQuarterState;
} public State getState() {
return state;
} public String getLocation() {
return location;
} public State getSoldOutState() {
return soldOutState;
} public State getNoQuarterState() {
return noQuarterState;
} public State getHasQuarterState() {
return hasQuarterState;
} public State getSoldState() {
return soldState;
} public State getWinnerState() {
return winnerState;
} public String toString() {
StringBuffer result = new StringBuffer();
result.append("\nMighty Gumball, Inc.");
result.append("\nJava-enabled Standing Gumball Model #2004");
result.append("\nInventory: " + count + " gumball");
if (count != 1) {
result.append("s");
}
result.append("\n");
result.append("Machine is " + state + "\n");
return result.toString();
}
}

2.

 package headfirst.designpatterns.proxy.gumballmonitor;

 public class GumballMonitor {
GumballMachine machine; public GumballMonitor(GumballMachine machine) {
this.machine = machine;
} public void report() {
System.out.println("Gumball Machine: " + machine.getLocation());
System.out.println("Current inventory: " + machine.getCount() + " gumballs");
System.out.println("Current state: " + machine.getState());
}
}

3.

 package headfirst.designpatterns.proxy.gumballmonitor;

 public class GumballMachineTestDrive {

     public static void main(String[] args) {
int count = 0; if (args.length < 2) {
System.out.println("GumballMachine <name> <inventory>");
System.exit(1);
} try {
count = Integer.parseInt(args[1]);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
GumballMachine gumballMachine = new GumballMachine(args[0], count); GumballMonitor monitor = new GumballMonitor(gumballMachine); System.out.println(gumballMachine); gumballMachine.insertQuarter();
gumballMachine.turnCrank();
gumballMachine.insertQuarter();
gumballMachine.turnCrank(); System.out.println(gumballMachine); gumballMachine.insertQuarter();
gumballMachine.turnCrank();
gumballMachine.insertQuarter();
gumballMachine.turnCrank(); System.out.println(gumballMachine); gumballMachine.insertQuarter();
gumballMachine.turnCrank();
gumballMachine.insertQuarter();
gumballMachine.turnCrank(); System.out.println(gumballMachine); gumballMachine.insertQuarter();
gumballMachine.turnCrank();
gumballMachine.insertQuarter();
gumballMachine.turnCrank(); System.out.println(gumballMachine); gumballMachine.insertQuarter();
gumballMachine.turnCrank();
gumballMachine.insertQuarter();
gumballMachine.turnCrank(); System.out.println(gumballMachine); monitor.report();
}
}

4.

 package headfirst.designpatterns.proxy.gumballmonitor;

 import java.util.Random;

 public class HasQuarterState implements State {
private static final long serialVersionUID = 2L;
Random randomWinner = new Random(System.currentTimeMillis());
GumballMachine gumballMachine; public HasQuarterState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
} public void insertQuarter() {
System.out.println("You can't insert another quarter");
} public void ejectQuarter() {
System.out.println("Quarter returned");
gumballMachine.setState(gumballMachine.getNoQuarterState());
} public void turnCrank() {
System.out.println("You turned...");
int winner = randomWinner.nextInt(10);
if (winner == 0) {
gumballMachine.setState(gumballMachine.getWinnerState());
} else {
gumballMachine.setState(gumballMachine.getSoldState());
}
} public void dispense() {
System.out.println("No gumball dispensed");
} public String toString() {
return "waiting for turn of crank";
}
}

5.

 package headfirst.designpatterns.proxy.gumballmonitor;

 public class NoQuarterState implements State {
private static final long serialVersionUID = 2L;
GumballMachine gumballMachine; public NoQuarterState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
} public void insertQuarter() {
System.out.println("You inserted a quarter");
gumballMachine.setState(gumballMachine.getHasQuarterState());
} public void ejectQuarter() {
System.out.println("You haven't inserted a quarter");
} public void turnCrank() {
System.out.println("You turned, but there's no quarter");
} public void dispense() {
System.out.println("You need to pay first");
} public String toString() {
return "waiting for quarter";
}
}

三、远程代理(使用RMI)

1.

 package headfirst.designpatterns.proxy.gumball;

 import java.rmi.*;

 public interface GumballMachineRemote extends Remote {
public int getCount() throws RemoteException;
public String getLocation() throws RemoteException;
public State getState() throws RemoteException;
}

2.

 package headfirst.designpatterns.proxy.gumball;

 import java.io.*;

 //Then we just extend the Serializable interface
//now State in all the subclasses can be transferred over the network.
public interface State extends Serializable {
public void insertQuarter();
public void ejectQuarter();
public void turnCrank();
public void dispense();
}

3.

 package headfirst.designpatterns.proxy.gumball;

 public class NoQuarterState implements State {
private static final long serialVersionUID = 2L; //in each implementation of State, we
// add the transient keyword to the
// GumballMachine instance variable. This
// tells the JVM not to serialize this field.
// Note that this can be slightly dangerous
// if you try to access this field once its
// been serialized and transferred.
transient GumballMachine gumballMachine; public NoQuarterState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
} public void insertQuarter() {
System.out.println("You inserted a quarter");
gumballMachine.setState(gumballMachine.getHasQuarterState());
} public void ejectQuarter() {
System.out.println("You haven't inserted a quarter");
} public void turnCrank() {
System.out.println("You turned, but there's no quarter");
} public void dispense() {
System.out.println("You need to pay first");
} public String toString() {
return "waiting for quarter";
}
}

4.

 package headfirst.designpatterns.proxy.gumball;

 import java.rmi.*;
import java.rmi.server.*; //GumballMachine is going to subclass the UnicastRemoteObject;
//this gives it the ability to act as a remote service.
public class GumballMachine
extends UnicastRemoteObject implements GumballMachineRemote
{
private static final long serialVersionUID = 2L;
State soldOutState;
State noQuarterState;
State hasQuarterState;
State soldState;
State winnerState; State state = soldOutState;
int count = 0;
String location; public GumballMachine(String location, int numberGumballs) throws RemoteException {
soldOutState = new SoldOutState(this);
noQuarterState = new NoQuarterState(this);
hasQuarterState = new HasQuarterState(this);
soldState = new SoldState(this);
winnerState = new WinnerState(this); this.count = numberGumballs;
if (numberGumballs > 0) {
state = noQuarterState;
}
this.location = location;
} public void insertQuarter() {
state.insertQuarter();
} public void ejectQuarter() {
state.ejectQuarter();
} public void turnCrank() {
state.turnCrank();
state.dispense();
} void setState(State state) {
this.state = state;
} void releaseBall() {
System.out.println("A gumball comes rolling out the slot...");
if (count != 0) {
count = count - 1;
}
} public void refill(int count) {
this.count = count;
state = noQuarterState;
} public int getCount() {
return count;
} public State getState() {
return state;
} public String getLocation() {
return location;
} public State getSoldOutState() {
return soldOutState;
} public State getNoQuarterState() {
return noQuarterState;
} public State getHasQuarterState() {
return hasQuarterState;
} public State getSoldState() {
return soldState;
} public State getWinnerState() {
return winnerState;
} public String toString() {
StringBuffer result = new StringBuffer();
result.append("\nMighty Gumball, Inc.");
result.append("\nJava-enabled Standing Gumball Model #2014");
result.append("\nInventory: " + count + " gumball");
if (count != 1) {
result.append("s");
}
result.append("\n");
result.append("Machine is " + state + "\n");
return result.toString();
}
}

5.Registering with the RMI registry

 package headfirst.designpatterns.proxy.gumball;
import java.rmi.*; public class GumballMachineTestDrive { public static void main(String[] args) {
GumballMachineRemote gumballMachine = null;
int count; if (args.length < 2) {
System.out.println("GumballMachine <name> <inventory>");
System.exit(1);
} try {
count = Integer.parseInt(args[1]); gumballMachine =
new GumballMachine(args[0], count);
Naming.rebind("//" + args[0] + "/gumballmachine", gumballMachine);
} catch (Exception e) {
e.printStackTrace();
}
}
}

6.

 package headfirst.designpatterns.proxy.gumball;

 import java.rmi.*;

 public class GumballMonitor {
//Now we’re going to rely on the remote interface
//rather than the concrete GumballMachine class.
GumballMachineRemote machine; public GumballMonitor(GumballMachineRemote machine) {
this.machine = machine;
} public void report() {
try {
System.out.println("Gumball Machine: " + machine.getLocation());
System.out.println("Current inventory: " + machine.getCount() + " gumballs");
System.out.println("Current state: " + machine.getState());
} catch (RemoteException e) {
e.printStackTrace();
}
}
}

7.

 package headfirst.designpatterns.proxy.gumball;

 import java.rmi.*;

 public class GumballMonitorTestDrive {

     public static void main(String[] args) {
String[] location = {"rmi://santafe.mightygumball.com/gumballmachine",
"rmi://boulder.mightygumball.com/gumballmachine",
"rmi://seattle.mightygumball.com/gumballmachine"}; if (args.length >= 0)
{
location = new String[1];
location[0] = "rmi://" + args[0] + "/gumballmachine";
} GumballMonitor[] monitor = new GumballMonitor[location.length]; for (int i=0;i < location.length; i++) {
try {
//This returns a proxy to the remote Gumball Machine
//(or throws an exception if one can’t be located).
GumballMachineRemote machine =
(GumballMachineRemote) Naming.lookup(location[i]);
//Naming.lookup() is a static method in the RMI package
//that takes a location and service name and looks it up in the
//rmiregistry at that location.
monitor[i] = new GumballMonitor(machine);
System.out.println(monitor[i]);
} catch (Exception e) {
e.printStackTrace();
}
} for(int i=0; i < monitor.length; i++) {
monitor[i].report();
}
}
}

By invoking methods on the proxy, a remote call is made across the wire and a String, an integer and a State object are returned. Because we are using a proxy, the GumballMonitor doesn’t know,or care, that calls are remote (other than having to worry about remote exceptions).

四.虚拟代理(代理create代价高的对象)分析

1.需求:要做一个显示cd封面的应用,封面是访问网络得到,为了当在访问网络获取图片较慢时,卡住程序,使用代理模式,但图片还没下载完时显示文字提示信息,但下载完后就显示图片

2.How ImageProxy is going to work:

(1)ImageProxy first creates an ImageIcon and starts loading it from a network URL.

(2)While the bytes of the image are being retrieved,ImageProxy displays “Loading CD cover, please wait...”.
(3)When the image is fully loaded, ImageProxy delegates all method calls to the image icon, including paintIcon(), getWidth() and getHeight().
(4)If the user requests a new image, we’ll create a new proxy and start the process over.

3.

4.

五、虚拟代理的实现

1.

 package headfirst.designpatterns.proxy.virtualproxy;

 import java.net.*;
import java.awt.*;
import javax.swing.*; class ImageProxy implements Icon {
volatile ImageIcon imageIcon;
final URL imageURL;
Thread retrievalThread;
boolean retrieving = false; public ImageProxy(URL url) { imageURL = url; } public int getIconWidth() {
if (imageIcon != null) {
return imageIcon.getIconWidth();
} else {
return 800;
}
} public int getIconHeight() {
if (imageIcon != null) {
return imageIcon.getIconHeight();
} else {
return 600;
}
} synchronized void setImageIcon(ImageIcon imageIcon) {
this.imageIcon = imageIcon;
} //This method is called when it’s time to paint the icon on the screen.
public void paintIcon(final Component c, Graphics g, int x, int y) {
//If we’ve got an icon already, we go ahead and tell it to paint itself.
if (imageIcon != null) {
imageIcon.paintIcon(c, g, x, y);
} else {
//Otherwise we display the “loading” message.
g.drawString("Loading CD cover, please wait...", x+300, y+190);
if (!retrieving) {
retrieving = true; retrievalThread = new Thread(new Runnable() {
public void run() {
try {
setImageIcon(new ImageIcon(imageURL, "CD Cover"));
c.repaint();
} catch (Exception e) {
e.printStackTrace();
}
}
});
retrievalThread.start();
}
}
}
}

2.

 package headfirst.designpatterns.proxy.virtualproxy;

 import java.awt.*;
import javax.swing.*; class ImageComponent extends JComponent {
private static final long serialVersionUID = 1L;
private Icon icon; public ImageComponent(Icon icon) {
this.icon = icon;
} public void setIcon(Icon icon) {
this.icon = icon;
} public void paintComponent(Graphics g) {
super.paintComponent(g);
int w = icon.getIconWidth();
int h = icon.getIconHeight();
int x = (800 - w)/2;
int y = (600 - h)/2;
icon.paintIcon(this, g, x, y);
}
}

3.

 package headfirst.designpatterns.proxy.virtualproxy;

 import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.*;
import javax.swing.*;
import java.util.*; public class ImageProxyTestDrive {
ImageComponent imageComponent;
JFrame frame = new JFrame("CD Cover Viewer");
JMenuBar menuBar;
JMenu menu;
Hashtable<String, String> cds = new Hashtable<String, String>(); public static void main (String[] args) throws Exception {
ImageProxyTestDrive testDrive = new ImageProxyTestDrive();
} public ImageProxyTestDrive() throws Exception{
cds.put("Buddha Bar","http://images.amazon.com/images/P/B00009XBYK.01.LZZZZZZZ.jpg");
cds.put("Ima","http://images.amazon.com/images/P/B000005IRM.01.LZZZZZZZ.jpg");
cds.put("Karma","http://images.amazon.com/images/P/B000005DCB.01.LZZZZZZZ.gif");
cds.put("MCMXC A.D.","http://images.amazon.com/images/P/B000002URV.01.LZZZZZZZ.jpg");
cds.put("Northern Exposure","http://images.amazon.com/images/P/B000003SFN.01.LZZZZZZZ.jpg");
cds.put("Selected Ambient Works, Vol. 2","http://images.amazon.com/images/P/B000002MNZ.01.LZZZZZZZ.jpg"); URL initialURL = new URL((String)cds.get("Selected Ambient Works, Vol. 2"));
menuBar = new JMenuBar();
menu = new JMenu("Favorite CDs");
menuBar.add(menu);
frame.setJMenuBar(menuBar); for (Enumeration<String> e = cds.keys(); e.hasMoreElements();) {
String name = (String)e.nextElement();
JMenuItem menuItem = new JMenuItem(name);
menu.add(menuItem);
menuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
imageComponent.setIcon(new ImageProxy(getCDUrl(e.getActionCommand())));
frame.repaint();
}
});
} // set up frame and menus Icon icon = new ImageProxy(initialURL);
imageComponent = new ImageComponent(icon);
frame.getContentPane().add(imageComponent);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800,600);
frame.setVisible(true); } URL getCDUrl(String name) {
try {
return new URL((String)cds.get(name));
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
}
}
}

六、动态代理分析

1.

2.The job of the InvocationHandler is to respond to any method calls on the proxy. Think of the InvocationHandler as the

object the Proxy asks to do all the real work after it’s received the method calls.

3.The Decorator Pattern adds behavior to an object, while a Proxy controls access.

七、动态代理实现

1.

 package headfirst.designpatterns.proxy.javaproxy;

 public interface PersonBean {

     String getName();
String getGender();
String getInterests();
int getHotOrNotRating(); void setName(String name);
void setGender(String gender);
void setInterests(String interests);
void setHotOrNotRating(int rating); }

2.

 package headfirst.designpatterns.proxy.javaproxy;

 public class PersonBeanImpl implements PersonBean {
String name;
String gender;
String interests;
int rating;
int ratingCount = 0; public String getName() {
return name;
} public String getGender() {
return gender;
} public String getInterests() {
return interests;
} public int getHotOrNotRating() {
if (ratingCount == 0) return 0;
return (rating/ratingCount);
} public void setName(String name) {
this.name = name;
} public void setGender(String gender) {
this.gender = gender;
} public void setInterests(String interests) {
this.interests = interests;
} public void setHotOrNotRating(int rating) {
this.rating += rating;
ratingCount++;
}
}

3.

 package headfirst.designpatterns.proxy.javaproxy;

 import java.lang.reflect.*;

 public class NonOwnerInvocationHandler implements InvocationHandler {
PersonBean person; public NonOwnerInvocationHandler(PersonBean person) {
this.person = person;
} public Object invoke(Object proxy, Method method, Object[] args)
throws IllegalAccessException { try {
if (method.getName().startsWith("get")) {
return method.invoke(person, args);
} else if (method.getName().equals("setHotOrNotRating")) {
return method.invoke(person, args);
} else if (method.getName().startsWith("set")) {
throw new IllegalAccessException();
}
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}

4.

 package headfirst.designpatterns.proxy.javaproxy;

 import java.lang.reflect.*;

 public class OwnerInvocationHandler implements InvocationHandler {
PersonBean person; public OwnerInvocationHandler(PersonBean person) {
this.person = person;
} public Object invoke(Object proxy, Method method, Object[] args)
throws IllegalAccessException { try {
if (method.getName().startsWith("get")) {
return method.invoke(person, args);
} else if (method.getName().equals("setHotOrNotRating")) {
throw new IllegalAccessException();
} else if (method.getName().startsWith("set")) {
return method.invoke(person, args);
}
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}

5.

 package headfirst.designpatterns.proxy.javaproxy;

 import java.lang.reflect.*;
import java.util.*; public class MatchMakingTestDrive {
HashMap<String, PersonBean> datingDB = new HashMap<String, PersonBean>(); public static void main(String[] args) {
MatchMakingTestDrive test = new MatchMakingTestDrive();
test.drive();
} public MatchMakingTestDrive() {
initializeDatabase();
} public void drive() {
PersonBean joe = getPersonFromDatabase("Joe Javabean");
PersonBean ownerProxy = getOwnerProxy(joe);
System.out.println("Name is " + ownerProxy.getName());
ownerProxy.setInterests("bowling, Go");
System.out.println("Interests set from owner proxy");
try {
ownerProxy.setHotOrNotRating(10);
} catch (Exception e) {
System.out.println("Can't set rating from owner proxy");
}
System.out.println("Rating is " + ownerProxy.getHotOrNotRating()); PersonBean nonOwnerProxy = getNonOwnerProxy(joe);
System.out.println("Name is " + nonOwnerProxy.getName());
try {
nonOwnerProxy.setInterests("bowling, Go");
} catch (Exception e) {
System.out.println("Can't set interests from non owner proxy");
}
nonOwnerProxy.setHotOrNotRating(3);
System.out.println("Rating set from non owner proxy");
System.out.println("Rating is " + nonOwnerProxy.getHotOrNotRating());
} PersonBean getOwnerProxy(PersonBean person) { return (PersonBean) Proxy.newProxyInstance(
person.getClass().getClassLoader(),
person.getClass().getInterfaces(),
new OwnerInvocationHandler(person));
} PersonBean getNonOwnerProxy(PersonBean person) { return (PersonBean) Proxy.newProxyInstance(
person.getClass().getClassLoader(),
person.getClass().getInterfaces(),
new NonOwnerInvocationHandler(person));
} PersonBean getPersonFromDatabase(String name) {
return (PersonBean)datingDB.get(name);
} void initializeDatabase() {
PersonBean joe = new PersonBeanImpl();
joe.setName("Joe Javabean");
joe.setInterests("cars, computers, music");
joe.setHotOrNotRating(7);
datingDB.put(joe.getName(), joe); PersonBean kelly = new PersonBeanImpl();
kelly.setName("Kelly Klosure");
kelly.setInterests("ebay, movies, music");
kelly.setHotOrNotRating(6);
datingDB.put(kelly.getName(), kelly);
}
}

6.

HeadFirst设计模式之代理模式的更多相关文章

  1. C#设计模式(13)——代理模式(Proxy Pattern)

    一.引言 在软件开发过程中,有些对象有时候会由于网络或其他的障碍,以至于不能够或者不能直接访问到这些对象,如果直接访问对象给系统带来不必要的复杂性,这时候可以在客户端和目标对象之间增加一层中间层,让代 ...

  2. 乐在其中设计模式(C#) - 代理模式(Proxy Pattern)

    原文:乐在其中设计模式(C#) - 代理模式(Proxy Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 代理模式(Proxy Pattern) 作者:webabcd 介绍 为 ...

  3. Java设计模式之代理模式(静态代理和JDK、CGLib动态代理)以及应用场景

    我做了个例子 ,需要可以下载源码:代理模式 1.前言: Spring 的AOP 面向切面编程,是通过动态代理实现的, 由两部分组成:(a) 如果有接口的话 通过 JDK 接口级别的代理 (b) 如果没 ...

  4. 设计模式之代理模式之二(Proxy)

    from://http://www.cnblogs.com/xwdreamer/archive/2012/05/23/2515306.html 设计模式之代理模式之二(Proxy)   0.前言 在前 ...

  5. 夜话JAVA设计模式之代理模式(Proxy)

    代理模式定义:为另一个对象提供一个替身或者占位符以控制对这个对象的访问.---<Head First 设计模式> 代理模式换句话说就是给某一个对象创建一个代理对象,由这个代理对象控制对原对 ...

  6. GOF23设计模式之代理模式

    GOF23设计模式之代理模式 核心作用:通过代理,控制对对象的访问.可以详细控制访问某个(某类)对象的方法,在调用这个方法前做前置处理,调用这个方法后做后置处理(即:AOP的微观实现) AOP(Asp ...

  7. C#设计模式:代理模式(Proxy Pattern)

    一,什么是C#设计模式? 代理模式(Proxy Pattern):为其他对象提供一种代理以控制对这个对象的访问 二,代码如下: using System; using System.Collectio ...

  8. js设计模式——1.代理模式

    js设计模式——1.代理模式 以下是代码示例 /*js设计模式——代理模式*/ class ReadImg { constructor(fileName) { this.fileName = file ...

  9. java设计模式6——代理模式

    java设计模式6--代理模式 1.代理模式介绍: 1.1.为什么要学习代理模式?因为这就是Spring Aop的底层!(SpringAop 和 SpringMvc) 1.2.代理模式的分类: 静态代 ...

随机推荐

  1. DataX的简单编译安装测试

    搭建环境:     Java > =1.6     Python>=2.6 <3     Ant     Rpmbuild     G++     编译DataX: 进入rpm文件夹 ...

  2. OpenCV基本架构[OpenCV 笔记0]

    最近正在系统学习OpenCV,将不定期发布笔记,主要按照毛星云的<OpenCV3编程入门>的顺序学习,会参考官方教程和文档.学习工具是Xcode+CMake,会对书中一部分内容更正,并加入 ...

  3. 【转】TCP的SEQ和ACK的生成

    TCP序列号和确认号详解 完整的PDF下载: 在网络分析中,读懂TCP序列号和确认号在的变化趋势,可以帮助我们学习TCP协议以及排查通讯故障,如通过查看序列号和确认号可以确定数据传输是否乱序.但我在查 ...

  4. C++与Lua交互(一)

    引言 之前做手游项目时,客户端用lua做脚本,基本所有游戏逻辑都用它完成,玩起来有点不爽,感觉"太重"了.而我又比较偏服务端这边(仅有C++),所以热情不高.最近,加入了一个端游项 ...

  5. input内容改变触发事件,兼容IE

    <html> <head> <script type="text/javascript"> window.onload = function() ...

  6. 《编写高质量代码-Web前端开发修改之道》笔记--第一章 从网站重构说起

    本章内容: 糟糕的页面实现,头疼的维护工作 Web标准--结构.样式和行为的分离 前端的现状 打造高品质的前端代码,提高代码的可维护性--精简.重用.有序 糟糕的页面实现,头疼的维护工作 工作中最大的 ...

  7. jquery ListBox 左右移动

    <head runat="server"> <title>无标题页</title> <script type="text/jav ...

  8. 禁止指定目录执行php文件

    我们设置网站权限的时候,有些目录不得不设置让http服务器有写入权限,这样安全隐患就来了.比如discuz x2的 data目录,这个必须要有写入限,论坛才能正常运行,但有的黑客可能就会利用这个目录上 ...

  9. 关于B/S系统中文件上传的大小限制怎么做

    1.前端:采用flash控件或者Html5的特性(有浏览器版本要求)来判断文件大小.纯html或js是没法判断用户上传文件大小的. 2.nginx:服务器端的第一道防线,一般会有对上传文件做大小限制. ...

  10. WordPress非插件添加文章浏览次数统计功能

    一: 转载:http://www.jiangyangangblog.com/26.html 首先在寻找到functions.php.php文件夹,在最后面  ?> 的前面加入下面的代码 func ...