玩转play framework ( by quqi99 )

                                         玩转play framework ( by quqi99 )

 

作者:张华  发表于:2011-04-06
版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明

( http://blog.csdn.net/quqi99 )

p { margin-bottom: 0.21cm; }h1 { margin-bottom: 0.21cm; }h1.western { font-family: "Arial",sans-serif; font-size: 16pt; }h1.cjk { font-family: "宋体"; font-size: 16pt; font-style: normal; font-weight: bold; }h1.ctl { font-family: "Tahoma"; font-size: 16pt; font-weight: bold; }h2 { margin-bottom: 0.21cm; }h2.western { font-family: "Arial",sans-serif; font-size: 14pt; font-style: italic; }h2.cjk { font-family: "宋体"; font-size: 14pt; font-style: italic; }h2.ctl { font-family: "Tahoma"; font-size: 14pt; font-style: italic; }pre { font-family: "Courier New",monospace; }h3 { margin-bottom: 0.21cm; }h3.western { font-family: "Arial",sans-serif; }h3.cjk { font-family: "宋体"; font-style: normal; }h3.ctl { font-family: "Tahoma"; }a:link { color: rgb(0, 0, 255); }

 



内容目录

1 开发环境构建 1

1.1 下载二进制发布包 1

1.2 创建应用 1

1.3 集成eclipse 2

2 Hello World 2

3 Play 程序开发 3

3.1 视图层 3

3.1.1 模板元素 3

3.1.2 模板继承 3

3.2 控制层 3

3.3 模型层 4

3.4 无状态的体系结构 4

3.5 任务调度 5

3.6 支持non-web 应用 5

3.7 支持CRUD 应用 8

3.8 支持安全 9


 

1 开发环境构建

1.1 下载二进制发布包

http://download.playframework.org/releases/play-1.2.1.zip

下载完后解压,例如我解压的目录是: /home/workspace/play-1.2.1

1.2 创建应用

zhanghua:play-1.2.1 root# ./play new QATool

~ _ _

~ _ __ | | __ _ _ _| |

~ | '_ /| |/ _' | || |_|

~ | __/|_|/____|/__ (_)

~ |_| |__/

~

~ play! 1.2.1, http://www.playframework.org

~

~ The new application will be created in /home/workspace/play-1.2.1/QATool

~ What is the application name? [QATool]

~

~ OK, the application is created.

~ Start it with : play run QATool

~ Have fun!

~

zhanghua:play-1.2.1 root# ./play run QATool

~ _ _

~ _ __ | | __ _ _ _| |

~ | '_ /| |/ _' | || |_|

~ | __/|_|/____|/__ (_)

~ |_| |__/

~

~ play! 1.2.1, http://www.playframework.org

~

~ Ctrl+C to stop

~

Listening for transport dt_socket at address: 8000

10:44:48,951 INFO ~ Starting /home/workspace/play-1.2.1/QATool

10:44:49,774 WARN ~ You're running Play! in DEV mode

10:44:49,876 INFO ~ Listening for HTTP on port 9000 (Waiting a first request to start) ...

 

这时,你能在浏览器上访问 http://localhost:9000 验证

1.3 集成 eclipse

zhanghua:play-1.2.1 root# ./play eclipsify QATool

 

然后,能过 File/Import/General/Existing project… QATool 应用导入到 eclipse 中。

其次,要安装 Eclipse 插件,在 support/eclipse/ 目录下,要安装它,只需将你在该目录下找到的 JAR 文件,简单地复制到 Eclipse 安装目录的 dropins 文件夹下。

说明一下, eclipsify 命令生成若干个应用程序的启动器( launcher ),主启动器( main launcher )只能通过 Eclipse Run As 命令使用。可以随时通过 Debug As 启动一个调试会话,然后使用 Connect JPDA launcher ,停止调试会话并不会导致服务器终止。如果你对应用程序做了任何重要的修改,如改变 classpath ,则需要使用 eclipsify 重新生成 Eclipse 配置文件。

在调试时,首先用 ./play run QATool 命令启动应用 ; 然后连接 JPDA 调试器即可。

在启动应用时,也可以先将所有 conf 目录、应用本身的 JAR 包、及 play 本身的 JAR 包加到环境变量后再执行下列命令即可 ( 通过 run as 启动,而不是 debug as)

java -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n

-Dapplication.path="${project_loc:QATool}"

-javaagent:"/home/workspace/play-1.2.1/framework/play-1.2.1.jar"

play.server.Server

2 Hello World

  1. vim app/views/Application/index.html

#{extends 'main.html' /}

#{set title:'Home' /}

 

#{if flash.error}

< p style =" color : #c00 " >

${flash.error}

</ p >

#{/if}

< form action = "@{Application.sayHello()}" method = "GET" >

< input type = "text" name = "myName" />

< input type = "submit" value = "Say hello!" />

</ form >

 

2 vim app/controllers/Application.java 添加一方法:

 

public static void sayHello( @Required String myName) {

if ( validation . hasErrors ()) {

flash .error( "Oops, please enter your name!" );

index ();

}

render (myName);

}

 

3 vim app/views/Application/sayHello.html

#{extends 'main.html' /}

       #{set title:'Home' /}


 

       <h1>Hello ${myName ?: 'guest'}!</h1>


 

       <a href="@{Application.index()}">Back to form</a>

3 Play 程序开发

3.1 视图层

3.1.1 模板元素

Play 框架的模板技术使用的是 Groovy 语言。在模板中可以使用的动态元素如下说明:

${...} 用来对一个表达式求值,如 ${note.title} 是指取 note 对象的 title 属性。

@{...} @@{...} 是指 JAVA 端控制器动作方法的相对 URL 及绝对 URL

&{...} 用来显示经国际化之后的消息内容。

*{...}* 注释

%{...}% 用来添加复杂的 Groovy 脚本,可以声明变量和添加语句。

#{...} 用来调用 Play 框架或自定义的标签。


举个例子,如对 topics 变量进行循环迭代,则用 Groovy 模板,如下:

%{ for(topic in topics){ }%

<td> ${topic.id} </td>

%{ } }%

3.1.2 模板继承

Play 框架中可以使用 #{extends} #{doLayout} 来实现模板之间的继承。

在父模板中可以包含任意的内容。在需要由子模板填充的位置,使用 #{doLayout /} 进行声明即可。在子模板中通过 #{extends} 来声明所继承的模板。如 #{extends 'main.html'} 就声明继承自模板 main.html 。当子模板被生成之后,将包含父模板中的内容。而子模板中只需要定义扩展的内容即可。

3.2 控制层

在控制层的动作方法完成了与业务逻辑相关的处理之后,需要把响应返回给客户端。响应的结果可能是正确完成,也可能是出现错误。 Play 框架提供了方便的实现用来返回不同类型的响应。使用 play.mvc.Controller 类提供的不同方法就可以生成这些响应内容。

  • 请求正确完成, HTTP 状态代码为 200 。使用 ok() 方法生成不带内容的响应。使用 render() 方法来生成使用模板的响应。使用 renderText() 方法生成 text/plain 类型的纯文本响应。使用 renderXml() 方法生成 text/xml 类型的 XML 格式的响应。使用 renderJSON() 方法生成 application/json 类型的 JSON 格式的响应。使用 renderBinary() 方法生成二进制内容的响应。

  • 跳转到新的页面, HTTP 状态代码为 3XX 。使用 redirect() 方法来跳转到新的 URL 。使用 notModified() 方法来返回状态代码 304

  • HTTP 状态代码 4XX 。使用 unauthorized() 方法返回状态代码 401 。使用 forbidden() 方法返回状态代码 403 。使用 notFound() 方法返回状态代码 404

  • 服务器内部错误, HTTP 状态代码 5XX 。使用 error() 方法返回状态代码 500


3.3 模型层

领域对象的实例一般需要持久化下来。最常见的持久化方式就是使用关系数据库。 Play 框架使用 JPA 规范来进行领域对象的持久化。具体的后台实现使用的是 Hibernate 。开发人员只需要使用 JPA 规范定义的标注,就可以声明领域的持久化行为。比较好的做法是将领域对象类继承自 Play 框架提供的 play.db.jpa.Model 类。 play.db.jpa.Model 类提供了一个域 id 作为对象的标识符,也是对应的数据库表中的主键。 play.db.jpa.JPASupport 类是 play.db.jpa.Model 的父类,提供了一些实用方法用来完成从领域对象到数据库之间的映射。

举些例子:

1 )分页查询:

