Luminus A Clojure web framework
Luminus는 경량급 유형의 마이크로 구조를 바탕으로 한다.그것의 목적은 강력하고 확장 가능하며 사용하기 쉬운 플랫폼을 제공하는 것이다.Luminus를 사용하면 다른 방해를 신경 쓰지 않고 응용 프로그램을 개발하는 데 중점을 둘 수 있다.
Whydevelop web applications with Clojure?
Rapiddevelopment-빠른 발전
REPL로 바로 해킹 및 내장형 개발 서버 시작 가능
생산성 - 생산성
JVM이 Clojure와 결합하면 생산성과 성능 사이에서 선택할 필요가 없음
상호 작용 - 상호 작용
다시 컴파일하거나 다시 시작할 필요 없이 변경 사항을 즉시 감지할 수 있습니다
유연성-유연성
당신에게 적합한 구성 요소를 선택하면 프로젝트의 구조상 완전한 통제권이 있습니다
Matureecosystem-성숙한 생태계
기존 Clojure 및 Java 라이브러리 지원
Powerfultools-강력한 도구
Leiningen으로 응용 프로그램을 구축하고 배치하는 것은 매우 쉬우며, Heroku를 포함한 일련의 배치 옵션을 누릴 수 있다
Yourfirstapplication
1.Guestbook Application
이 강좌는 간단한 게시판 프로그램을 만들기 위해 Luminus 동태를 사용하도록 안내합니다.이 메시지는 사용자가 메시지를 남기고 다른 사람이 남긴 메시지를 볼 수 있도록 한다.응용 프로그램은 HTML 템플릿, 기본 데이터베이스 액세스 및 프로젝트의 구조를 표시합니다.
만약 당신이 이미 좋아하는 Clojure 편집기가 없다면, 이 강좌에 따라 LightTable을 사용하는 것을 권장합니다.
2.Installing Leiningen
Luminus 언어를 사용하려면 Leiningen 설치가 필요합니다.Leiningen 설치는 다음 단계를 포함한 간단한 절차입니다.
1. 스크립트 다운로드
2. 실행 가능한 것으로 설정 (예:chmod + x lein)
3. 그것을 당신의 $경로에 놓으세요.(예: ~/bin)
4. leinself-install을 실행하고 설치가 완료될 때까지 기다립니다.wget https://raw.github.com/technomancy/leiningen/stable/bin/lein
chmod +x lein
mv lein ~/bin
lein self-install
3.Creating a new application
Leiningen이 설치되면 터미널에서 다음 명령을 실행하여 애플리케이션을 초기화할 수 있습니다.
leinnew luminus guestbook +h2
cdguestbook
H2 내장형 데이터베이스를 엔진으로 하는 새 템플릿 프로젝트가 생성됩니다.
이제 다음 절차에 따라 프로젝트를 실행할 수 있습니다.
>leinring server
guestbookstarted successfully...
2013-03-01 19:05:30.389:INFO:oejs.Server:jetty-7.6.1.v20120215
Startedserver on port 3000
2013-03-01 19:05:30.459:INFO:oejs.AbstractConnector:StartedSelectChannelConnect
19:05:30.459:INFO:oejs.AbstractConnector:[email protected]:3000
새 브라우저 창이 뜰 것입니다. 프로그램이 실행 중인 것을 볼 수 있을 것입니다.새 브라우저를 꺼내지 않으려면 다음을 실행할 수 있습니다.
leinring server-headless
다음과 같은 사용자 정의 포트를 사용할 수도 있습니다.
leinring server-headless 8000
4.Anatomy of a Luminus application
새로 만든 응용 프로그램은 다음과 같은 구조를 가지고 있다Procfile
README.md
project.clj
src
└ log4j.xml
guestbook
└ handler.clj
layout.clj
middleware.clj
util.clj
repl.clj
db
└ core.clj
schema.clj
routes
└ home.clj
test
└ guestbook
└ test
└ handler.clj
resources
└ templates
└ about.html
base.html
home.html
└ public
└ css
└ screen.css
fonts
└ glyphicons-halflings-regular.eot
glyphicons-halflings-regular.svg
glyphicons-halflings-regular.ttf
glyphicons-halflings-regular.woff
img
js
md
└ docs.md
응용 프로그램의 루트 폴더에 있는 파일의 역할을 살펴보겠습니다.
procfile - Heroku 배포를 촉진하는 데 사용됩니다.
readme.md - 응용 프로그램 문서의 일반적인 보관소.
project.clj - 프로젝트의 구성 및 종속성을 Leiningen에서 관리합니다.
5.The Source Directory
모든 코드는 SRC 폴더 아래에 있습니다.우리의 응용 프로그램을 방명록이라고 부르기 때문에, 이것은 프로젝트의 루트 이름 공간입니다.우리를 위해 만들어진 모든 명명 공간을 살펴보자.
guestbook
handler.clj - 응용 프로그램의 기본 노선을 정의합니다. 이것은 프로그램의 입구점입니다.
layout.clj - 레이아웃 도움말이 있는 이름 공간입니다. 우리가 정의한 모든 웹 페이지는 그들의 경로를 여기에 추가해야 합니다.
middleware.clj - 프로그램 사용자 정의 중간부품을 포함하는 이름 공간
util.clj - 일반적인 액세스 기능에 사용되며 미리 제공되는 MD - HTML 도우미입니다.
repl.clj - REPL에서 응용 프로그램을 시작하고 중지하는 기능 제공
log4j.xml 레코드 구성
guestbook.db
db 이름 공간은 프로그램의 모델을 정의하고 데이터 영구층을 처리하는 데 사용됩니다.
core.clj - 함수 저장 및 데이터베이스 상호작용
schema.clj - 연결 매개 변수와 데이터베이스 테이블 정의에 사용
guestbook.routes
루트 이름 공간은 우리 홈페이지의 루트와 컨트롤러가 있는 위치입니다.authentication(인증)이나 specificworkflows (특정한 작업 절차) 와 같은routes를 더 추가하면, 그들을 위한 이름 공간을 만들어야 합니다.
home.clj - 홈과 프로그램 관련 페이지를 정의하는 이름 공간
6.The Test Directory
이것은 우리 프로그램을 설치하는 테스트에 사용되며, 이미 우리를 위해 두 개의 테스트 샘플을 정의했다.
7.The ResourcesDirectory
이것은 우리 프로그램의 모든 정적 자원을 배치하는 데 쓰인다.이미 폴더 CSS, JavaScript, images, markdown이 정의되어 있습니다.
HTML templates
템플릿 디렉토리는 응용 프로그램 페이지를 나타내는 Selmer 템플릿입니다.
about.html - 페이지
base.html-사이트를 위한 기본 레이아웃
html - 홈페이지
8.Adding Dependencies
위에서 언급한 바와 같이 모든 의존 관계 관리는 프로젝트 업데이트를 통해 이루어진다.clj 파일.루트 폴더에서 만든 응용 프로그램의 항목 파일을 찾을 수 있습니다. 다음과 같습니다.
(defproject
guestbook "0.1.0-SNAPSHOT"
:url "http://example.com/FIXME"
:description "FIXME: write description"
:dependencies
[[com.h2database/h2 "1.4.178"]
[ring-server "0.3.1"]
[environ "0.5.0"]
[com.taoensso/timbre "3.2.1"]
[markdown-clj "0.9.44"]
[korma "0.3.1"]
[com.taoensso/tower "2.0.2"]
[selmer "0.6.6"]
[org.clojure/clojure "1.6.0"]
[log4j
"1.2.17"
:exclusions
[javax.mail/mail
javax.jms/jms
com.sun.jdmk/jmxtools
com.sun.jmx/jmxri]]
[compojure "1.1.8"]
[lib-noir "0.8.3"]]
:plugins
[[lein-ring "0.8.7"] [lein-environ "0.5.0"]]
:ring
{:handler guestbook.handler/app,
:init guestbook.handler/init,
:destroy guestbook.handler/destroy}
:profiles
{:uberjar {:aot :all}
:production
{:ring
{:open-browser? false, :stacktraces? false, :auto-reload? false}},
:dev
{:dependencies [[ring-mock "0.1.5"] [ring/ring-devel "1.2.2"]],
:env {:dev true}}}
:min-lein-version "2.0.0")
보시다시피 프로젝트입니다.clj는 키/value 설명이 포함된 다른 방면의 Clojure 목록일 뿐입니다.사용자 정의 의존 zhixu를 추가하려면 dependenciesvector (의존 벡터) 에 간단하게 추가합니다.
9.Accessingthe Database
우선, 우리는 응용 프로그램을 위한 모델을 만들 것입니다. 이렇게 하면 src/guestbook/db 폴더에 있는 schema를 열 것입니다.clj 파일.여기서 우리는 이미 우리의 데이터베이스 연결에 대해 정의를 내렸다.JDBC 드라이버 JDBCdriver, 프로토콜protocol, 사용자user, 비밀번호password, H2 데이터베이스를 사용하는 데이터베이스 파일을 포함하는 간단한 맵을 정의합니다.(def db-spec {:classname "org.h2.Driver"
:subprotocol "h2"
:subname (str (io/resource-path) db-store)
:user "sa"
:password ""
:naming {:keys clojure.string/upper-case
:fields clojure.string/upper-case}})
다음에create-users-table에user표 정의가 있는 함수가 있습니다.이 함수 대신create-guestbook-table 함수를 사용합니다.(defn create-guestbook-table []
(sql/db-do-commands
db-spec
(sql/create-table-ddl
:guestbook
[:id "INTEGER PRIMARY KEY AUTO_INCREMENT"]
[:timestamp :timestamp]
[:name "varchar(30)"]
[:message "varchar(200)"]))
(sql/db-do-prepared db-spec
"CREATE INDEX timestamp_index ON guestbook (timestamp)"))
메모표는 주석자의 이름, 메일의 내용과 시간 스탬프 등 모든 필드 설명 정보를 저장합니다.
create-tables 함수를 업데이트하여 호출합니다.(defn create-tables
"creates the database tables used by the application"
[]
(create-guestbook-table))
만든 표로 우리는 우리의 메시지에 읽고 쓰는 기능을 추가할 수 있다.src/guestbook/db/core를 엽니다.clj 파일을 추가하십시오.우리는 이미 사용자 테이블을 처리하는 코드가 있는 것을 보았다.우리는 아래의 코드로 그들을 대체할 것이다.(ns guestbook.db.core
(:use korma.core
[korma.db :only (defdb)])
(:require [guestbook.db.schema :as schema]))
(defdb db schema/db-spec)
(defentity guestbook)
(defn save-message
[name message]
(insert guestbook
(values {:name name
:message message
:timestamp (new java.util.Date)})))
(defn get-messages []
(select guestbook))
위에서 우리는 하나의 실체를 만들어서 우리가 명명 공간을 구축하는 데 메모표를 만드는 것을 대표한다.그리고 함수save-message와 get-messages를 추가하여 그것과 상호작용합니다.
10.Running Code on Startup
핸들handler 이름 공간에는 함수 init가 포함되어 있습니다.프로그램이 시작될 때, 이 함수는 한 번 호출될 것이다.데이터베이스가 초기화되었는지 확인하기 위해 코드를 추가합니다. 필요하면 초기화합니다.
우리는 우선 구조 명칭 공간을 참고해야 한다. initialized를 사용하기 위해서?그리고create-tables의 기능.(ns guestbook.handler
(:use ...)
(:require ...
[guestbook.db.schema :as schema]))
다음은 init 함수를 업데이트합니다(defn init
"init will be called once when
app is deployed as a servlet on
an app server such as Tomcat
put any initialization code here"
[]
(timbre/set-config!
[:appenders :rotor]
{:min-level :info
:enabled? true
:async? false ; should be always false for rotor
:max-message-per-msecs nil
:fn rotor/appender-fn})
(timbre/set-config!
[:shared-appender-config :rotor]
{:path "guestbook.log" :max-size (* 512 1024) :backlog 10})
(if (env :selmer-dev) (parser/cache-off!))
;;initialize the database if needed
(if-not (schema/initialized?) (schema/create-tables))
(timbre/info "guestbook started successfully"))
프로그램의 init 함수를 바꿨기 때문에 서비스 (ctrl+c) 를 끄고 서비스 (leinring server) 를 다시 시작합니다
11.Creating Pages and HandlingForm Input
우리의 루트는 모두guestbook에 정의되어 있습니다.routes.홈 네임스페이스에서.그것을 열면 데이터베이스에서 정보를 읽는 이동은 논리를 증가시켜야 한다.우선, Referenc가 우리의db 명칭 공간을 늘려야 합니다.(ns guestbook.routes.home
(:use ...)
(:require ...
[guestbook.db.core :as db]))
다음으로 홈 페이지 컨트롤러를 변경합니다.(defn home-page [& [name message error]]
(layout/render "home.html"
{:error error
:name name
:message message
:messages (db/get-messages)}))
현재, 우리는 템플릿에 추가 파라미터를 추가할 수 있으며, 파라미터는 데이터베이스에서 나온 정보 목록이다.
우리는 사용자가 새로운 메시지를 발표할 수 있기를 희망하기 때문에handler에 controller theformposts를 추가해야 합니다:(defn save-message [name message]
(cond
(empty? name)
(home-page name message "Somebody forgot to leave a name")
(empty? message)
(home-page name message "Don't you have something to say?")
:else
(do
(db/save-message name message)
(home-page))))
마지막으로, 우리는 controller에 home-routes 정의에 루트를 추가합니다.(defroutes home-routes
(GET "/" [] (home-page))
(POST "/" [name message] (save-message name message))
(GET "/about" [] (about-page)))
현재, 우리의 컨트롤러는 이미 setup, 홈을 열었습니다.html 템플릿. {% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
<p>Time to start building your site!</p>
<p><a class="btn btn-primary btn-lg" href="http://luminusweb.net">Learn more »</a></p>
</div>
<div class="row-fluid">
<div class="span8">
{{content|safe}}
</div>
</div>
{% endblock %}
메시지 목록을 반복적으로 표시할 수 있도록 내용을 업데이트합니다.{% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
</div>
<div class="row-fluid">
<div class="span8">
<ul>
{% for item in messages %}
<li>
<time>{{item.timestamp|date:"yyyy-MM-dd HH:mm"}}</time>
<p>{{item.message}}</p>
<p> - {{item.name}}</p>
</li>
{% endfor %}
</ul>
</div>
</div>
{% endblock %}
보시다시피 우리는iterator를 사용하여 메시지를 달립니다.모든 메시지는 하나의 맵입니다. 메시지,name,timestamp 키워드를 포함하여name를 통해 얻을 수 있습니다.또한useof the date filter to format the timestamps into a humanreadableform.
다음은 컨트롤러에 발생할 수 있는 오류를 보여주기 위해 error 모듈을 추가해야 합니다.{% if error %}
<p class="error">{{error}}</p>
{% endif %}
error 모듈이 작동하는지 간단하게 테스트해 보세요.마지막으로, 사용자가 메시지를 제출할 수 있는form을 만듭니다.<form action="/" method="POST">
<p>
Name:
<input type="text" name="name" value={{name}}>
</p>
<p>
Message:
<textarea rows="4" cols="50" name="message">
{{message}}
</textarea>
</p>
<input type="submit" value="comment">
</form>
home.html template는 다음과 같습니다.{% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
</div>
<div class="row-fluid">
<div class="span8">
<ul>
{% for item in messages %}
<li>
<time>{{item.timestamp|date:"yyyy-MM-dd HH:mm"}}</time>
<p>{{item.message}}</p>
<p> - {{item.name}}</p>
</li>
{% endfor %}
</ul>
{% if error %}
<p class="error">{{error}}</p>
{% endif %}
</div>
<div class="span8">
<form action="/" method="POST">
<p>
Name:
<input type="text" name="name" value="{{name}}" />
</p>
<p>
Message:
<textarea rows="4" cols="50" name="message" />{{message}}</textarea>
</p>
<input type="submit" value="comment" />
</form>
</div>
</div>
{% endblock %}
마지막으로, 화면을 업데이트합니다.css 파일, 페이지의 아름다움:body {
height: 100%;
padding-top: 70px;
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #eaeaea;
color: #4d4d4d;
width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
input[type=submit] {
margin: 0;
padding: 0;
border: 0;
line-height: 1.4em;
background: none;
vertical-align: baseline;
}
input[type=submit], textarea {
font-size: 24px;
font-family: inherit;
border: 0;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
}
input[type=submit]:hover {
background: rgba(0, 0, 0, 0.15);
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);
}
textarea {
position: relative;
line-height: 1em;
width: 100%;
}
.error {
font-weight: bold;
color: red;
}
.jumbotron {
position: relative;
background: white;
z-index: 2;
border-top: 1px dotted #adadad;
}
h1 {
width: 100%;
font-size: 70px;
font-weight: bold;
text-align: center;
}
ul {
margin: 0;
padding: 0;
list-style: none;
}
li {
position: relative;
font-size: 16px;
padding: 5px;
border-bottom: 1px dotted #ccc;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
li:last-child {
border-bottom: none;
}
li time {
font-size: 12px;
padding-bottom: 20px;
}
form:before, .error:before {
content: '';
position: absolute;
top: 0;
right: 0;
left: 0;
height: 15px;
border-bottom: 1px solid #6c615c;
background: #8d7d77;
}
form, .error {
width: 520px;
padding: 30px;
margin-bottom: 50px;
background: #fff;
border: 1px solid #ccc;
position: relative;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
form input {
width: 50%;
clear: both;
}
페이지를 다시 불러오면 새로운 발견이 있습니다.코멘트를 늘려서 효과가 있는지 확인해 보세요.
12.Packaging the application
포장:
lein ring uberjar
패키지 직접 실행:
java -jartarget/guestbook-0.1.0-SNAPSHOT-standalone.jar
배포할 경우 Apache Tomcat과 같이 다음을 실행합니다.
lein ring uberwar
원하는 곳에 배치할 수 있습니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSON
JSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다.
그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다.
저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.
Luminus 언어를 사용하려면 Leiningen 설치가 필요합니다.Leiningen 설치는 다음 단계를 포함한 간단한 절차입니다.
1. 스크립트 다운로드
2. 실행 가능한 것으로 설정 (예:chmod + x lein)
3. 그것을 당신의 $경로에 놓으세요.(예: ~/bin)
4. leinself-install을 실행하고 설치가 완료될 때까지 기다립니다.
wget https://raw.github.com/technomancy/leiningen/stable/bin/lein
chmod +x lein
mv lein ~/bin
lein self-install
3.Creating a new application
Leiningen이 설치되면 터미널에서 다음 명령을 실행하여 애플리케이션을 초기화할 수 있습니다.
leinnew luminus guestbook +h2
cdguestbook
H2 내장형 데이터베이스를 엔진으로 하는 새 템플릿 프로젝트가 생성됩니다.
이제 다음 절차에 따라 프로젝트를 실행할 수 있습니다.
>leinring server
guestbookstarted successfully...
2013-03-01 19:05:30.389:INFO:oejs.Server:jetty-7.6.1.v20120215
Startedserver on port 3000
2013-03-01 19:05:30.459:INFO:oejs.AbstractConnector:StartedSelectChannelConnect
19:05:30.459:INFO:oejs.AbstractConnector:[email protected]:3000
새 브라우저 창이 뜰 것입니다. 프로그램이 실행 중인 것을 볼 수 있을 것입니다.새 브라우저를 꺼내지 않으려면 다음을 실행할 수 있습니다.
leinring server-headless
다음과 같은 사용자 정의 포트를 사용할 수도 있습니다.
leinring server-headless 8000
4.Anatomy of a Luminus application
새로 만든 응용 프로그램은 다음과 같은 구조를 가지고 있다Procfile
README.md
project.clj
src
└ log4j.xml
guestbook
└ handler.clj
layout.clj
middleware.clj
util.clj
repl.clj
db
└ core.clj
schema.clj
routes
└ home.clj
test
└ guestbook
└ test
└ handler.clj
resources
└ templates
└ about.html
base.html
home.html
└ public
└ css
└ screen.css
fonts
└ glyphicons-halflings-regular.eot
glyphicons-halflings-regular.svg
glyphicons-halflings-regular.ttf
glyphicons-halflings-regular.woff
img
js
md
└ docs.md
응용 프로그램의 루트 폴더에 있는 파일의 역할을 살펴보겠습니다.
procfile - Heroku 배포를 촉진하는 데 사용됩니다.
readme.md - 응용 프로그램 문서의 일반적인 보관소.
project.clj - 프로젝트의 구성 및 종속성을 Leiningen에서 관리합니다.
5.The Source Directory
모든 코드는 SRC 폴더 아래에 있습니다.우리의 응용 프로그램을 방명록이라고 부르기 때문에, 이것은 프로젝트의 루트 이름 공간입니다.우리를 위해 만들어진 모든 명명 공간을 살펴보자.
guestbook
handler.clj - 응용 프로그램의 기본 노선을 정의합니다. 이것은 프로그램의 입구점입니다.
layout.clj - 레이아웃 도움말이 있는 이름 공간입니다. 우리가 정의한 모든 웹 페이지는 그들의 경로를 여기에 추가해야 합니다.
middleware.clj - 프로그램 사용자 정의 중간부품을 포함하는 이름 공간
util.clj - 일반적인 액세스 기능에 사용되며 미리 제공되는 MD - HTML 도우미입니다.
repl.clj - REPL에서 응용 프로그램을 시작하고 중지하는 기능 제공
log4j.xml 레코드 구성
guestbook.db
db 이름 공간은 프로그램의 모델을 정의하고 데이터 영구층을 처리하는 데 사용됩니다.
core.clj - 함수 저장 및 데이터베이스 상호작용
schema.clj - 연결 매개 변수와 데이터베이스 테이블 정의에 사용
guestbook.routes
루트 이름 공간은 우리 홈페이지의 루트와 컨트롤러가 있는 위치입니다.authentication(인증)이나 specificworkflows (특정한 작업 절차) 와 같은routes를 더 추가하면, 그들을 위한 이름 공간을 만들어야 합니다.
home.clj - 홈과 프로그램 관련 페이지를 정의하는 이름 공간
6.The Test Directory
이것은 우리 프로그램을 설치하는 테스트에 사용되며, 이미 우리를 위해 두 개의 테스트 샘플을 정의했다.
7.The ResourcesDirectory
이것은 우리 프로그램의 모든 정적 자원을 배치하는 데 쓰인다.이미 폴더 CSS, JavaScript, images, markdown이 정의되어 있습니다.
HTML templates
템플릿 디렉토리는 응용 프로그램 페이지를 나타내는 Selmer 템플릿입니다.
about.html - 페이지
base.html-사이트를 위한 기본 레이아웃
html - 홈페이지
8.Adding Dependencies
위에서 언급한 바와 같이 모든 의존 관계 관리는 프로젝트 업데이트를 통해 이루어진다.clj 파일.루트 폴더에서 만든 응용 프로그램의 항목 파일을 찾을 수 있습니다. 다음과 같습니다.
(defproject
guestbook "0.1.0-SNAPSHOT"
:url "http://example.com/FIXME"
:description "FIXME: write description"
:dependencies
[[com.h2database/h2 "1.4.178"]
[ring-server "0.3.1"]
[environ "0.5.0"]
[com.taoensso/timbre "3.2.1"]
[markdown-clj "0.9.44"]
[korma "0.3.1"]
[com.taoensso/tower "2.0.2"]
[selmer "0.6.6"]
[org.clojure/clojure "1.6.0"]
[log4j
"1.2.17"
:exclusions
[javax.mail/mail
javax.jms/jms
com.sun.jdmk/jmxtools
com.sun.jmx/jmxri]]
[compojure "1.1.8"]
[lib-noir "0.8.3"]]
:plugins
[[lein-ring "0.8.7"] [lein-environ "0.5.0"]]
:ring
{:handler guestbook.handler/app,
:init guestbook.handler/init,
:destroy guestbook.handler/destroy}
:profiles
{:uberjar {:aot :all}
:production
{:ring
{:open-browser? false, :stacktraces? false, :auto-reload? false}},
:dev
{:dependencies [[ring-mock "0.1.5"] [ring/ring-devel "1.2.2"]],
:env {:dev true}}}
:min-lein-version "2.0.0")
보시다시피 프로젝트입니다.clj는 키/value 설명이 포함된 다른 방면의 Clojure 목록일 뿐입니다.사용자 정의 의존 zhixu를 추가하려면 dependenciesvector (의존 벡터) 에 간단하게 추가합니다.
9.Accessingthe Database
우선, 우리는 응용 프로그램을 위한 모델을 만들 것입니다. 이렇게 하면 src/guestbook/db 폴더에 있는 schema를 열 것입니다.clj 파일.여기서 우리는 이미 우리의 데이터베이스 연결에 대해 정의를 내렸다.JDBC 드라이버 JDBCdriver, 프로토콜protocol, 사용자user, 비밀번호password, H2 데이터베이스를 사용하는 데이터베이스 파일을 포함하는 간단한 맵을 정의합니다.(def db-spec {:classname "org.h2.Driver"
:subprotocol "h2"
:subname (str (io/resource-path) db-store)
:user "sa"
:password ""
:naming {:keys clojure.string/upper-case
:fields clojure.string/upper-case}})
다음에create-users-table에user표 정의가 있는 함수가 있습니다.이 함수 대신create-guestbook-table 함수를 사용합니다.(defn create-guestbook-table []
(sql/db-do-commands
db-spec
(sql/create-table-ddl
:guestbook
[:id "INTEGER PRIMARY KEY AUTO_INCREMENT"]
[:timestamp :timestamp]
[:name "varchar(30)"]
[:message "varchar(200)"]))
(sql/db-do-prepared db-spec
"CREATE INDEX timestamp_index ON guestbook (timestamp)"))
메모표는 주석자의 이름, 메일의 내용과 시간 스탬프 등 모든 필드 설명 정보를 저장합니다.
create-tables 함수를 업데이트하여 호출합니다.(defn create-tables
"creates the database tables used by the application"
[]
(create-guestbook-table))
만든 표로 우리는 우리의 메시지에 읽고 쓰는 기능을 추가할 수 있다.src/guestbook/db/core를 엽니다.clj 파일을 추가하십시오.우리는 이미 사용자 테이블을 처리하는 코드가 있는 것을 보았다.우리는 아래의 코드로 그들을 대체할 것이다.(ns guestbook.db.core
(:use korma.core
[korma.db :only (defdb)])
(:require [guestbook.db.schema :as schema]))
(defdb db schema/db-spec)
(defentity guestbook)
(defn save-message
[name message]
(insert guestbook
(values {:name name
:message message
:timestamp (new java.util.Date)})))
(defn get-messages []
(select guestbook))
위에서 우리는 하나의 실체를 만들어서 우리가 명명 공간을 구축하는 데 메모표를 만드는 것을 대표한다.그리고 함수save-message와 get-messages를 추가하여 그것과 상호작용합니다.
10.Running Code on Startup
핸들handler 이름 공간에는 함수 init가 포함되어 있습니다.프로그램이 시작될 때, 이 함수는 한 번 호출될 것이다.데이터베이스가 초기화되었는지 확인하기 위해 코드를 추가합니다. 필요하면 초기화합니다.
우리는 우선 구조 명칭 공간을 참고해야 한다. initialized를 사용하기 위해서?그리고create-tables의 기능.(ns guestbook.handler
(:use ...)
(:require ...
[guestbook.db.schema :as schema]))
다음은 init 함수를 업데이트합니다(defn init
"init will be called once when
app is deployed as a servlet on
an app server such as Tomcat
put any initialization code here"
[]
(timbre/set-config!
[:appenders :rotor]
{:min-level :info
:enabled? true
:async? false ; should be always false for rotor
:max-message-per-msecs nil
:fn rotor/appender-fn})
(timbre/set-config!
[:shared-appender-config :rotor]
{:path "guestbook.log" :max-size (* 512 1024) :backlog 10})
(if (env :selmer-dev) (parser/cache-off!))
;;initialize the database if needed
(if-not (schema/initialized?) (schema/create-tables))
(timbre/info "guestbook started successfully"))
프로그램의 init 함수를 바꿨기 때문에 서비스 (ctrl+c) 를 끄고 서비스 (leinring server) 를 다시 시작합니다
11.Creating Pages and HandlingForm Input
우리의 루트는 모두guestbook에 정의되어 있습니다.routes.홈 네임스페이스에서.그것을 열면 데이터베이스에서 정보를 읽는 이동은 논리를 증가시켜야 한다.우선, Referenc가 우리의db 명칭 공간을 늘려야 합니다.(ns guestbook.routes.home
(:use ...)
(:require ...
[guestbook.db.core :as db]))
다음으로 홈 페이지 컨트롤러를 변경합니다.(defn home-page [& [name message error]]
(layout/render "home.html"
{:error error
:name name
:message message
:messages (db/get-messages)}))
현재, 우리는 템플릿에 추가 파라미터를 추가할 수 있으며, 파라미터는 데이터베이스에서 나온 정보 목록이다.
우리는 사용자가 새로운 메시지를 발표할 수 있기를 희망하기 때문에handler에 controller theformposts를 추가해야 합니다:(defn save-message [name message]
(cond
(empty? name)
(home-page name message "Somebody forgot to leave a name")
(empty? message)
(home-page name message "Don't you have something to say?")
:else
(do
(db/save-message name message)
(home-page))))
마지막으로, 우리는 controller에 home-routes 정의에 루트를 추가합니다.(defroutes home-routes
(GET "/" [] (home-page))
(POST "/" [name message] (save-message name message))
(GET "/about" [] (about-page)))
현재, 우리의 컨트롤러는 이미 setup, 홈을 열었습니다.html 템플릿. {% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
<p>Time to start building your site!</p>
<p><a class="btn btn-primary btn-lg" href="http://luminusweb.net">Learn more »</a></p>
</div>
<div class="row-fluid">
<div class="span8">
{{content|safe}}
</div>
</div>
{% endblock %}
메시지 목록을 반복적으로 표시할 수 있도록 내용을 업데이트합니다.{% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
</div>
<div class="row-fluid">
<div class="span8">
<ul>
{% for item in messages %}
<li>
<time>{{item.timestamp|date:"yyyy-MM-dd HH:mm"}}</time>
<p>{{item.message}}</p>
<p> - {{item.name}}</p>
</li>
{% endfor %}
</ul>
</div>
</div>
{% endblock %}
보시다시피 우리는iterator를 사용하여 메시지를 달립니다.모든 메시지는 하나의 맵입니다. 메시지,name,timestamp 키워드를 포함하여name를 통해 얻을 수 있습니다.또한useof the date filter to format the timestamps into a humanreadableform.
다음은 컨트롤러에 발생할 수 있는 오류를 보여주기 위해 error 모듈을 추가해야 합니다.{% if error %}
<p class="error">{{error}}</p>
{% endif %}
error 모듈이 작동하는지 간단하게 테스트해 보세요.마지막으로, 사용자가 메시지를 제출할 수 있는form을 만듭니다.<form action="/" method="POST">
<p>
Name:
<input type="text" name="name" value={{name}}>
</p>
<p>
Message:
<textarea rows="4" cols="50" name="message">
{{message}}
</textarea>
</p>
<input type="submit" value="comment">
</form>
home.html template는 다음과 같습니다.{% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
</div>
<div class="row-fluid">
<div class="span8">
<ul>
{% for item in messages %}
<li>
<time>{{item.timestamp|date:"yyyy-MM-dd HH:mm"}}</time>
<p>{{item.message}}</p>
<p> - {{item.name}}</p>
</li>
{% endfor %}
</ul>
{% if error %}
<p class="error">{{error}}</p>
{% endif %}
</div>
<div class="span8">
<form action="/" method="POST">
<p>
Name:
<input type="text" name="name" value="{{name}}" />
</p>
<p>
Message:
<textarea rows="4" cols="50" name="message" />{{message}}</textarea>
</p>
<input type="submit" value="comment" />
</form>
</div>
</div>
{% endblock %}
마지막으로, 화면을 업데이트합니다.css 파일, 페이지의 아름다움:body {
height: 100%;
padding-top: 70px;
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #eaeaea;
color: #4d4d4d;
width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
input[type=submit] {
margin: 0;
padding: 0;
border: 0;
line-height: 1.4em;
background: none;
vertical-align: baseline;
}
input[type=submit], textarea {
font-size: 24px;
font-family: inherit;
border: 0;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
}
input[type=submit]:hover {
background: rgba(0, 0, 0, 0.15);
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);
}
textarea {
position: relative;
line-height: 1em;
width: 100%;
}
.error {
font-weight: bold;
color: red;
}
.jumbotron {
position: relative;
background: white;
z-index: 2;
border-top: 1px dotted #adadad;
}
h1 {
width: 100%;
font-size: 70px;
font-weight: bold;
text-align: center;
}
ul {
margin: 0;
padding: 0;
list-style: none;
}
li {
position: relative;
font-size: 16px;
padding: 5px;
border-bottom: 1px dotted #ccc;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
li:last-child {
border-bottom: none;
}
li time {
font-size: 12px;
padding-bottom: 20px;
}
form:before, .error:before {
content: '';
position: absolute;
top: 0;
right: 0;
left: 0;
height: 15px;
border-bottom: 1px solid #6c615c;
background: #8d7d77;
}
form, .error {
width: 520px;
padding: 30px;
margin-bottom: 50px;
background: #fff;
border: 1px solid #ccc;
position: relative;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
form input {
width: 50%;
clear: both;
}
페이지를 다시 불러오면 새로운 발견이 있습니다.코멘트를 늘려서 효과가 있는지 확인해 보세요.
12.Packaging the application
포장:
lein ring uberjar
패키지 직접 실행:
java -jartarget/guestbook-0.1.0-SNAPSHOT-standalone.jar
배포할 경우 Apache Tomcat과 같이 다음을 실행합니다.
lein ring uberwar
원하는 곳에 배치할 수 있습니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSON
JSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다.
그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다.
저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.
새로 만든 응용 프로그램은 다음과 같은 구조를 가지고 있다
Procfile
README.md
project.clj
src
└ log4j.xml
guestbook
└ handler.clj
layout.clj
middleware.clj
util.clj
repl.clj
db
└ core.clj
schema.clj
routes
└ home.clj
test
└ guestbook
└ test
└ handler.clj
resources
└ templates
└ about.html
base.html
home.html
└ public
└ css
└ screen.css
fonts
└ glyphicons-halflings-regular.eot
glyphicons-halflings-regular.svg
glyphicons-halflings-regular.ttf
glyphicons-halflings-regular.woff
img
js
md
└ docs.md
응용 프로그램의 루트 폴더에 있는 파일의 역할을 살펴보겠습니다.
procfile - Heroku 배포를 촉진하는 데 사용됩니다.
readme.md - 응용 프로그램 문서의 일반적인 보관소.
project.clj - 프로젝트의 구성 및 종속성을 Leiningen에서 관리합니다.
5.The Source Directory
모든 코드는 SRC 폴더 아래에 있습니다.우리의 응용 프로그램을 방명록이라고 부르기 때문에, 이것은 프로젝트의 루트 이름 공간입니다.우리를 위해 만들어진 모든 명명 공간을 살펴보자.
guestbook
handler.clj - 응용 프로그램의 기본 노선을 정의합니다. 이것은 프로그램의 입구점입니다.
layout.clj - 레이아웃 도움말이 있는 이름 공간입니다. 우리가 정의한 모든 웹 페이지는 그들의 경로를 여기에 추가해야 합니다.
middleware.clj - 프로그램 사용자 정의 중간부품을 포함하는 이름 공간
util.clj - 일반적인 액세스 기능에 사용되며 미리 제공되는 MD - HTML 도우미입니다.
repl.clj - REPL에서 응용 프로그램을 시작하고 중지하는 기능 제공
log4j.xml 레코드 구성
guestbook.db
db 이름 공간은 프로그램의 모델을 정의하고 데이터 영구층을 처리하는 데 사용됩니다.
core.clj - 함수 저장 및 데이터베이스 상호작용
schema.clj - 연결 매개 변수와 데이터베이스 테이블 정의에 사용
guestbook.routes
루트 이름 공간은 우리 홈페이지의 루트와 컨트롤러가 있는 위치입니다.authentication(인증)이나 specificworkflows (특정한 작업 절차) 와 같은routes를 더 추가하면, 그들을 위한 이름 공간을 만들어야 합니다.
home.clj - 홈과 프로그램 관련 페이지를 정의하는 이름 공간
6.The Test Directory
이것은 우리 프로그램을 설치하는 테스트에 사용되며, 이미 우리를 위해 두 개의 테스트 샘플을 정의했다.
7.The ResourcesDirectory
이것은 우리 프로그램의 모든 정적 자원을 배치하는 데 쓰인다.이미 폴더 CSS, JavaScript, images, markdown이 정의되어 있습니다.
HTML templates
템플릿 디렉토리는 응용 프로그램 페이지를 나타내는 Selmer 템플릿입니다.
about.html - 페이지
base.html-사이트를 위한 기본 레이아웃
html - 홈페이지
8.Adding Dependencies
위에서 언급한 바와 같이 모든 의존 관계 관리는 프로젝트 업데이트를 통해 이루어진다.clj 파일.루트 폴더에서 만든 응용 프로그램의 항목 파일을 찾을 수 있습니다. 다음과 같습니다.
(defproject
guestbook "0.1.0-SNAPSHOT"
:url "http://example.com/FIXME"
:description "FIXME: write description"
:dependencies
[[com.h2database/h2 "1.4.178"]
[ring-server "0.3.1"]
[environ "0.5.0"]
[com.taoensso/timbre "3.2.1"]
[markdown-clj "0.9.44"]
[korma "0.3.1"]
[com.taoensso/tower "2.0.2"]
[selmer "0.6.6"]
[org.clojure/clojure "1.6.0"]
[log4j
"1.2.17"
:exclusions
[javax.mail/mail
javax.jms/jms
com.sun.jdmk/jmxtools
com.sun.jmx/jmxri]]
[compojure "1.1.8"]
[lib-noir "0.8.3"]]
:plugins
[[lein-ring "0.8.7"] [lein-environ "0.5.0"]]
:ring
{:handler guestbook.handler/app,
:init guestbook.handler/init,
:destroy guestbook.handler/destroy}
:profiles
{:uberjar {:aot :all}
:production
{:ring
{:open-browser? false, :stacktraces? false, :auto-reload? false}},
:dev
{:dependencies [[ring-mock "0.1.5"] [ring/ring-devel "1.2.2"]],
:env {:dev true}}}
:min-lein-version "2.0.0")
보시다시피 프로젝트입니다.clj는 키/value 설명이 포함된 다른 방면의 Clojure 목록일 뿐입니다.사용자 정의 의존 zhixu를 추가하려면 dependenciesvector (의존 벡터) 에 간단하게 추가합니다.
9.Accessingthe Database
우선, 우리는 응용 프로그램을 위한 모델을 만들 것입니다. 이렇게 하면 src/guestbook/db 폴더에 있는 schema를 열 것입니다.clj 파일.여기서 우리는 이미 우리의 데이터베이스 연결에 대해 정의를 내렸다.JDBC 드라이버 JDBCdriver, 프로토콜protocol, 사용자user, 비밀번호password, H2 데이터베이스를 사용하는 데이터베이스 파일을 포함하는 간단한 맵을 정의합니다.(def db-spec {:classname "org.h2.Driver"
:subprotocol "h2"
:subname (str (io/resource-path) db-store)
:user "sa"
:password ""
:naming {:keys clojure.string/upper-case
:fields clojure.string/upper-case}})
다음에create-users-table에user표 정의가 있는 함수가 있습니다.이 함수 대신create-guestbook-table 함수를 사용합니다.(defn create-guestbook-table []
(sql/db-do-commands
db-spec
(sql/create-table-ddl
:guestbook
[:id "INTEGER PRIMARY KEY AUTO_INCREMENT"]
[:timestamp :timestamp]
[:name "varchar(30)"]
[:message "varchar(200)"]))
(sql/db-do-prepared db-spec
"CREATE INDEX timestamp_index ON guestbook (timestamp)"))
메모표는 주석자의 이름, 메일의 내용과 시간 스탬프 등 모든 필드 설명 정보를 저장합니다.
create-tables 함수를 업데이트하여 호출합니다.(defn create-tables
"creates the database tables used by the application"
[]
(create-guestbook-table))
만든 표로 우리는 우리의 메시지에 읽고 쓰는 기능을 추가할 수 있다.src/guestbook/db/core를 엽니다.clj 파일을 추가하십시오.우리는 이미 사용자 테이블을 처리하는 코드가 있는 것을 보았다.우리는 아래의 코드로 그들을 대체할 것이다.(ns guestbook.db.core
(:use korma.core
[korma.db :only (defdb)])
(:require [guestbook.db.schema :as schema]))
(defdb db schema/db-spec)
(defentity guestbook)
(defn save-message
[name message]
(insert guestbook
(values {:name name
:message message
:timestamp (new java.util.Date)})))
(defn get-messages []
(select guestbook))
위에서 우리는 하나의 실체를 만들어서 우리가 명명 공간을 구축하는 데 메모표를 만드는 것을 대표한다.그리고 함수save-message와 get-messages를 추가하여 그것과 상호작용합니다.
10.Running Code on Startup
핸들handler 이름 공간에는 함수 init가 포함되어 있습니다.프로그램이 시작될 때, 이 함수는 한 번 호출될 것이다.데이터베이스가 초기화되었는지 확인하기 위해 코드를 추가합니다. 필요하면 초기화합니다.
우리는 우선 구조 명칭 공간을 참고해야 한다. initialized를 사용하기 위해서?그리고create-tables의 기능.(ns guestbook.handler
(:use ...)
(:require ...
[guestbook.db.schema :as schema]))
다음은 init 함수를 업데이트합니다(defn init
"init will be called once when
app is deployed as a servlet on
an app server such as Tomcat
put any initialization code here"
[]
(timbre/set-config!
[:appenders :rotor]
{:min-level :info
:enabled? true
:async? false ; should be always false for rotor
:max-message-per-msecs nil
:fn rotor/appender-fn})
(timbre/set-config!
[:shared-appender-config :rotor]
{:path "guestbook.log" :max-size (* 512 1024) :backlog 10})
(if (env :selmer-dev) (parser/cache-off!))
;;initialize the database if needed
(if-not (schema/initialized?) (schema/create-tables))
(timbre/info "guestbook started successfully"))
프로그램의 init 함수를 바꿨기 때문에 서비스 (ctrl+c) 를 끄고 서비스 (leinring server) 를 다시 시작합니다
11.Creating Pages and HandlingForm Input
우리의 루트는 모두guestbook에 정의되어 있습니다.routes.홈 네임스페이스에서.그것을 열면 데이터베이스에서 정보를 읽는 이동은 논리를 증가시켜야 한다.우선, Referenc가 우리의db 명칭 공간을 늘려야 합니다.(ns guestbook.routes.home
(:use ...)
(:require ...
[guestbook.db.core :as db]))
다음으로 홈 페이지 컨트롤러를 변경합니다.(defn home-page [& [name message error]]
(layout/render "home.html"
{:error error
:name name
:message message
:messages (db/get-messages)}))
현재, 우리는 템플릿에 추가 파라미터를 추가할 수 있으며, 파라미터는 데이터베이스에서 나온 정보 목록이다.
우리는 사용자가 새로운 메시지를 발표할 수 있기를 희망하기 때문에handler에 controller theformposts를 추가해야 합니다:(defn save-message [name message]
(cond
(empty? name)
(home-page name message "Somebody forgot to leave a name")
(empty? message)
(home-page name message "Don't you have something to say?")
:else
(do
(db/save-message name message)
(home-page))))
마지막으로, 우리는 controller에 home-routes 정의에 루트를 추가합니다.(defroutes home-routes
(GET "/" [] (home-page))
(POST "/" [name message] (save-message name message))
(GET "/about" [] (about-page)))
현재, 우리의 컨트롤러는 이미 setup, 홈을 열었습니다.html 템플릿. {% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
<p>Time to start building your site!</p>
<p><a class="btn btn-primary btn-lg" href="http://luminusweb.net">Learn more »</a></p>
</div>
<div class="row-fluid">
<div class="span8">
{{content|safe}}
</div>
</div>
{% endblock %}
메시지 목록을 반복적으로 표시할 수 있도록 내용을 업데이트합니다.{% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
</div>
<div class="row-fluid">
<div class="span8">
<ul>
{% for item in messages %}
<li>
<time>{{item.timestamp|date:"yyyy-MM-dd HH:mm"}}</time>
<p>{{item.message}}</p>
<p> - {{item.name}}</p>
</li>
{% endfor %}
</ul>
</div>
</div>
{% endblock %}
보시다시피 우리는iterator를 사용하여 메시지를 달립니다.모든 메시지는 하나의 맵입니다. 메시지,name,timestamp 키워드를 포함하여name를 통해 얻을 수 있습니다.또한useof the date filter to format the timestamps into a humanreadableform.
다음은 컨트롤러에 발생할 수 있는 오류를 보여주기 위해 error 모듈을 추가해야 합니다.{% if error %}
<p class="error">{{error}}</p>
{% endif %}
error 모듈이 작동하는지 간단하게 테스트해 보세요.마지막으로, 사용자가 메시지를 제출할 수 있는form을 만듭니다.<form action="/" method="POST">
<p>
Name:
<input type="text" name="name" value={{name}}>
</p>
<p>
Message:
<textarea rows="4" cols="50" name="message">
{{message}}
</textarea>
</p>
<input type="submit" value="comment">
</form>
home.html template는 다음과 같습니다.{% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
</div>
<div class="row-fluid">
<div class="span8">
<ul>
{% for item in messages %}
<li>
<time>{{item.timestamp|date:"yyyy-MM-dd HH:mm"}}</time>
<p>{{item.message}}</p>
<p> - {{item.name}}</p>
</li>
{% endfor %}
</ul>
{% if error %}
<p class="error">{{error}}</p>
{% endif %}
</div>
<div class="span8">
<form action="/" method="POST">
<p>
Name:
<input type="text" name="name" value="{{name}}" />
</p>
<p>
Message:
<textarea rows="4" cols="50" name="message" />{{message}}</textarea>
</p>
<input type="submit" value="comment" />
</form>
</div>
</div>
{% endblock %}
마지막으로, 화면을 업데이트합니다.css 파일, 페이지의 아름다움:body {
height: 100%;
padding-top: 70px;
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #eaeaea;
color: #4d4d4d;
width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
input[type=submit] {
margin: 0;
padding: 0;
border: 0;
line-height: 1.4em;
background: none;
vertical-align: baseline;
}
input[type=submit], textarea {
font-size: 24px;
font-family: inherit;
border: 0;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
}
input[type=submit]:hover {
background: rgba(0, 0, 0, 0.15);
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);
}
textarea {
position: relative;
line-height: 1em;
width: 100%;
}
.error {
font-weight: bold;
color: red;
}
.jumbotron {
position: relative;
background: white;
z-index: 2;
border-top: 1px dotted #adadad;
}
h1 {
width: 100%;
font-size: 70px;
font-weight: bold;
text-align: center;
}
ul {
margin: 0;
padding: 0;
list-style: none;
}
li {
position: relative;
font-size: 16px;
padding: 5px;
border-bottom: 1px dotted #ccc;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
li:last-child {
border-bottom: none;
}
li time {
font-size: 12px;
padding-bottom: 20px;
}
form:before, .error:before {
content: '';
position: absolute;
top: 0;
right: 0;
left: 0;
height: 15px;
border-bottom: 1px solid #6c615c;
background: #8d7d77;
}
form, .error {
width: 520px;
padding: 30px;
margin-bottom: 50px;
background: #fff;
border: 1px solid #ccc;
position: relative;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
form input {
width: 50%;
clear: both;
}
페이지를 다시 불러오면 새로운 발견이 있습니다.코멘트를 늘려서 효과가 있는지 확인해 보세요.
12.Packaging the application
포장:
lein ring uberjar
패키지 직접 실행:
java -jartarget/guestbook-0.1.0-SNAPSHOT-standalone.jar
배포할 경우 Apache Tomcat과 같이 다음을 실행합니다.
lein ring uberwar
원하는 곳에 배치할 수 있습니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSON
JSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다.
그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다.
저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.
이것은 우리 프로그램을 설치하는 테스트에 사용되며, 이미 우리를 위해 두 개의 테스트 샘플을 정의했다.
7.The ResourcesDirectory
이것은 우리 프로그램의 모든 정적 자원을 배치하는 데 쓰인다.이미 폴더 CSS, JavaScript, images, markdown이 정의되어 있습니다.
HTML templates
템플릿 디렉토리는 응용 프로그램 페이지를 나타내는 Selmer 템플릿입니다.
about.html - 페이지
base.html-사이트를 위한 기본 레이아웃
html - 홈페이지
8.Adding Dependencies
위에서 언급한 바와 같이 모든 의존 관계 관리는 프로젝트 업데이트를 통해 이루어진다.clj 파일.루트 폴더에서 만든 응용 프로그램의 항목 파일을 찾을 수 있습니다. 다음과 같습니다.
(defproject
guestbook "0.1.0-SNAPSHOT"
:url "http://example.com/FIXME"
:description "FIXME: write description"
:dependencies
[[com.h2database/h2 "1.4.178"]
[ring-server "0.3.1"]
[environ "0.5.0"]
[com.taoensso/timbre "3.2.1"]
[markdown-clj "0.9.44"]
[korma "0.3.1"]
[com.taoensso/tower "2.0.2"]
[selmer "0.6.6"]
[org.clojure/clojure "1.6.0"]
[log4j
"1.2.17"
:exclusions
[javax.mail/mail
javax.jms/jms
com.sun.jdmk/jmxtools
com.sun.jmx/jmxri]]
[compojure "1.1.8"]
[lib-noir "0.8.3"]]
:plugins
[[lein-ring "0.8.7"] [lein-environ "0.5.0"]]
:ring
{:handler guestbook.handler/app,
:init guestbook.handler/init,
:destroy guestbook.handler/destroy}
:profiles
{:uberjar {:aot :all}
:production
{:ring
{:open-browser? false, :stacktraces? false, :auto-reload? false}},
:dev
{:dependencies [[ring-mock "0.1.5"] [ring/ring-devel "1.2.2"]],
:env {:dev true}}}
:min-lein-version "2.0.0")
보시다시피 프로젝트입니다.clj는 키/value 설명이 포함된 다른 방면의 Clojure 목록일 뿐입니다.사용자 정의 의존 zhixu를 추가하려면 dependenciesvector (의존 벡터) 에 간단하게 추가합니다.
9.Accessingthe Database
우선, 우리는 응용 프로그램을 위한 모델을 만들 것입니다. 이렇게 하면 src/guestbook/db 폴더에 있는 schema를 열 것입니다.clj 파일.여기서 우리는 이미 우리의 데이터베이스 연결에 대해 정의를 내렸다.JDBC 드라이버 JDBCdriver, 프로토콜protocol, 사용자user, 비밀번호password, H2 데이터베이스를 사용하는 데이터베이스 파일을 포함하는 간단한 맵을 정의합니다.(def db-spec {:classname "org.h2.Driver"
:subprotocol "h2"
:subname (str (io/resource-path) db-store)
:user "sa"
:password ""
:naming {:keys clojure.string/upper-case
:fields clojure.string/upper-case}})
다음에create-users-table에user표 정의가 있는 함수가 있습니다.이 함수 대신create-guestbook-table 함수를 사용합니다.(defn create-guestbook-table []
(sql/db-do-commands
db-spec
(sql/create-table-ddl
:guestbook
[:id "INTEGER PRIMARY KEY AUTO_INCREMENT"]
[:timestamp :timestamp]
[:name "varchar(30)"]
[:message "varchar(200)"]))
(sql/db-do-prepared db-spec
"CREATE INDEX timestamp_index ON guestbook (timestamp)"))
메모표는 주석자의 이름, 메일의 내용과 시간 스탬프 등 모든 필드 설명 정보를 저장합니다.
create-tables 함수를 업데이트하여 호출합니다.(defn create-tables
"creates the database tables used by the application"
[]
(create-guestbook-table))
만든 표로 우리는 우리의 메시지에 읽고 쓰는 기능을 추가할 수 있다.src/guestbook/db/core를 엽니다.clj 파일을 추가하십시오.우리는 이미 사용자 테이블을 처리하는 코드가 있는 것을 보았다.우리는 아래의 코드로 그들을 대체할 것이다.(ns guestbook.db.core
(:use korma.core
[korma.db :only (defdb)])
(:require [guestbook.db.schema :as schema]))
(defdb db schema/db-spec)
(defentity guestbook)
(defn save-message
[name message]
(insert guestbook
(values {:name name
:message message
:timestamp (new java.util.Date)})))
(defn get-messages []
(select guestbook))
위에서 우리는 하나의 실체를 만들어서 우리가 명명 공간을 구축하는 데 메모표를 만드는 것을 대표한다.그리고 함수save-message와 get-messages를 추가하여 그것과 상호작용합니다.
10.Running Code on Startup
핸들handler 이름 공간에는 함수 init가 포함되어 있습니다.프로그램이 시작될 때, 이 함수는 한 번 호출될 것이다.데이터베이스가 초기화되었는지 확인하기 위해 코드를 추가합니다. 필요하면 초기화합니다.
우리는 우선 구조 명칭 공간을 참고해야 한다. initialized를 사용하기 위해서?그리고create-tables의 기능.(ns guestbook.handler
(:use ...)
(:require ...
[guestbook.db.schema :as schema]))
다음은 init 함수를 업데이트합니다(defn init
"init will be called once when
app is deployed as a servlet on
an app server such as Tomcat
put any initialization code here"
[]
(timbre/set-config!
[:appenders :rotor]
{:min-level :info
:enabled? true
:async? false ; should be always false for rotor
:max-message-per-msecs nil
:fn rotor/appender-fn})
(timbre/set-config!
[:shared-appender-config :rotor]
{:path "guestbook.log" :max-size (* 512 1024) :backlog 10})
(if (env :selmer-dev) (parser/cache-off!))
;;initialize the database if needed
(if-not (schema/initialized?) (schema/create-tables))
(timbre/info "guestbook started successfully"))
프로그램의 init 함수를 바꿨기 때문에 서비스 (ctrl+c) 를 끄고 서비스 (leinring server) 를 다시 시작합니다
11.Creating Pages and HandlingForm Input
우리의 루트는 모두guestbook에 정의되어 있습니다.routes.홈 네임스페이스에서.그것을 열면 데이터베이스에서 정보를 읽는 이동은 논리를 증가시켜야 한다.우선, Referenc가 우리의db 명칭 공간을 늘려야 합니다.(ns guestbook.routes.home
(:use ...)
(:require ...
[guestbook.db.core :as db]))
다음으로 홈 페이지 컨트롤러를 변경합니다.(defn home-page [& [name message error]]
(layout/render "home.html"
{:error error
:name name
:message message
:messages (db/get-messages)}))
현재, 우리는 템플릿에 추가 파라미터를 추가할 수 있으며, 파라미터는 데이터베이스에서 나온 정보 목록이다.
우리는 사용자가 새로운 메시지를 발표할 수 있기를 희망하기 때문에handler에 controller theformposts를 추가해야 합니다:(defn save-message [name message]
(cond
(empty? name)
(home-page name message "Somebody forgot to leave a name")
(empty? message)
(home-page name message "Don't you have something to say?")
:else
(do
(db/save-message name message)
(home-page))))
마지막으로, 우리는 controller에 home-routes 정의에 루트를 추가합니다.(defroutes home-routes
(GET "/" [] (home-page))
(POST "/" [name message] (save-message name message))
(GET "/about" [] (about-page)))
현재, 우리의 컨트롤러는 이미 setup, 홈을 열었습니다.html 템플릿. {% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
<p>Time to start building your site!</p>
<p><a class="btn btn-primary btn-lg" href="http://luminusweb.net">Learn more »</a></p>
</div>
<div class="row-fluid">
<div class="span8">
{{content|safe}}
</div>
</div>
{% endblock %}
메시지 목록을 반복적으로 표시할 수 있도록 내용을 업데이트합니다.{% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
</div>
<div class="row-fluid">
<div class="span8">
<ul>
{% for item in messages %}
<li>
<time>{{item.timestamp|date:"yyyy-MM-dd HH:mm"}}</time>
<p>{{item.message}}</p>
<p> - {{item.name}}</p>
</li>
{% endfor %}
</ul>
</div>
</div>
{% endblock %}
보시다시피 우리는iterator를 사용하여 메시지를 달립니다.모든 메시지는 하나의 맵입니다. 메시지,name,timestamp 키워드를 포함하여name를 통해 얻을 수 있습니다.또한useof the date filter to format the timestamps into a humanreadableform.
다음은 컨트롤러에 발생할 수 있는 오류를 보여주기 위해 error 모듈을 추가해야 합니다.{% if error %}
<p class="error">{{error}}</p>
{% endif %}
error 모듈이 작동하는지 간단하게 테스트해 보세요.마지막으로, 사용자가 메시지를 제출할 수 있는form을 만듭니다.<form action="/" method="POST">
<p>
Name:
<input type="text" name="name" value={{name}}>
</p>
<p>
Message:
<textarea rows="4" cols="50" name="message">
{{message}}
</textarea>
</p>
<input type="submit" value="comment">
</form>
home.html template는 다음과 같습니다.{% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
</div>
<div class="row-fluid">
<div class="span8">
<ul>
{% for item in messages %}
<li>
<time>{{item.timestamp|date:"yyyy-MM-dd HH:mm"}}</time>
<p>{{item.message}}</p>
<p> - {{item.name}}</p>
</li>
{% endfor %}
</ul>
{% if error %}
<p class="error">{{error}}</p>
{% endif %}
</div>
<div class="span8">
<form action="/" method="POST">
<p>
Name:
<input type="text" name="name" value="{{name}}" />
</p>
<p>
Message:
<textarea rows="4" cols="50" name="message" />{{message}}</textarea>
</p>
<input type="submit" value="comment" />
</form>
</div>
</div>
{% endblock %}
마지막으로, 화면을 업데이트합니다.css 파일, 페이지의 아름다움:body {
height: 100%;
padding-top: 70px;
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #eaeaea;
color: #4d4d4d;
width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
input[type=submit] {
margin: 0;
padding: 0;
border: 0;
line-height: 1.4em;
background: none;
vertical-align: baseline;
}
input[type=submit], textarea {
font-size: 24px;
font-family: inherit;
border: 0;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
}
input[type=submit]:hover {
background: rgba(0, 0, 0, 0.15);
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);
}
textarea {
position: relative;
line-height: 1em;
width: 100%;
}
.error {
font-weight: bold;
color: red;
}
.jumbotron {
position: relative;
background: white;
z-index: 2;
border-top: 1px dotted #adadad;
}
h1 {
width: 100%;
font-size: 70px;
font-weight: bold;
text-align: center;
}
ul {
margin: 0;
padding: 0;
list-style: none;
}
li {
position: relative;
font-size: 16px;
padding: 5px;
border-bottom: 1px dotted #ccc;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
li:last-child {
border-bottom: none;
}
li time {
font-size: 12px;
padding-bottom: 20px;
}
form:before, .error:before {
content: '';
position: absolute;
top: 0;
right: 0;
left: 0;
height: 15px;
border-bottom: 1px solid #6c615c;
background: #8d7d77;
}
form, .error {
width: 520px;
padding: 30px;
margin-bottom: 50px;
background: #fff;
border: 1px solid #ccc;
position: relative;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
form input {
width: 50%;
clear: both;
}
페이지를 다시 불러오면 새로운 발견이 있습니다.코멘트를 늘려서 효과가 있는지 확인해 보세요.
12.Packaging the application
포장:
lein ring uberjar
패키지 직접 실행:
java -jartarget/guestbook-0.1.0-SNAPSHOT-standalone.jar
배포할 경우 Apache Tomcat과 같이 다음을 실행합니다.
lein ring uberwar
원하는 곳에 배치할 수 있습니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSON
JSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다.
그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다.
저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.
위에서 언급한 바와 같이 모든 의존 관계 관리는 프로젝트 업데이트를 통해 이루어진다.clj 파일.루트 폴더에서 만든 응용 프로그램의 항목 파일을 찾을 수 있습니다. 다음과 같습니다.
(defproject
guestbook "0.1.0-SNAPSHOT"
:url "http://example.com/FIXME"
:description "FIXME: write description"
:dependencies
[[com.h2database/h2 "1.4.178"]
[ring-server "0.3.1"]
[environ "0.5.0"]
[com.taoensso/timbre "3.2.1"]
[markdown-clj "0.9.44"]
[korma "0.3.1"]
[com.taoensso/tower "2.0.2"]
[selmer "0.6.6"]
[org.clojure/clojure "1.6.0"]
[log4j
"1.2.17"
:exclusions
[javax.mail/mail
javax.jms/jms
com.sun.jdmk/jmxtools
com.sun.jmx/jmxri]]
[compojure "1.1.8"]
[lib-noir "0.8.3"]]
:plugins
[[lein-ring "0.8.7"] [lein-environ "0.5.0"]]
:ring
{:handler guestbook.handler/app,
:init guestbook.handler/init,
:destroy guestbook.handler/destroy}
:profiles
{:uberjar {:aot :all}
:production
{:ring
{:open-browser? false, :stacktraces? false, :auto-reload? false}},
:dev
{:dependencies [[ring-mock "0.1.5"] [ring/ring-devel "1.2.2"]],
:env {:dev true}}}
:min-lein-version "2.0.0")
보시다시피 프로젝트입니다.clj는 키/value 설명이 포함된 다른 방면의 Clojure 목록일 뿐입니다.사용자 정의 의존 zhixu를 추가하려면 dependenciesvector (의존 벡터) 에 간단하게 추가합니다.
9.Accessingthe Database
우선, 우리는 응용 프로그램을 위한 모델을 만들 것입니다. 이렇게 하면 src/guestbook/db 폴더에 있는 schema를 열 것입니다.clj 파일.여기서 우리는 이미 우리의 데이터베이스 연결에 대해 정의를 내렸다.JDBC 드라이버 JDBCdriver, 프로토콜protocol, 사용자user, 비밀번호password, H2 데이터베이스를 사용하는 데이터베이스 파일을 포함하는 간단한 맵을 정의합니다.(def db-spec {:classname "org.h2.Driver"
:subprotocol "h2"
:subname (str (io/resource-path) db-store)
:user "sa"
:password ""
:naming {:keys clojure.string/upper-case
:fields clojure.string/upper-case}})
다음에create-users-table에user표 정의가 있는 함수가 있습니다.이 함수 대신create-guestbook-table 함수를 사용합니다.(defn create-guestbook-table []
(sql/db-do-commands
db-spec
(sql/create-table-ddl
:guestbook
[:id "INTEGER PRIMARY KEY AUTO_INCREMENT"]
[:timestamp :timestamp]
[:name "varchar(30)"]
[:message "varchar(200)"]))
(sql/db-do-prepared db-spec
"CREATE INDEX timestamp_index ON guestbook (timestamp)"))
메모표는 주석자의 이름, 메일의 내용과 시간 스탬프 등 모든 필드 설명 정보를 저장합니다.
create-tables 함수를 업데이트하여 호출합니다.(defn create-tables
"creates the database tables used by the application"
[]
(create-guestbook-table))
만든 표로 우리는 우리의 메시지에 읽고 쓰는 기능을 추가할 수 있다.src/guestbook/db/core를 엽니다.clj 파일을 추가하십시오.우리는 이미 사용자 테이블을 처리하는 코드가 있는 것을 보았다.우리는 아래의 코드로 그들을 대체할 것이다.(ns guestbook.db.core
(:use korma.core
[korma.db :only (defdb)])
(:require [guestbook.db.schema :as schema]))
(defdb db schema/db-spec)
(defentity guestbook)
(defn save-message
[name message]
(insert guestbook
(values {:name name
:message message
:timestamp (new java.util.Date)})))
(defn get-messages []
(select guestbook))
위에서 우리는 하나의 실체를 만들어서 우리가 명명 공간을 구축하는 데 메모표를 만드는 것을 대표한다.그리고 함수save-message와 get-messages를 추가하여 그것과 상호작용합니다.
10.Running Code on Startup
핸들handler 이름 공간에는 함수 init가 포함되어 있습니다.프로그램이 시작될 때, 이 함수는 한 번 호출될 것이다.데이터베이스가 초기화되었는지 확인하기 위해 코드를 추가합니다. 필요하면 초기화합니다.
우리는 우선 구조 명칭 공간을 참고해야 한다. initialized를 사용하기 위해서?그리고create-tables의 기능.(ns guestbook.handler
(:use ...)
(:require ...
[guestbook.db.schema :as schema]))
다음은 init 함수를 업데이트합니다(defn init
"init will be called once when
app is deployed as a servlet on
an app server such as Tomcat
put any initialization code here"
[]
(timbre/set-config!
[:appenders :rotor]
{:min-level :info
:enabled? true
:async? false ; should be always false for rotor
:max-message-per-msecs nil
:fn rotor/appender-fn})
(timbre/set-config!
[:shared-appender-config :rotor]
{:path "guestbook.log" :max-size (* 512 1024) :backlog 10})
(if (env :selmer-dev) (parser/cache-off!))
;;initialize the database if needed
(if-not (schema/initialized?) (schema/create-tables))
(timbre/info "guestbook started successfully"))
프로그램의 init 함수를 바꿨기 때문에 서비스 (ctrl+c) 를 끄고 서비스 (leinring server) 를 다시 시작합니다
11.Creating Pages and HandlingForm Input
우리의 루트는 모두guestbook에 정의되어 있습니다.routes.홈 네임스페이스에서.그것을 열면 데이터베이스에서 정보를 읽는 이동은 논리를 증가시켜야 한다.우선, Referenc가 우리의db 명칭 공간을 늘려야 합니다.(ns guestbook.routes.home
(:use ...)
(:require ...
[guestbook.db.core :as db]))
다음으로 홈 페이지 컨트롤러를 변경합니다.(defn home-page [& [name message error]]
(layout/render "home.html"
{:error error
:name name
:message message
:messages (db/get-messages)}))
현재, 우리는 템플릿에 추가 파라미터를 추가할 수 있으며, 파라미터는 데이터베이스에서 나온 정보 목록이다.
우리는 사용자가 새로운 메시지를 발표할 수 있기를 희망하기 때문에handler에 controller theformposts를 추가해야 합니다:(defn save-message [name message]
(cond
(empty? name)
(home-page name message "Somebody forgot to leave a name")
(empty? message)
(home-page name message "Don't you have something to say?")
:else
(do
(db/save-message name message)
(home-page))))
마지막으로, 우리는 controller에 home-routes 정의에 루트를 추가합니다.(defroutes home-routes
(GET "/" [] (home-page))
(POST "/" [name message] (save-message name message))
(GET "/about" [] (about-page)))
현재, 우리의 컨트롤러는 이미 setup, 홈을 열었습니다.html 템플릿. {% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
<p>Time to start building your site!</p>
<p><a class="btn btn-primary btn-lg" href="http://luminusweb.net">Learn more »</a></p>
</div>
<div class="row-fluid">
<div class="span8">
{{content|safe}}
</div>
</div>
{% endblock %}
메시지 목록을 반복적으로 표시할 수 있도록 내용을 업데이트합니다.{% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
</div>
<div class="row-fluid">
<div class="span8">
<ul>
{% for item in messages %}
<li>
<time>{{item.timestamp|date:"yyyy-MM-dd HH:mm"}}</time>
<p>{{item.message}}</p>
<p> - {{item.name}}</p>
</li>
{% endfor %}
</ul>
</div>
</div>
{% endblock %}
보시다시피 우리는iterator를 사용하여 메시지를 달립니다.모든 메시지는 하나의 맵입니다. 메시지,name,timestamp 키워드를 포함하여name를 통해 얻을 수 있습니다.또한useof the date filter to format the timestamps into a humanreadableform.
다음은 컨트롤러에 발생할 수 있는 오류를 보여주기 위해 error 모듈을 추가해야 합니다.{% if error %}
<p class="error">{{error}}</p>
{% endif %}
error 모듈이 작동하는지 간단하게 테스트해 보세요.마지막으로, 사용자가 메시지를 제출할 수 있는form을 만듭니다.<form action="/" method="POST">
<p>
Name:
<input type="text" name="name" value={{name}}>
</p>
<p>
Message:
<textarea rows="4" cols="50" name="message">
{{message}}
</textarea>
</p>
<input type="submit" value="comment">
</form>
home.html template는 다음과 같습니다.{% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
</div>
<div class="row-fluid">
<div class="span8">
<ul>
{% for item in messages %}
<li>
<time>{{item.timestamp|date:"yyyy-MM-dd HH:mm"}}</time>
<p>{{item.message}}</p>
<p> - {{item.name}}</p>
</li>
{% endfor %}
</ul>
{% if error %}
<p class="error">{{error}}</p>
{% endif %}
</div>
<div class="span8">
<form action="/" method="POST">
<p>
Name:
<input type="text" name="name" value="{{name}}" />
</p>
<p>
Message:
<textarea rows="4" cols="50" name="message" />{{message}}</textarea>
</p>
<input type="submit" value="comment" />
</form>
</div>
</div>
{% endblock %}
마지막으로, 화면을 업데이트합니다.css 파일, 페이지의 아름다움:body {
height: 100%;
padding-top: 70px;
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #eaeaea;
color: #4d4d4d;
width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
input[type=submit] {
margin: 0;
padding: 0;
border: 0;
line-height: 1.4em;
background: none;
vertical-align: baseline;
}
input[type=submit], textarea {
font-size: 24px;
font-family: inherit;
border: 0;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
}
input[type=submit]:hover {
background: rgba(0, 0, 0, 0.15);
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);
}
textarea {
position: relative;
line-height: 1em;
width: 100%;
}
.error {
font-weight: bold;
color: red;
}
.jumbotron {
position: relative;
background: white;
z-index: 2;
border-top: 1px dotted #adadad;
}
h1 {
width: 100%;
font-size: 70px;
font-weight: bold;
text-align: center;
}
ul {
margin: 0;
padding: 0;
list-style: none;
}
li {
position: relative;
font-size: 16px;
padding: 5px;
border-bottom: 1px dotted #ccc;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
li:last-child {
border-bottom: none;
}
li time {
font-size: 12px;
padding-bottom: 20px;
}
form:before, .error:before {
content: '';
position: absolute;
top: 0;
right: 0;
left: 0;
height: 15px;
border-bottom: 1px solid #6c615c;
background: #8d7d77;
}
form, .error {
width: 520px;
padding: 30px;
margin-bottom: 50px;
background: #fff;
border: 1px solid #ccc;
position: relative;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
form input {
width: 50%;
clear: both;
}
페이지를 다시 불러오면 새로운 발견이 있습니다.코멘트를 늘려서 효과가 있는지 확인해 보세요.
12.Packaging the application
포장:
lein ring uberjar
패키지 직접 실행:
java -jartarget/guestbook-0.1.0-SNAPSHOT-standalone.jar
배포할 경우 Apache Tomcat과 같이 다음을 실행합니다.
lein ring uberwar
원하는 곳에 배치할 수 있습니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSON
JSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다.
그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다.
저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.
(def db-spec {:classname "org.h2.Driver"
:subprotocol "h2"
:subname (str (io/resource-path) db-store)
:user "sa"
:password ""
:naming {:keys clojure.string/upper-case
:fields clojure.string/upper-case}})
(defn create-guestbook-table []
(sql/db-do-commands
db-spec
(sql/create-table-ddl
:guestbook
[:id "INTEGER PRIMARY KEY AUTO_INCREMENT"]
[:timestamp :timestamp]
[:name "varchar(30)"]
[:message "varchar(200)"]))
(sql/db-do-prepared db-spec
"CREATE INDEX timestamp_index ON guestbook (timestamp)"))
(defn create-tables
"creates the database tables used by the application"
[]
(create-guestbook-table))
(ns guestbook.db.core
(:use korma.core
[korma.db :only (defdb)])
(:require [guestbook.db.schema :as schema]))
(defdb db schema/db-spec)
(defentity guestbook)
(defn save-message
[name message]
(insert guestbook
(values {:name name
:message message
:timestamp (new java.util.Date)})))
(defn get-messages []
(select guestbook))
핸들handler 이름 공간에는 함수 init가 포함되어 있습니다.프로그램이 시작될 때, 이 함수는 한 번 호출될 것이다.데이터베이스가 초기화되었는지 확인하기 위해 코드를 추가합니다. 필요하면 초기화합니다.
우리는 우선 구조 명칭 공간을 참고해야 한다. initialized를 사용하기 위해서?그리고create-tables의 기능.
(ns guestbook.handler
(:use ...)
(:require ...
[guestbook.db.schema :as schema]))
다음은 init 함수를 업데이트합니다
(defn init
"init will be called once when
app is deployed as a servlet on
an app server such as Tomcat
put any initialization code here"
[]
(timbre/set-config!
[:appenders :rotor]
{:min-level :info
:enabled? true
:async? false ; should be always false for rotor
:max-message-per-msecs nil
:fn rotor/appender-fn})
(timbre/set-config!
[:shared-appender-config :rotor]
{:path "guestbook.log" :max-size (* 512 1024) :backlog 10})
(if (env :selmer-dev) (parser/cache-off!))
;;initialize the database if needed
(if-not (schema/initialized?) (schema/create-tables))
(timbre/info "guestbook started successfully"))
프로그램의 init 함수를 바꿨기 때문에 서비스 (ctrl+c) 를 끄고 서비스 (leinring server) 를 다시 시작합니다
11.Creating Pages and HandlingForm Input
우리의 루트는 모두guestbook에 정의되어 있습니다.routes.홈 네임스페이스에서.그것을 열면 데이터베이스에서 정보를 읽는 이동은 논리를 증가시켜야 한다.우선, Referenc가 우리의db 명칭 공간을 늘려야 합니다.(ns guestbook.routes.home
(:use ...)
(:require ...
[guestbook.db.core :as db]))
다음으로 홈 페이지 컨트롤러를 변경합니다.(defn home-page [& [name message error]]
(layout/render "home.html"
{:error error
:name name
:message message
:messages (db/get-messages)}))
현재, 우리는 템플릿에 추가 파라미터를 추가할 수 있으며, 파라미터는 데이터베이스에서 나온 정보 목록이다.
우리는 사용자가 새로운 메시지를 발표할 수 있기를 희망하기 때문에handler에 controller theformposts를 추가해야 합니다:(defn save-message [name message]
(cond
(empty? name)
(home-page name message "Somebody forgot to leave a name")
(empty? message)
(home-page name message "Don't you have something to say?")
:else
(do
(db/save-message name message)
(home-page))))
마지막으로, 우리는 controller에 home-routes 정의에 루트를 추가합니다.(defroutes home-routes
(GET "/" [] (home-page))
(POST "/" [name message] (save-message name message))
(GET "/about" [] (about-page)))
현재, 우리의 컨트롤러는 이미 setup, 홈을 열었습니다.html 템플릿. {% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
<p>Time to start building your site!</p>
<p><a class="btn btn-primary btn-lg" href="http://luminusweb.net">Learn more »</a></p>
</div>
<div class="row-fluid">
<div class="span8">
{{content|safe}}
</div>
</div>
{% endblock %}
메시지 목록을 반복적으로 표시할 수 있도록 내용을 업데이트합니다.{% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
</div>
<div class="row-fluid">
<div class="span8">
<ul>
{% for item in messages %}
<li>
<time>{{item.timestamp|date:"yyyy-MM-dd HH:mm"}}</time>
<p>{{item.message}}</p>
<p> - {{item.name}}</p>
</li>
{% endfor %}
</ul>
</div>
</div>
{% endblock %}
보시다시피 우리는iterator를 사용하여 메시지를 달립니다.모든 메시지는 하나의 맵입니다. 메시지,name,timestamp 키워드를 포함하여name를 통해 얻을 수 있습니다.또한useof the date filter to format the timestamps into a humanreadableform.
다음은 컨트롤러에 발생할 수 있는 오류를 보여주기 위해 error 모듈을 추가해야 합니다.{% if error %}
<p class="error">{{error}}</p>
{% endif %}
error 모듈이 작동하는지 간단하게 테스트해 보세요.마지막으로, 사용자가 메시지를 제출할 수 있는form을 만듭니다.<form action="/" method="POST">
<p>
Name:
<input type="text" name="name" value={{name}}>
</p>
<p>
Message:
<textarea rows="4" cols="50" name="message">
{{message}}
</textarea>
</p>
<input type="submit" value="comment">
</form>
home.html template는 다음과 같습니다.{% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
</div>
<div class="row-fluid">
<div class="span8">
<ul>
{% for item in messages %}
<li>
<time>{{item.timestamp|date:"yyyy-MM-dd HH:mm"}}</time>
<p>{{item.message}}</p>
<p> - {{item.name}}</p>
</li>
{% endfor %}
</ul>
{% if error %}
<p class="error">{{error}}</p>
{% endif %}
</div>
<div class="span8">
<form action="/" method="POST">
<p>
Name:
<input type="text" name="name" value="{{name}}" />
</p>
<p>
Message:
<textarea rows="4" cols="50" name="message" />{{message}}</textarea>
</p>
<input type="submit" value="comment" />
</form>
</div>
</div>
{% endblock %}
마지막으로, 화면을 업데이트합니다.css 파일, 페이지의 아름다움:body {
height: 100%;
padding-top: 70px;
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #eaeaea;
color: #4d4d4d;
width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
input[type=submit] {
margin: 0;
padding: 0;
border: 0;
line-height: 1.4em;
background: none;
vertical-align: baseline;
}
input[type=submit], textarea {
font-size: 24px;
font-family: inherit;
border: 0;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
}
input[type=submit]:hover {
background: rgba(0, 0, 0, 0.15);
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);
}
textarea {
position: relative;
line-height: 1em;
width: 100%;
}
.error {
font-weight: bold;
color: red;
}
.jumbotron {
position: relative;
background: white;
z-index: 2;
border-top: 1px dotted #adadad;
}
h1 {
width: 100%;
font-size: 70px;
font-weight: bold;
text-align: center;
}
ul {
margin: 0;
padding: 0;
list-style: none;
}
li {
position: relative;
font-size: 16px;
padding: 5px;
border-bottom: 1px dotted #ccc;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
li:last-child {
border-bottom: none;
}
li time {
font-size: 12px;
padding-bottom: 20px;
}
form:before, .error:before {
content: '';
position: absolute;
top: 0;
right: 0;
left: 0;
height: 15px;
border-bottom: 1px solid #6c615c;
background: #8d7d77;
}
form, .error {
width: 520px;
padding: 30px;
margin-bottom: 50px;
background: #fff;
border: 1px solid #ccc;
position: relative;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
form input {
width: 50%;
clear: both;
}
페이지를 다시 불러오면 새로운 발견이 있습니다.코멘트를 늘려서 효과가 있는지 확인해 보세요.
12.Packaging the application
포장:
lein ring uberjar
패키지 직접 실행:
java -jartarget/guestbook-0.1.0-SNAPSHOT-standalone.jar
배포할 경우 Apache Tomcat과 같이 다음을 실행합니다.
lein ring uberwar
원하는 곳에 배치할 수 있습니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSON
JSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다.
그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다.
저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.
(ns guestbook.routes.home
(:use ...)
(:require ...
[guestbook.db.core :as db]))
(defn home-page [& [name message error]]
(layout/render "home.html"
{:error error
:name name
:message message
:messages (db/get-messages)}))
(defn save-message [name message]
(cond
(empty? name)
(home-page name message "Somebody forgot to leave a name")
(empty? message)
(home-page name message "Don't you have something to say?")
:else
(do
(db/save-message name message)
(home-page))))
(defroutes home-routes
(GET "/" [] (home-page))
(POST "/" [name message] (save-message name message))
(GET "/about" [] (about-page)))
{% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
<p>Time to start building your site!</p>
<p><a class="btn btn-primary btn-lg" href="http://luminusweb.net">Learn more »</a></p>
</div>
<div class="row-fluid">
<div class="span8">
{{content|safe}}
</div>
</div>
{% endblock %}
{% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
</div>
<div class="row-fluid">
<div class="span8">
<ul>
{% for item in messages %}
<li>
<time>{{item.timestamp|date:"yyyy-MM-dd HH:mm"}}</time>
<p>{{item.message}}</p>
<p> - {{item.name}}</p>
</li>
{% endfor %}
</ul>
</div>
</div>
{% endblock %}
{% if error %}
<p class="error">{{error}}</p>
{% endif %}
<form action="/" method="POST">
<p>
Name:
<input type="text" name="name" value={{name}}>
</p>
<p>
Message:
<textarea rows="4" cols="50" name="message">
{{message}}
</textarea>
</p>
<input type="submit" value="comment">
</form>
{% extends "templates/base.html" %}
{% block content %}
<div class="jumbotron">
<h1>Welcome to guestbook</h1>
</div>
<div class="row-fluid">
<div class="span8">
<ul>
{% for item in messages %}
<li>
<time>{{item.timestamp|date:"yyyy-MM-dd HH:mm"}}</time>
<p>{{item.message}}</p>
<p> - {{item.name}}</p>
</li>
{% endfor %}
</ul>
{% if error %}
<p class="error">{{error}}</p>
{% endif %}
</div>
<div class="span8">
<form action="/" method="POST">
<p>
Name:
<input type="text" name="name" value="{{name}}" />
</p>
<p>
Message:
<textarea rows="4" cols="50" name="message" />{{message}}</textarea>
</p>
<input type="submit" value="comment" />
</form>
</div>
</div>
{% endblock %}
body {
height: 100%;
padding-top: 70px;
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #eaeaea;
color: #4d4d4d;
width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
-ms-font-smoothing: antialiased;
-o-font-smoothing: antialiased;
font-smoothing: antialiased;
}
input[type=submit] {
margin: 0;
padding: 0;
border: 0;
line-height: 1.4em;
background: none;
vertical-align: baseline;
}
input[type=submit], textarea {
font-size: 24px;
font-family: inherit;
border: 0;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
}
input[type=submit]:hover {
background: rgba(0, 0, 0, 0.15);
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);
}
textarea {
position: relative;
line-height: 1em;
width: 100%;
}
.error {
font-weight: bold;
color: red;
}
.jumbotron {
position: relative;
background: white;
z-index: 2;
border-top: 1px dotted #adadad;
}
h1 {
width: 100%;
font-size: 70px;
font-weight: bold;
text-align: center;
}
ul {
margin: 0;
padding: 0;
list-style: none;
}
li {
position: relative;
font-size: 16px;
padding: 5px;
border-bottom: 1px dotted #ccc;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
li:last-child {
border-bottom: none;
}
li time {
font-size: 12px;
padding-bottom: 20px;
}
form:before, .error:before {
content: '';
position: absolute;
top: 0;
right: 0;
left: 0;
height: 15px;
border-bottom: 1px solid #6c615c;
background: #8d7d77;
}
form, .error {
width: 520px;
padding: 30px;
margin-bottom: 50px;
background: #fff;
border: 1px solid #ccc;
position: relative;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.15);
}
form input {
width: 50%;
clear: both;
}
포장:
lein ring uberjar
패키지 직접 실행:
java -jartarget/guestbook-0.1.0-SNAPSHOT-standalone.jar
배포할 경우 Apache Tomcat과 같이 다음을 실행합니다.
lein ring uberwar
원하는 곳에 배치할 수 있습니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.