yii第一个应用blog
1. 连接到数据库
大多数 Web 应用由数据库驱动,我们的测试应用也不例外。要使用数据库,我们首先需要告诉应用如何连接它。修改应用的配置文件 WebRoot/testdrive/protected/config/main.php
即可,如下所示:
return array(
......
'components'=>array(
......
'db'=>array(
'connectionString'=>'sqlite:protected/data/source.db',
),
),
......
);
上面的代码告诉 Yii 应用在需要时将连接到 SQLite 数据库。
如何使用mysql:
Tip: If you want to use MySQL instead of SQLite to store data, you may cre-
ate a MySQL database named blog using the SQL statements in /wwwroot/yii/
demos/blog/protected/data/schema.mysql.sql. Then, modify the application
conguration as follows,
return array(
......
'components'=>array(
......
'db'=>array(
'connectionString' => 'mysql:host=localhost;dbname=blog',
'emulatePrepare' => true,
'username' => 'root',
'password' => '',
'charset' => 'utf8',
'tablePrefix' => 'tbl ',
),
),
......
);
2. 实现 CRUD 操作
激动人心的时刻来了。我们想要为刚才建立的 tbl_user
表实现 CRUD (create, read, update 和 delete) 操作,这也是实际应用中最常见的操作。我们无需麻烦地编写实际代码,这里我们将使用 Gii
—— 一个强大的基于Web 的代码生成器。
配置Gii
为了使用 Gii,首先需要编辑文件 WebRoot/testdrive/protected/main.php
,这是已知的 应用配置 文件:
return array(
......
'import'=>array(
'application.models.*',
'application.components.*',
), 'modules'=>array(
'gii'=>array(
'class'=>'system.gii.GiiModule',
'password'=>'pick up a password here',
),
),
);
然后,访问 URL http://hostname/testdrive/index.php?r=gii
。这里我们需要输入密码,它是在我们在上面的配置中指定的。
生成 User 模型
登陆后,点击链接 Model Generator
。它将显示下面的模型生成页面,
在 Table Name
输入框中,输入 tbl_user
。在 Model Class
输入框中,输入 User
。然后点击 Preview
按钮。这里将展示将要生成的新文件。现在点击 Generate
按钮。一个名为 User.php
将生成到protected/models
目录中。如我们稍后描述的, User
模型类允许我们以面向对象的方式来访问数据表tbl_user
。
Repeat the same procedure for the rest of the database tables, including tbl post, tbl
comment, tbl tag and tbl lookup.
Tip: We can also enter an asterisk character * in the Table Name Field. This will
generate a model class for every database table in a single shot.
3. Implementing CRUD Operations
After the model classes are created, we can use the Crud Generator to generate the code
implementing the CRUD operations for these models. We will do this for the Post and
Comment models.
On the Crud Generator page, enter Post (the name of the post model class we just created)
in the Model Class eld, and then press the Preview button. We will see a lot more les
will be generated. Press the Generate button to generate them.
Repeat the same procedure for the Comment model.
Let's take a look at the files generated by the CRUD generator. All the files are generated
under /wwwroot/blog/protected. For convenience, we group them into controller files and
view files:
Testing
We can test the features implemented by the code we just generated by accessing the
following URLs:
http://www.example.com/blog/index.php?r=post
http://www.example.com/blog/index.php?r=comment
主要post和comment,由于代码是自动生成的,所以2者还没有关联起来。
Authenticating User
Our blog application needs to differentiate between the system owner and guest users.
Therefore, we need to implement the user authentication feature.As you may have found that the skeleton application already provides user authentication by checking if the username and password are both demo or admin. In this section, we
will modify the corresponding code so that the authentication is done against the User database table.
User authentication is performed in a class implementing the [IUserIdentity] interface.
The skeleton application uses the UserIdentity class for this purpose. The class is stored
in the file /wwwroot/blog/protected/components/UserIdentity.php.
Tip: By convention, the name of a class file must be the same as the corresponding
class name suffixed with the extension .php. Following this convention, one can
refer to a class using a path alias. For example, we can refer to the UserIdentity
class with the alias application.components.UserIdentity. Many APIs in Yii
can recognize path aliases (e.g. Yii::createComponent()), and using path aliases
avoids the necessity of embedding absolute file paths in the code. The existence of
the latter often causes trouble when we deploy an application.
默认的代码如下:
class UserIdentity extends CUserIdentity
{
/**
* Authenticates a user.
* The example implementation makes sure if the username and password
* are both 'demo'.
* In practical applications, this should be changed to authenticate
* against some persistent user identity storage (e.g. database).
* @return boolean whether authentication succeeds.
*/
public function authenticate()
{
$users=array(
// username => password
'demo'=>'demo',
'admin'=>'admin',
);
if(!isset($users[$this->username]))
$this->errorCode=self::ERROR_USERNAME_INVALID;
elseif($users[$this->username]!==$this->password)
$this->errorCode=self::ERROR_PASSWORD_INVALID;
else
$this->errorCode=self::ERROR_NONE;
return !$this->errorCode;
}
}
我们将 UserIdentity
类做如下修改,
<?php
class UserIdentity extends CUserIdentity
{
private $_id; public function authenticate()
{
$username=strtolower($this->username);
$user=User::model()->find('LOWER(username)=?',array($username));
if($user===null)
$this->errorCode=self::ERROR_USERNAME_INVALID;
else if(!$user->validatePassword($this->password))
$this->errorCode=self::ERROR_PASSWORD_INVALID;
else
{
$this->_id=$user->id;
$this->username=$user->username;
$this->errorCode=self::ERROR_NONE;
}
return $this->errorCode==self::ERROR_NONE;
} public function getId()
{
return $this->_id;
}
}
在 authenticate()
方法中,我们使用 User
类来查询 tbl_user
表中 username
列值(不区分大小写)和提供的用户名一致的一行,请记住 User
类是在前面的章节中通过 gii
工具创建的。由于 User
类继承自CActiveRecord ,我们可以利用 ActiveRecord 功能 以 OOP 的风格访问 tbl_user
表。
为了检查用户是否输入了一个有效的密码,我们调用了 User
类的 validatePassword
方法。我们需要按下面的代码修改 /wwwroot/blog/protected/models/User.php
文件。注意,我们在数据库中存储了密码的加密串和随机生成的SALT密钥,而不是存储明文密码。 所以当要验证用户输入的密码时,我们应该和加密结果做对比。
class User extends CActiveRecord
{
......
public function validatePassword($password)
{
return $this->hashPassword($password,$this->salt)===$this->password;
} public function hashPassword($password,$salt)
{
return md5($salt.$password);
}
}
在 UserIdentity
类中,我们还覆盖(Override,又称为重写)了 getId()
方法,它会返回在 User
表中找到的用户的 id
。父类 (CUserIdentity) 则会返回用户名。username
和 id
属性都将存储在用户 SESSION 中,可在代码的任何部分通过 Yii::app()->user
访问。
提示: 在
UserIdentity
类中,我们没有显式包含(include)相应的类文件就访问了 CUserIdentity 类,这是因为 CUserIdentity 是一个由Yii框架提供的核心类。Yii 将会在任何核心类被首次使用时自动包含类文件。我们也对
User
类做了同样的事情。这是因为User
类文件被放在了/wwwroot/blog/protected/models
目录,此目录已经通过应用配置中的如下几行代码被添加到了 PHP 的include_path
中:return array(
......
'import'=>array(
'application.models.*',
'application.components.*',
),
......
);上面的配置说明,位于
/wwwroot/blog/protected/models
或/wwwroot/blog/protected/components
目录中的任何类将在第一次使用时被自动包含。
UserIdentity
类主要用于 LoginForm
类中,它基于用户名和从登录页中收到的密码来实现用户验证。下面的代码展示了 UserIdentity
的使用:
$identity=new UserIdentity($username,$password);
$identity->authenticate();
switch($identity->errorCode)
{
case UserIdentity::ERROR_NONE:
Yii::app()->user->login($identity);
break;
......
}
信息: 人们经常对 identity 和
user
应用组件感到困惑,前者代表的是一种验证方法,后者代表当前用户相关的信息。一个应用只能有一个user
组件,但它可以有一个或多个 identity 类,这取决于它支持什么样的验证方法。一旦验证通过,identity 实例会把它自己的状态信息传递给user
组件,这样它们就可以通过user
实现全局可访问。
model中rules()
方法中定义的规则会在模型实例调用其 validate() 或 save() 方法时逐一执行。注意: 请务必记住 rules()
中出现的属性必须是那些通过用户输入的属性。其他的属性,如 Post
模型中的 id
和 create_time
,是通过我们的代码或数据库设定的,不应该出现在 rules()
中。详情请参考 属性的安全赋值(Securing Attribute Assignments).
自定义 relations()
方法
最后我们来自定义 relations()
方法,以指定与日志相关的对象。通过在 relations()
中声明这些相关对象,我们就可以利用强大的 Relational ActiveRecord (RAR) 功能来访问日志的相关对象,例如它的作者和评论。不需要自己写复杂的 SQL JOIN 语句。
我们自定义 relations()
方法如下:
public function relations()
{
return array(
'author' => array(self::BELONGS_TO, 'User', 'author_id'),
'comments' => array(self::HAS_MANY, 'Comment', 'post_id',
'condition'=>'comments.status='.Comment::STATUS_APPROVED,
'order'=>'comments.create_time DESC'),
'commentCount' => array(self::STAT, 'Comment', 'post_id',
'condition'=>'status='.Comment::STATUS_APPROVED),
);
}
我们还在 Comment
模型类中定义了两个在上面的方法中用到的常量。
class Comment extends CActiveRecord
{
const STATUS_PENDING=1;
const STATUS_APPROVED=2;
......
}
relations()
中声明的关系表明:
- 一篇日志属于一个作者,它的类是
User
,它们的关系建立在日志的author_id
属性值之上; - 一篇日志有多个评论,它们的类是
Comment
,它们的关系建立在评论的post_id
属性值之上。这些评论应该按它们的创建时间排列,且评论必须已通过审核; commentCount
关系有一点特别,它返回一个关于日志有多少条评论的一个聚合结果。
通过以上的关系声明,我们现在可以按下面的方式很容易的访问日志的作者和评论信息。
$author=$post->author;
echo $author->username; $comments=$post->comments;
foreach($comments as $comment)
echo $comment->content;
关于如何声明和使用关系的更多详情,请参考 指南.
class Post extends CActiveRecord
{
public function getUrl()
{
return Yii::app()->createUrl('post/view', array(
'id'=>$this->id,
'title'=>$this->title,
));
}
}
注意我们除了使用日志的ID之外,还添加了日志的标题作为URL中的一个 GET 参数。这主要是为了搜索引擎优化 (SEO) 的目的,在 美化 URL 中将会讲述。
由于 CComponent 是 Post
的最顶级父类,添加 getUrl()
这个 getter 方法使我们可以使用类似 $post->url
这样的表达式。当我们访问 $post->url
时,getter 方法将会被执行,它的返回结果会成为此表达式的值。关于这种组件的更多详情,请参考 指南。
postController中access rules:
accessRules()
我们将 /wwwroot/blog/protected/controllers/PostController.php
文件中的 accessRules()
方法修改如下:
public function accessRules()
{
return array(
array('allow', // allow all users to perform 'list' and 'show' actions
'actions'=>array('index', 'view'),
'users'=>array('*'),
),
array('allow', // allow authenticated users to perform any action
'users'=>array('@'),
),
array('deny', // deny all users
'users'=>array('*'),
),
);
}
上面的规则说明:所有用户均可访问 index
和 view
动作,已通过身份验证的用户可以访问任意动作,包括admin
动作。在其他场景中,应禁止用户访问。注意这些规则将会按它们在此列出的顺序计算。第一条匹配当前场景的规则将决定访问权。例如,如果当前用户是系统所有者,他想尝试访问日志创建页,第二条规则将匹配成功并授予此用户权限。
2. 自定义 创建
和 更新
操作
创建
和 更新
操作非常相似。他们都需要显示一个HTML表单用于收集用户的输入的信息,然后对其进行验证,然后将其存入数据库。主要的不同是 更新
操作需要把从数据库找到的已存在的日志数据重现在表单中。鉴于此,yiic
工具创建了一个局部视图 /wwwroot/blog/protected/views/post/_form.php
,它会插入 创建
和更新
视图来渲染所需的HTML表单。
我们先修改 _form.php
这个文件,使这个HTML表单只收集我们想要的输入:title
, content
, tags
和status
。我们使用文本域收集前三个属性的输入,还有一个下拉列表用来收集 status
的输入。此下拉列表的选项值就是可用的日志状态文本。
<?php echo $form->dropDownList($model,'status',Lookup::items('PostStatus')); ?>
在上面的代码中,我们调用了 Lookup::items('PostStatus')
以带回日志状态列表。
然后我们修改 Post
类,使它可以在日志被存入数据库前自动设置几个属性 (例如 create_time
, author_id
)。我们覆盖 beforeSave()
方法如下:
protected function beforeSave()
{
if(parent::beforeSave())
{
if($this->isNewRecord)
{
$this->create_time=$this->update_time=time();
$this->author_id=Yii::app()->user->id;
}
else
$this->update_time=time();
return true;
}
else
return false;
}
当我们保存日志时,我们想更新 tbl_tag
表以反映 Tag 的使用频率。我们可以在 afterSave()
方法中完成此工作,它会在日志被成功存入数据库后自动被Yii调用。
protected function afterSave()
{
parent::afterSave();
Tag::model()->updateFrequency($this->_oldTags, $this->tags);
} private $_oldTags; protected function afterFind()
{
parent::afterFind();
$this->_oldTags=$this->tags;
}
在这个实现中,因为我们想检测出用户在更新现有日志的时候是否修改了 Tag ,我们需要知道原来的 Tag 是什么, 鉴于此,我们还写了一个 afterFind()
方法把原有的 Tag 信息保存到变量 _oldTags
中。方法 afterFind()
会在一个 AR 记录被数据库中的数据填充时自动被 Yii 调用。
这里我们不再列出 Tag::updateFrequency()
方法的细节,读者可以参考/wwwroot/yii/demos/blog/protected/models/Tag.php
文件。
控制器
自定义 view
操作
view
操作是通过 PostController
中的 actionView()
方法实现的。它的显示是通过 view
视图文件/wwwroot/blog/protected/views/post/view.php
生成的。
下面是在 PostController
中实现 view
操作的具体代码:
public function actionView()
{
$post=$this->loadModel();
$this->render('view',array(
'model'=>$post,
));
} private $_model; public function loadModel()
{
if($this->_model===null)
{
if(isset($_GET['id']))
{
if(Yii::app()->user->isGuest)
$condition='status='.Post::STATUS_PUBLISHED
.' OR status='.Post::STATUS_ARCHIVED;
else
$condition='';
$this->_model=Post::model()->findByPk($_GET['id'], $condition);
}
if($this->_model===null)
throw new CHttpException(404,'The requested page does not exist.');
}
return $this->_model;
}
2. 自定义 index
操作
和 view
操作类似,我们在两处自定义 index
操作:PostController
中的 actionIndex()
方法和视图文件/wwwroot/blog/protected/views/post/index.php
。我们主要需要添加对显示一个特定Tag下的日志列表的支持;
下面就是在 PostController
中对 `actionIndex() 方法作出的修改:
public function actionIndex()
{
$criteria=new CDbCriteria(array(
'condition'=>'status='.Post::STATUS_PUBLISHED,
'order'=>'update_time DESC',
'with'=>'commentCount',
));
if(isset($_GET['tag']))
$criteria->addSearchCondition('tags',$_GET['tag']); $dataProvider=new CActiveDataProvider('Post', array(
'pagination'=>array(
'pageSize'=>5,
),
'criteria'=>$criteria,
)); $this->render('index',array(
'dataProvider'=>$dataProvider,
));
}
在上面的代码中,我们首先为检索日志列表创建了一个查询标准(criteria),此标准规定只返回已发布的日志,且应该按其更新时间倒序排列。因为我们打算在显示日志列表的同时显示日志收到的评论数量,因此在这个标准中我们还指定了要带回 commentCount
, 如果你还记得,它就是在 Post::relations()
中定义的一个关系。
考虑到当用户想查看某个Tag下的日志列表时的情况,我们还要为指定的Tag添加一个搜索条件到上述标准中。
使用这个查询标准,我们创建了一个数据提供者(data provider)。这主要出于三个目的。第一,它会在查询结果过多时实现数据分页。这里我们定义分页的页面大小为5。 第二,它会按用户的请求对数据排序。最后,它会填充排序并分页后的数据到小部件(widgets)或视图代码用于显示。
完成 actionIndex()
后,我们将 index
视图修改为如下代码。 此修改主要是关于在用户指定显示Tag下的日志时添加一个 h1
标题。
<?php if(!empty($_GET['tag'])): ?>
<h1>Posts Tagged with <i><?php echo CHtml::encode($_GET['tag']); ?></i></h1>
<?php endif; ?> <?php $this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_view',
'template'=>"{items}\n{pager}",
)); ?>
注意上面的代码,我们使用了 CListView 来显示日志列表。这个小物件需要一个局部视图以显示每一篇日志的详情。这里我们制定了局部视图为 _view
,也就是文件 /wwwroot/blog/protected/views/post/_view.php
. 在这个视图脚本中,我们可以通过一个名为 $data
的本地变量访问显示的日志实例。
参考资料
日志管理
日志管理主要是在一个管理视图中列出日志,我们可以查看所有状态的日志,更新或删除它们。它们分别通过admin
操作和 delete
操作实现。yiic
生成的代码并不需要太多修改。下面我们主要解释这两个操作是怎样实现的。
1. 在表格视图中列出日志
admin
操作在一个表格视图中列出了所有状态的日志。此视图支持排序和分页。下面就是 PostController
中的actionAdmin()
方法:
public function actionAdmin()
{
$model=new Post('search');
if(isset($_GET['Post']))
$model->attributes=$_GET['Post'];
$this->render('admin',array(
'model'=>$model,
));
}
上面的代码由 yiic
工具生成,且未作任何修改。它首先创建了一个 search
场景(scenario) 下的 Post
模型。我们将使用此模型收集用户指定的搜索条件。然后我们把用户可能会提供的数据赋值给模型。 最后,我们以此模型显示 admin
视图。
下面就是 admin
视图的代码:
<?php
$this->breadcrumbs=array(
'Manage Posts',
);
?>
<h1>Manage Posts</h1> <?php $this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
array(
'name'=>'title',
'type'=>'raw',
'value'=>'CHtml::link(CHtml::encode($data->title), $data->url)'
),
array(
'name'=>'status',
'value'=>'Lookup::item("PostStatus",$data->status)',
'filter'=>Lookup::items('PostStatus'),
),
array(
'name'=>'create_time',
'type'=>'datetime',
'filter'=>false,
),
array(
'class'=>'CButtonColumn',
),
),
)); ?>
我们使用 CGridView 来显示这些日志。它允许我们在单页显示过多时可以分页并可以按某一列排序。我们的修改主要针对每一列的显示。例如,针对 title
列,我们指定它应该显示为一个超级链接,指向日志的详情页面。表达式$data->url
返回我们之前在 Post
类中定义的 url
属性值。
提示: 当显示文本时,我们要调用 CHtml::encode() 对其中的HTML编码。这可以防止 跨站脚本攻击(cross-site scripting attack).
2. 日志删除
在 admin
数据表格中,每行有一个删除按钮。点击此按钮将会删除相应的日志。在程序内部,这会触发如下实现的 delete
动作。
public function actionDelete()
{
if(Yii::app()->request->isPostRequest)
{
// we only allow deletion via POST request
$this->loadModel()->delete(); if(!isset($_POST['ajax']))
$this->redirect(array('index'));
}
else
throw new CHttpException(400,'Invalid request. Please do not repeat this request again.');
}
上面的代码就是 yiic
生成的代码,未经任何修改。我们想在此对判断 $_POST['ajax']
稍作解释。CGridView小物件有一个非常好的特性:它的排序、分页和删除操作默认是通过AJAX实现的。这就意味着在执行上述操作时,整个页面不会重新加载。然而,它也可以在非AJAX模式下运行(通过设置它的 ajaxUpdate
属性为 false 或在客户端禁用JavaScript)。delete
动作区分两个场景是必要的:如果删除请求通过AJAX提交,我们就不应该重定向用户的浏览器,反之则应该重定向。
删除日志应该同时导致日志的所有评论被删除。额外的,我们应更新相关的删除日志后的 tbl_tag
表。 这两个任务都可以通过在 Post
模型类中写一个如下的 afterDelete
方法实现。
protected function afterDelete()
{
parent::afterDelete();
Comment::model()->deleteAll('post_id='.$this->id);
Tag::model()->updateFrequency($this->tags, '');
}
上面的代码很直观:它首先删除了所有 post_id
和所删除的日志ID相同的那些评论。然后它针对所删日志中的tags
更新了 tbl_tag
表。
提示: 由于 SQLite 并不真正支持外键约束,我们需要显式地删除属于所删日志的所有评论。在一个支持此约束的DBMS (例如 MySQL, PostgreSQL)中,可以设置好外键约束,这样如果删除了一篇日志,DBMS就可以自动删除其评论。这样的话,我们就不需要在我们的代码中显式执行删除了。
自定义存储的流程
由于我们想要记录评论创建的时间,和我们在 Post
模型中的做法一样,我们覆盖 Comment
的 beforeSave()
方法如下:
protected function beforeSave()
{
if(parent::beforeSave())
{
if($this->isNewRecord)
$this->create_time=time();
return true;
}
else
return false;
}
yii第一个应用blog的更多相关文章
- yii 第一步
第一步:index.php // include Yii bootstrap filerequire_once(dirname(__FILE__).'/../../framework/yii.php' ...
- Yii 权限分级式访问控制实现(非RBAC法)
以下由我们在信易网络公司开发项目的时候终结出的一些经验 主要参考资料:yii官网http://www.yiiframework.com/wiki/60/yii framework 提供了2套权限访问系 ...
- yii 权限分级式访问控制的实现(非RBAC法)——已验证
验证和授权——官方文档: http://www.yiichina.com/guide/topics.auth http://www.yiiframework.com/doc/guide/1.1/zh_ ...
- ubuntu kylin 14.04编译openjdk-7u40
1.ubuntu kylin 14.04安装依赖 sudo apt-get install build-essential gawk m4 libasound2-dev libcups2-dev li ...
- ffmpeg(2.6) rockplayer android 下编译 小记.
最近因为一些需求,开始学习 ffmgeg 在android 上使用. 使用的环境: 1,VMware V8 虚似机 安装的 FedoraV18 系统.(下载地址,请baidu),虚似机,最好有20-3 ...
- 神一样的CSDN博客排名规则
本文转载于:http://blog.csdn.net/littletigerat/article/details/17448521 神一样的CSDN博客排名规则 一.引言 年. 马年CSDN博客,毫无 ...
- [ASE][Daily Scrum]11.17
这两天感冒了没有第一时间更新blog和tfs,给大家抱歉了! 上周五我们已经将服务器搭建完成并成功通讯,周六周日大家非常给力的完成了很多内容! View Shilin Liu 处理来自服务器的数据 显 ...
- Qt的Qss样式
http://www.cnblogs.com/coffeegg/archive/2011/11/15/2249452.html(转) http://blog.csdn.net/cgzhello1/ar ...
- 菜鸟进阶Android Touch事件传递(四)
尊重他人劳动成果,转载请说明出处:http://blog.csdn.net/bingospunky/article/details/44343477 在该系列文章第四篇.我准备介绍一下viewpage ...
随机推荐
- B树叶子节点split
一.B-Tree索引的分裂 1. 创建测试表 SQL> create table split_tab (id number, name varchar2(100)); 表已创建. SQL> ...
- 【转】Android中引入第三方Jar包的方法(java.lang.NoClassDefFoundError解决办法)
原文网址:http://www.blogjava.net/anchor110/articles/355699.html 1.在工程下新建lib文件夹,将需要的第三方包拷贝进来.2.将引用的第三方包,添 ...
- HIbernate Oracle存储过程
之前为了实现基于Hibernate+Oracle的存储过程调用,发现了一个又一个坑,然后一个一个的尝试解决. 需求:使用Hibernate调用Oracle的存储过程,需要支持的有动态表名.存储过程变量 ...
- leetcode:Multiply Strings(字符串的乘法)【面试算法题】
题目: Given two numbers represented as strings, return multiplication of the numbers as a string. Note ...
- EL表达式 functions String处理函数
01.uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> 02.上面的 uri 根据 ...
- java Color
通过16进制颜色值获取颜色方法:Color.decode("#E0EEEE"); --后继续补充
- Javascript:一款简易的图片切换插件
最近迷上javascript,每天不写点什么都不舒服哈~ 尽管自己能力有限,还是尽自己所能写点东西出来. 实现效果: 效果预览:http://codepen.io/anon/pen/BNjxXj 该插 ...
- getInitParameter()
getInitParameter()方法是在GenericServlet接口中新定义的一个方法,用来调用初始化在web.xml中存放的参量.在web.xml配置文件中一个servlet中参量的初始 ...
- Android异步请求
class MyTask_SendMessage extends AsyncTask<String, Void, String> { @Override protected void on ...
- 我永远的 dell 15r
陪伴我三年多的15r 让我疯狂过.努力过.更记录了我很多的成长,与很多个瞬间.看到它是有感情的.还记得第一次失去她.我好像失去了自己. 我是一个程序员.每个程序员都有自己的环境配置.不同的软件.就是 ...