List<Content> list = Content. find ( " status=? order by id asc" , status).from(startPos).fetch(pageSize);

2 )查询数目

Content. count ( "status = ?" , status);

3 )保存 user.save();

4 )更新

User user = Dao. findByUsername ( "quqi99" );

user.setPassword( "111111" );

user.save();

 

可参考:
Play!
连接
MySQL
配置



 
http://c4fun.iteye.com/blog/506959



 

http://www.playframework.org/documentation/1.1.1/jpa



 

3.4 无状态的体系结构

HTTP 协议本身就被设计成无状态的,采用请求 / 响应的模式。不同的请求之间并不存在相互关系。但是这种架构模式在开发某些 Web 应用的时候不是很方便。有些应用要求用户进行认证登录之后才能进行某些操作。同样的 URL ,认证和未认证用户看到的内容是不同的。而且用户认证成功之后,他应该在一段时间内保持这种认证状态。否则的话,用户每次都需要输入用户名和密码才 能访问受限的内容。对于这种情况,很多 Web 开发框架提供了会话的支持,允许应用保存一些与会话相关的数据。 Java Servlet 规范中的 javax.servlet.http. HttpSession 就是一种会话的接口。应用的服务器会负责维护每个会话相关的数据。这些数据可以通过一个会话 ID 来进行标识。这个标识会利用浏览器的 cookie 机制保存在浏览器端,也可以作为请求 URL 的参数来传递。服务器端通过此标识来识别每个会话。在处理相应的请求的时候,就可以根据会话 ID 来获取保存在服务器端上的会话数据。会话机制的问题是会影响应用的可伸缩性。如果一个应用使用多台服务器的话,就需要额外的机制来保证同一用户在不同机器 上面的会话是同步的。而无状态的实现 则不存在这个问题,对于某一个请求,由不同机器来处理的结果都是相同的。

