如果我们有一个界面有很多请求,但这时候所有的请求都无效,这是我们可能会提示用户 “请求失败”,“请求超时“等等,
如果提示一次那当然很好,但是每一个失败的请求都触发一次提示框来提示用户,这样会很糟糕。
可能一次弹出很多提示框,我们点击一次然后又弹出另一个,并且这些提示信息还是一样的,这样会让用户很恼火的。
假设某家公司有两个不同的数据库A 和B,但是A是内网的,B是现网的,我们在A中注册下,然后把信息保存,这时候我们修改地址指向B,可能会出现问题。
如果我们访问了需要提供access token 的资源,我们需要提供access token ,但是这个access token 在A中是有效的,在B中是无效的。
所以服务端可能会返回 “无效的access token”等。
可是我们已经登陆了啊,咋办呢?
我们可以根据具体的情况,重新弹出登陆界面,当然这只是一个例子,我们可以用这样的方法处理其他类似的情况。
1 用dispatch once
这个不说了
2 用工厂类方法
#import <UIKit/UIKit.h>
@interface PresentLogInVC : UIViewController
+(void)appearLogInVC;
@end
#import "PresentLogInVC.h"
static UINavigationController *_navController;
static PresentLogInVC *_viewController;
@interface PresentLogInVC ()
{
}
@end
@implementation PresentLogInVC
+(void)appearLogInVC
{
if (!_navController)
{
_viewController=[[self alloc]init];
_navController=[[UINavigationController alloc]initWithRootViewController:_viewController];
[_viewController show];
}
else
{
NSLog(@"have appeared !!!");
}
}
-(void)show
{
UIWindow *window=[[[UIApplication sharedApplication] windows] objectAtIndex:0];
[window addSubview: _navController.view];
__block CGRect r=[[UIScreen mainScreen]bounds];
r.origin.y=r.size.height;
[_navController.view setFrame:r];
[UIView animateWithDuration:0.3 animations:^{
r.origin.y=0;
[_navController.view setFrame:r];
}];
}
-(void)dismiss
{
[UIView animateWithDuration:0.3 animations:^{
CGRect r=[[UIScreen mainScreen]bounds];
r.origin.y=r.size.height;
[_navController.view setFrame:r];
} completion:^(BOOL b){
[_navController.view removeFromSuperview];
}];
}
-(void)viewDidLoad
{
[super viewDidLoad];
self.title=@"登陆";
UIBarButtonItem * leftItem = [[UIBarButtonItem alloc] initWithTitle:@"dismiss" style:UIBarButtonItemStyleDone target:self action:@selector(dismiss)];
[self.navigationItem setLeftBarButtonItem:leftItem];
self.view.backgroundColor=[UIColor grayColor];
}
-(void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[_navController release];
_navController=nil;
[_viewController release];
_viewController =nil;
}
@end
多线程
多进程
每个进程间拥有独立的内存空间
0~4G
单核
系统将cpu所有时间分割为相同的时间片
有内核负责调度
线程属于进程内部
进程内部的所有线程共享进程的内存
让一个进程拥有同时执行多段代码的能力
java中的线程有jvm线程调度器负责调度
线程控制
start() 启动线程
interrupt() 中断线程,唤醒正在休眠线程
检测当前线程是否被中断
isInterrupted() 只检查中断标志
interrupted() 检查并清除中断标志
Thread.sleep() 线程休眠,清除当前中断标志
Thread.currentThread() 获取当前线程对象
getPriority() 获取线程优先级
setPriority() 修改线程优先级,linux没有实现
容易造成死锁
stop() 停止
suspend() 挂起
destory()
resume()
锁
线程交互
线程等待
进程是程序运行的最小单位。
线程是CPU调度的最小单位。
Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。
一般Singleton模式通常有几种种形式:
第一种形式: 定义一个类,它的构造函数为private的,它有一个static的private的该类变量,在类初始化时实例话,通过一个public的getInstance方法获取对它的引用,继而调用其中的方法。
public class Singleton {
private Singleton(){}
//在自己内部定义自己一个实例,是不是很奇怪?
//注意这是private 只供内部调用
private static Singleton instance = new Singleton();
//这里提供了一个供外部访问本class的静态方法,可以直接访问
public static Singleton getInstance() {
return instance;
}
}
第二种形式:
public class Singleton {
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
//这个方法比上面有所改进,不用每次都进行生成对象,只是第一次
//使用时生成实例,提高了效率!
if (instance==null)
instance=new Singleton();
return instance; }
}
其他形式:
定义一个类,它的构造函数为private的,所有方法为static的。
一般认为第一种形式要更加安全些
线程同步的方法。
wait():使一个线程处于等待状态,并且释放所持有的对象的lock。
sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。
notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。
Allnotity():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。
线程的基本概念、线程的基本状态以及状态之间的关系
线程指在程序执行过程中,能够执行程序代码的一个执行单位,每个程序至少都有一个线程,也就是程序本身。
Java中的线程有四种状态分别是:运行、就绪、挂起、结束。
synchronized和java.util.concurrent.locks.Lock的异同 ?
主要相同点:Lock能完成synchronized所实现的所有功能
主要不同点:Lock有比synchronized更精确的线程语义和更好的性能。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放。
Java中的23种设计模式:
Factory(工厂模式), Builder(建造模式), Factory Method(工厂方法模式),
Prototype(原始模型模式),Singleton(单例模式), Facade(门面模式),
Adapter(适配器模式), Bridge(桥梁模式), Composite(合成模式),
Decorator(装饰模式), Flyweight(享元模式), Proxy(代理模式),
Command(命令模式), Interpreter(解释器模式), Visitor(访问者模式),
Iterator(迭代子模式), Mediator(调停者模式), Memento(备忘录模式),
Observer(观察者模式), State(状态模式), Strategy(策略模式),
Template Method(模板方法模式), Chain Of Responsibleity(责任链模式)
IO流
1.what?
流的概念来自Unix的管道,在Unix中,管道是一条不间断的字节流,
用来实现进程间通讯,或者读写外围设备,文件等.
2.一个流,一定会有一个源端和目标端,它们分别可以是计算机内存的某个区域,
也可以是磁盘文件,或者是网络上的某个URL
3.流的方向,根据流的方向,流可以分为两类,流的方向是固定并且是不可逆的
1)输入流 只能读,不能写
2)输出流 只能写,不能读
4.java api
可以读入一个字节的流, 称为输入流
可以写入一个字节的流,称为输出流
5.流的分类,
节点流(低级流):从特定地方读写的流
过滤流(高级流):使用节点流作为输入输出
6.
字节流:操作的内容为字节 InputStream/OuputStream
字符流:操作的内容为字符 Reader/Writer
特性
Struts1.x
Struts2
Action类
Struts1.x要求Action类要扩展自一个抽象基类。Struts1.x的一个共有的问题是面向抽象类编程而不是面向接口编程。
Struts2的Action类实现了一个Action接口,连同其他接口一起来实现可选择和自定义的服务。Struts2提供一个名叫ActionSupport的基类来实现一般使用的接口。当然,Action接口不是必须的。任何使用execute方法的POJO对象可以被当作Struts 2的Action对象来使用。
线程模型
Struts1.x Action类是单例类,因为只有一个实例来控制所有的请求。单例类策略造成了一定的限制,并且给开发带来了额外的烦恼。Action资源必须是线程安全或者同步的。
Struts2 Action对象为每一个请求都实例化对象,所以没有线程安全的问题。(实践中,servlet容器给每一个请求产生许多丟弃的对象,并且不会导致性能和垃圾回收问题)。
Servlet 依赖
Struts1.x的Action类依赖于servlet API,当Action被调用时,以HttpServletRequest和HttpServletResponse作为参数传给execute方法。
Struts2的Action和容器无关。Servlet上下文被表现为简单的Maps,允许Action被独立的测试。Struts2的Action可以访问最初的请求(如果需要的话)。但是,尽可能避免或排除其他元素直接访问HttpServletRequest或HttpServletResponse。
易测性
测试Struts1.x的主要问题是execute方法暴露了Servlet API这使得测试要依赖于容器)。第三方的扩展,如Struts TestCase,提供了一套Struts1的模拟对象(来进行测试)。
Struts2的Action可以通过初始化、设置属性、调用方法来测试。依赖注入的支持也是测试变得更简单。
捕获输入
Struts1.x使用ActionForm对象来捕获输入。象Action一样,所有的ActionForm必须扩展基类。因为其他的JavaBean不能作为ActionForm使用,开发者经常创建多余的类来捕获输入。DynaBeans可以被用来作为替代ActionForm的类来创建。但是,开发者可能是在重新描述(创建)已经存在的JavaBean(仍然会导致有冗余的javabean)。
Struts2直接使用Action属性作为输入属性,消除了对第二个输入对象的需求。输入属性可能是有自己(子)属性的rich对象类型。Action属性能够通过web页面上的taglibs访问。Struts2也支持ActionForm模式。rich对象类型,包括业务对象,能够用作输入/输出对象。这种ModelDriven 特性简化了taglib对POJO输入对象的引用。
表达式语言
Struts1.x整合JSTL,所以它使用JSTL的表达式语言。表达式语言有基本的图形对象移动,但是对集合和索引属性的支持很弱。
Struts2使用JSTL,但是也支持一个更强大和灵活的表达式语言--"Object Graph Notation Language" (OGNL)。
将值绑定到页面
Struts1.x使用标准JSP机制来绑定对象到页面上下文。
Struts2使用“ValueStack”技术,使taglib能够访问值而不需要把你的页面(view)和对象绑定起来。ValueStack策略允许通过一系列名称相同但类型不同的属性重用页面(view)。
类型转换
Struts1.x的ActionForm属性经常都是String。Struts 1.x使用Commons-Beanutils来进行类型转换。转换每一个类,而不是为每一个实例配置。
Struts2使用OGNL进行类型转换。提供基本和常用对象的转换器。
验证
Struts1.x支持在ActionForm的validate方法中手动校验,或者通过Commons Validator的扩展来校验。同一个类可以有不同的校验内容,但不能校验子对象。
Struts2支持通过validate方法和XWork校验框架来进行校验。XWork校验框架使用为属性类类型定义的校验和内容校验,来支持chain校验子属性
Action执行控制
Struts1.x支持每一个模块有单独的Request Processors(生命周期),但是模块中的所有Action必须共享相同的生命周期。
Struts2支持通过拦截器堆栈(Interceptor Stacks)为每一个Action创建不同的生命周期。堆栈能够根据需要和不同的Action一起使用。
结论
前面已经简要介绍了Struts2的起源,并详细对比了Struts2和Struts1.x的差异,读者应该对Struts2的基础有所了解了——包括高层的框架概念和基础的请求流程,并理解Struts1.x和Struts2两者之间在Action方面的差别,Struts2加强了对拦截器与IoC的支持,而在Struts1.x中,这些特性是很难想象的。
同时,读者应该明白:Struts2是WebWork的升级,而不是Struts 1.x的升级。虽然Struts 2提供了与Struts1.x的兼容,但已经不是Struts1.x的升级。对于已有Struts1.x开发经验的开发者而言,Struts1.x的开发经验对于Struts2并没有太大的帮助;相反,对于已经有WebWork开发经验的开发者而言,WebWork的开发经验对Struts2的开发将有很好的借鉴意义