Play 框架的设计架构就是无状态的。它没有提供服务器端的机制用来维护跨多个请求的数据。如果确实需要保存这样的数据的话,可以考虑下面几种方案:

  • 保存在 Session Flash 作用域中。 Play 框架中仍然有会话的机制,但是并没有提供在服务器端保存会话数据的能力。会话数据是保存在浏览器的 cookie 中的,由浏览器在每次请求的时候自动发送。通过这种方式来达到维护会话数据的目的。 由于会话数据是保存在 cookie 中,其大小是有限制的,一般不能超过 4K 字节,而且只能保存字符串类型的数据。 Flash 作用域和会话一样,也是通过 cookie 来保存的。所不同的是, Flash 作用域中的数据只在下次请求中是有效的。

  • 保存在持久化的数据存储中,如数据库中。如果需要在多个请求中使用同一个领域对象的话,可以把这个对象的 ID 保存在 Session Flash 作用域中,而在控制器动作方法中使用此 ID 来从数据库中查询相应的对象。

  • 保存在暂时性数据存储中,如缓存中。 Play 框架内置了缓存的支持,通过调用类 play.cache.Cache 就可以对缓存进行操作。与使用持久化存储类似,缓存中的键的值可以保存在 Session Flash 作用域中。

对于熟悉了 Java Servlet 规范的开发人员来说,需要一些时间来适应 Play 框架的这种无状态的体系结构。不过这种结构对于应用的可伸缩性来说,确实是非常有好处的。

3.5 任务调度

Web 应用开发中,有时候会需要定期执行一些调度任务,比如数据库备份和数据同步等。这些任务不是通过 HTTP 请求来触发的,而是定时执行的。 Play 框架提供了内置的任务调度支持的能力。创建新任务的时候,只需要继承自 play.jobs.Job 类,并覆写 doJob() 方法即可。如果要创建的任务有返回结果的话,覆写 doJobWithResult() 方法即可。任务创建完成之后,可以选择不同的调度方式。一种方式是在应用启动的时候执行一次。只需要在任务的 Java 类上添加标注 @OnApplicationStart 即可。对于定期执行的任务, Play 框架提供了两个标注:一个是 @Every ,用来按照固定的时间间隔调度任务,如 @Every("1h") 声明任务每个小时执行一次;另外一个是 @On ,用来声明描述调度策略的 CRON 表达式。

3.6 支持 non-web 应用

对于 non-web 应用,如果想要重要模型层的话,可用如下代码:

package nonwebapp;

 

import java.io.File;

import java.lang.reflect.Method;

import java.util.List;

 

import models.Content;

import play.Play;

import play.db.DBPlugin;

import play.db.jpa.JPAPlugin;

import play.test.Fixtures;

 

/**

*

* author: huazhang since : 2011 - 6 - 21

*/

public abstract class PlayLoaderMain

{

 

public static void main(String[] args) throws Exception

{

try

{

String appPath = "/home/workspace/play-1.2.1/QATool" ;

File root = new File(appPath);

Play. init (root, System. getProperty ( "play.id" , "" ));

 

Thread. currentThread ().setContextClassLoader(Play. classloader );

Class<?> c = Play. classloader .loadClass( "nonwebapp.BuildAccounts" );

Method m = c.getMethod( "run" );

m.invoke(c.newInstance());

} catch (Exception e)

{

e.printStackTrace();

}

}

 

public void run() throws Exception

{

new DBPlugin().onApplicationStart();

new JPAPlugin().onApplicationStart();

JPAPlugin. startTx ( true );

 

exec();

 

JPAPlugin. closeTx ( false );

}

 

public abstract void exec() throws Exception;

}



package nonwebapp;

 

import java.util.List;

 

import models.Content;

 

/**

*

* author: huazhang since : 2011 - 6 - 22

*/

public class BuildAccounts extends PlayLoaderMain

{

@Override

public void exec() throws Exception

{

List<Content> list = Content. findAll ();

System. out .println( "" );

}

}

 

再写个脚本调用它,脚本中加环境变量

 

#!/bin/bash

# huazhang

# 2011-06-28

#

 

# resolve links - $0 may be a softlink

THIS="$0"

while [ -h "$THIS" ]; do

ls =` ls - ld "$THIS"`

link=` expr "$ ls " : '.*-> /(.*/)$'`

if expr "$link" : '.*/.*' > / dev /null; then

THIS="$link"

else

THIS=` dirname "$THIS"`/"$link"

fi

done

 

# some directories

THIS_DIR=` dirname "$THIS"`

QATOOL_HOME=` cd "$THIS_DIR" ; pwd `

PLAY_HOME=` cd "$QATOOL_HOME/.." ; pwd `

 

if [ $# - lt 1 ] ; then

echo "USAGE: $0 class"

echo " e.g.: $0 nonwebapp.ImportData"

exit 1;

fi

 

if [ "$JAVA_HOME" = "" ]; then

echo "Error: JAVA_HOME is not set."

exit 1

fi

 

JAVA=$JAVA_HOME/bin/java

JAVA_HEAP_MAX=-Xmx1000m

 

for f in ${PLAY_HOME}/framework/*.jar; do

CLASSPATH=${CLASSPATH}:$f;

done

for f in ${PLAY_HOME}/framework/ lib /*.jar; do

CLASSPATH=${CLASSPATH}:$f;

done

 

if [ -d "${QATOOL_HOME}/ conf " ]; then

CLASSPATH=${CLASSPATH}:${QATOOL_HOME}/ conf

fi

for f in $QATOOL_HOME/ lib /*.jar; do

CLASSPATH=${CLASSPATH}:$f;

done

if [ -d "${QATOOL_HOME}/ tmp /classes" ]; then

CLASSPATH=${CLASSPATH}:${QATOOL_HOME}/ tmp /classes

fi

 

# default log directory & file

if [ "$QATOOL_LOGFILE" = "" ]; then

QATOOL_LOGFILE="$QATOOL_HOME/logs/QATool.log"

fi

 

if [ "x$JAVA_LIBRARY_PATH" != "x" ]; then

QATOOL_OPTS="$QATOOL_OPTS -Djava.library.path=$JAVA_LIBRARY_PATH"

fi

 

# run it

JAVA_OPTS="-server -Xms1600m -Xmx1600m -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=128m -Djava.awt.headless=true"

exec "$JAVA" $QATOOL_OPTS - classpath "$CLASSPATH" "$@"

3.7 支持 CRUD 应用

1) vim application.conf

# Import the crud module

module.crud =${play.path}/modules/crud

2) vim routes

# Import CRUD routes

* /admin module:crud

3) 改动了配置,要重新运行下列命令:

zhanghua:play-1.2.1 root# ./play eclipsify QATool

4) 新建 Control

package controllers;

/**

*

* author: huazhang

* since : 2011 - 6 - 27

*/

public class Users extends CRUD

{

}

5) 新建 Model

/**

*

* author: huazhang

* since : 2011 - 6 - 27

*/

@Entity

public class User extends Model

{

@Email

@Required

@MaxSize (256)

public String username ;

@Required

public String password ;

@Required

public String role ;

  1. 启动后访问 http://localhost:9000/admin 即可

7) 客户化字符串 , vim conf/messages, 添加:

username= 用户名

password= 密码

role= 角色

8) 客户化表现层,执行下列命令创建 /app/views/Users/list.html

zhanghua:play-1.2.1 root# ./play crud:ov --template Users/list

3.8 支持安全

http://www.playframework.org/documentation/1.0/secure

1) vim application.conf

# Import the secure module

module.secure=${play.path}/modules/secure

2) vim routes

# Import Secure routes

     *      /                module:secure

3) 改动了配置,要重新运行下列命令:

zhanghua:play-1.2.1 root# ./play eclipsify QATool

4) 修改 Controller, 添加 With Check 两个标签:

@With (Secure. class )

public class Application extends Controller {

 

@Check (Constant. ROLE_ADMIN )

public static void index() {

String user = Security. connected ();

System. out .println( "" );

render ();

}

5) 新建一个自定义 Security 类,如下:

/**

*

* author: huazhang

* since : 2011 - 6 - 28

*/

public class Security extends Secure.Security

{

static boolean authentify(String username, String password)

{

User user = Dao. findByUsername (username);

return user != null && user. password .equals(password);

}

static boolean check(String role) {

String loginUser = connected ();

User user = Dao. findByUsername (loginUser);

return user== null ? false : role.equalsIgnoreCase(user.getRole());

}

}

[强烈推荐, 文档不多, 很快就可以看完, 看完了, 就会使用play了] 目录 MVC应用程序模型 - 7 - app/controllers - 8 - app/models - 8 - app/views - 8 - 请求生命周期 - 8 - 标准应用程序布局layout - 9 - app目录 - 9 - public目录 - 10 - conf目录 - 10 - lib目录 - 11 - 开发生命周期 - 11 - 连接到java调试器 - 12 - 类增强Enhancement - 13 - 02.HTTP路由 - 13 - 关于REST - 14 - routes文件语法 - 14 - HTTP方法 - 15 - URI范示 Pattern - 15 - Java调用定义 - 17 - 把404当作action来用 - 17 - 指派静态参数 - 17 - 变量和脚本 - 18 - 路由优先级 - 18 - 服务器静态资源 - 18 - staticDir: mapping - 18 - staticFile: mapping - 19 - URL 编码 - 19 - 反转路由:用于生成某些URL - 19 - 设置内容风格(CSS) - 20 - HTTP 内容协商 negotiation - 21 - 从http headers开始设置内容类型 - 21 - 定制格式 - 22 - 03.控制器 - 23 - 控制器概览 - 23 - 获取http参数 - 24 - 使用params map - 25 - 还可以从action方法签名实现转换 - 25 - 高级HTTP Java绑定 - 26 - 简单类型 - 26 - Date类型 - 26 - Calendar日历 - 27 - File - 27 - 支持类型的数组或集合 - 28 - POJO对象绑定 - 29 - JPA 对象绑定 - 30 - 定制绑定 - 30 - @play.data.binding.As - 30 - @play.data.binding.NoBinding - 31 - play.data.binding.TypeBinder - 31 - @play.data.binding.Global - 32 - 结果类型 - 32 - 返回一些文本类型的内容 - 33 - 返回一个JSON字符串 - 33 - 返回一个XML字符串 - 34 - 返回二进制内容 - 34 - 作为附件下载文件 - 34 - 执行一个模板 - 35 - 跳转到其他URL - 36 - Action链 - 36 - 定制web编码 - 37 - 拦截器 - 38 - @Before - 38 - @After - 39 - @Catch - 40 - @Finally - 41 - 控制器继承 - 42 - 使用@With注释添加更多的拦截器 - 42 - Because Java does not allow multiple inheritance, it can be very limiting to rely on the Controller hierarchy to apply interceptors. But you can define some interceptors in a totally different class, and link them with any controller using the @With annotation.由于java不允许多继承,通过控制器继承特点来应用拦截器就受到极大的限制。但是我们可以在一个完全不同的类里定义一些拦截器,然后在任何控制器里使用@With注释来链接他们。 - 42 - Session和Flash作用域 - 42 - 04.模板引擎 - 43 - 模板语法 - 43 - Expressions: ${…} - 44 - Template decorators : #{extends /} and #{doLayout /} - 44 - Tags: #{tagName /} - 45 - Actions: @{…} or @@{…} - 46 - Messages: &{…} - 46 - Comment: *{…}* - 46 - Scripts: %{…}% - 46 - Template inheritance继承 - 47 - 定制模板标签 - 48 - 检索tag参数 - 48 - 调用标签体 - 48 - 格式化特定标签 - 49 - 定制java标签 - 49 - 标签命名空间 - 50 - 在模板里的Java对象扩展 - 51 - 创建定制扩展 - 52 - 模板里可以使用的保留对象 - 52 - 05.用play验证http数据 - 53 - 在play里验证如何进行的? - 53 - 验证的错误消息 - 54 - Localised validation messages 局部验证消息 - 55 - 验证消息参数 - 55 - 定制局部验证消息 - 56 - 定制teral(非局部)验证消息 - 57 - 在模板里显示验证错误消息 - 57 - 验证注释 - 60 - 验证复杂对象 - 60 - 内建验证 - 61 - 使用@CheckWith定制验证 - 61 - 定制注释 - 62 - 06.域对象模型 - 64 - 属性模仿 - 65 - 设置数据库来持久化模型对象 - 68 - 用hibernate持久化对象模型 - 69 - 保持模型stateless - 70 - 07.JPA持久化 - 70 - 启动JPA实体管理器 - 70 - 获取JPA实体管理器 - 70 - 事务管理 - 71 - play.db.jpa.Model支持类 - 71 - 为GenreicModel定制id映射 - 72 - Finding对象 - 72 - Find by ID - 72 - Find all - 73 - 使用简单查询进行查找 - 73 - 使用JPQL 查询进行查找 - 74 - Counting统计对象 - 74 - 用play.db.jpa.Blob存储上传文件 - 74 - 强制保存 - 75 - 更多公共类型generic typing问题 - 77 - 08.Play.libs库包 - 78 - 用XPath解析XML - 78 - Web Service client - 79 - Functional programming with Java功能扩展? - 79 - Option<T>, Some<T> and None<T> - 80 - Tuple<A, B> - 80 - Pattern Matching模式匹配 - 81 - Promises - 81 - OAuth - 82 - OAuth 1.0 - 82 - OAuth 2.0 - 83 - OpenID - 84 - 09.异步Jobs - 86 - 引导程序任务Bootstrap jobs - 87 - 预定义任务Scheduled jobs - 87 - 触发任务job - 88 - 停止应用程序 - 89 - 10.在HTTP下进行异步编程 - 89 - 暂停http请求 - 89 - Continuations - 90 - 回调Callbacks - 91 - HTTP response流 streaming - 92 - 使用WebSockets - 92 - 11.在play框架里使用Ajax - 94 - 通过jsAction标签使用jQuery - 95 - 12. Internationalization国际化支持 - 96 - 仅使用 UTF-8! - 96 - 国际化你的信息 - 96 - 通过应用程序定义支持的语言 - 96 - 依照你的区域定义日期格式 - 97 - 找回区域信息 - 97 - Message arguments - 97 - 模板输出 - 98 - 多参数 - 98 - 立即数Argument indices - 98 - 13.使用cache - 99 - The cache API - 99 - 不要把Session当成缓存! - 101 - 配置mcached - 101 - 14.发送e-mail - 102 - Mail 和MVC 集成 - 102 - text/html e-mail - 103 - text/plain e-mail - 104 - text/html e-mail with text/plain alternative - 104 - 在应用程序里链接到邮件 - 104 - SMTP配置 - 105 - 使用 Gmail - 105 - 15.测试应用程序 - 105 - 书写测试程序 - 105 - 单元测试 - 106 - 功能性测试 - 106 - Selenium test用例测试 - 107 - Fixtures固定值 - 108 - 运行测试 - 110 - 陆续集成,并自动运行测试 - 111 - 16.安全指南 - 112 - Sessions - 112 - 守住你的安全…安全 - 112 - 不要存储关键性的数据 - 112 - 跨站点脚本攻击 - 112 - SQL注入 - 113 - 跨站点请求伪造 - 114 - 17.Play模块和模块仓库 - 115 - 什么是模块? - 115 - 如何从一个应用程序里加载模块 - 115 - 从模块加载默认的routes - 115 - 为模块增加文档说明 - 115 - 使用模块仓库 - 116 - 贡献新模块到模块仓库里 - 117 - 先决条件 - 117 - 模块注册 - 117 - 发布你的模块 - 118 - 18.依赖管理 - 118 - 依赖格式 - 119 - 动态版本 - 119 - dependencies.yml - 119 - ‘play dependencies’命令 - 120 - 透明依赖 - 121 - 保持lib/和modules/目录同步 - 122 - 冲突判定Conflict resolution - 123 - 增加要的仓库 - 124 - Maven仓库 - 125 - 本地仓库 - 125 - 定制ivy设置(Apache ivy:项目依赖管理工具) - 126 - 清除Ivy缓存 - 127 - 19.管理数据库变化Evolution - 128 - Evolutions脚本 - 128 - 同步同时发生的改变 - 130 - 数据不一致状态 - 133 - Evolutions 命令 - 136 - 20.日志配置 - 139 - 对应用程序进行日志 - 139 - 配置日志级别 - 140 - 生产配置 - 140 - 21.管理多环境下的application.conf - 140 - 框架id(framework ID) - 141 - 从命令行设置框架id - 142 - 22.生产部署 - 142 - application.conf - 142 - 设置框架为prod模式: - 142 - 定义一个真实的数据库: - 143 - 禁止JPA的自动结构更新: - 143 - 定义一个安全的secret key: - 143 - 日志配置 - 143 - 前端http服务器(Front-end HTTP server) - 144 - 部署到lighttpd服务器的设置 - 144 - 部署到Apache服务器的设置 - 145 - Apache作为前端代理服务器,可以允许透明更新你的应用程序 - 145 - 高级代理设置 - 146 - HTTPS配置 - 147 - 不依赖Python进行部署 - 148 - 23.部署选择 - 148 - 独立Play应用程序 - 149 - Java EE应用服务器 - 149 - 支持应用服务器 - 149 - 部署 - 150 - 数据源 - 150 - 定制web.xml - 151 - 基于云的主机Cloud-based hosting - 151 - AWS Elastic Beanstalk - 152 - CloudBees - 152 - Cloud Foundry - 152 - Google App Engine (GAE) - 152 - Heroku - 152 - playapps.net - 153 -
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

quqi99

你的鼓励就是我创造的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值