最近在学习使用 Node.JS 框架, 边学习边使用, 花了大概 3 周 时间做完这个 web 应用 且在 12 月 16 凌晨左右上线成功(其实就是把开发环境搬到服务器), 地址: https://a.lishaoy.net
这个 Web 应用 的代码是开源的, 如对这个应用感兴趣, 想知道代码是如何运行的, 可以去我 GitHub 下载或 clone : 应用源码 https://github.com/persilee/adonis_pro
首先, 来看看用 3 周 时间做出来的应用都有些什么功能, 之后再看看选用的 Node.JS 框架, 最后看看 Node.JS 项目如何部署到服务器.
Web 应用功能
登录, 注册验证
登录功能
输入框没有输入点击登录会提示: 用户名, 密码不能为空
输入的用户错误或不存在会提示: 用户不存在
输入的密码错误会提示: 密码错误
登录后会重定向到用户上次访问的地址
Login
注册功能
输入框没有输入点击注册会提示: 用户名, 邮箱, 密码不能为空
用户名和邮箱与其他用户相同会提示: 用户名, 邮箱已存在
密码小于 6 位数会提示: 最小长度是 6 位
注册成功后会发送验证邮件到用户邮箱, 需点击邮箱按钮验证
Register
文章列表
登录进来, 会显示文章列表页面, 显示内容如下:
文章标题: 点击可进入文章详情页
- cd adonis_pro
- adonis serve --dev
- Route.resource('posts', 'PostController').middleware(
- new Map([
- [ [ 'create', 'store', 'edit', 'update', 'destroy' ], [ 'auth' ] ],
- [ [ 'update', 'destroy', 'edit' ], [ 'own:post' ] ]
- ])
- ).validator(new Map([
- [['posts.update', 'posts.store'], ['StorePost']]
- ]))
- Route.get(url, closure)
- Route.post(url, closure)
- Route.put(url, closure)
- Route.patch(url, closure)
- Route.delete(url, closure)
- Route.group(() => {
- Route.get('profile', 'ProfileController.edit').as('profile.edit')
- Route.post('profile', 'ProfileController.update').as('profile.update').validator('UpdateProfile')
- Route.get('password', 'PasswordController.edit').as('password.edit')
- Route.post('password', 'PasswordController.update').as('password.update').validator('UpdatePassword')
- })
- .prefix('settings')
- .middleware([ 'auth' ])
- async index ({ request, response, view }) {}
- /**
- * Render a form to be used for creating a new posts.
- * GET posts/create
- */
- async create ({ request, response, view }) {}
- /**
- * Create/save a new posts.
- * POST posts
- */
- async store ({ request, response, view }) {}
- /**
- * Display a single posts.
- * GET posts/:id
- */
- async show ({ request, response, view }) {}
- /**
- * Render a form to update an existing posts.
- * GET posts/:id/edit
- */
- async edit ({ request, response, view }) {}
- /**
- * Update posts details.
- * PUT or PATCH posts/:id
- */
- async update ({ request, response, view}) {}
- /**
- * Delete a posts with id.
- * DELETE posts/:id
- */
- async destroy ({ params, request, response }) {}
- }
- module.exports = PostController
- 'use strict'
- const Schema = use('Schema')
- class UsersSchema extends Schema {
- up () {
- this.create('users', (table) => {
- table.increments()
- table.timestamps()
- })
- }
- down () {
- this.drop('users')
- }
- }
- module.exports = UsersSchema
- 'use strict'
- const Schema = use('Schema')
- class UsersSchema extends Schema {
- up () {
- this.create('users', (table) => {
- table.increments()
- table.string('username', 80).notNullable().unique()
- table.string('email', 254).notNullable().unique()
- table.string('password', 60).notNullable()
- table.timestamps()
- })
- }
- down () {
- this.drop('users')
- }
- }
- module.exports = UsersSchema
- const Database = use('Database')
- class UserController {
- async index (request, response) {
- return await Database
- .table('users')
- .where('username', 'admin')
- .first()
- }
- }
- 'use strict'
- const Database = use('Database')
- class NotificationController {
- async followNotice ({ auth, view }) {
- const notices = await Database.raw('select users.id as user_id,users.username,users.email,b.title,b.created_at,b.is_read,b.id as post_id from adonis.users , (select posts.id,posts.title, a.user_id,a.created_at,a.is_read from adonis.posts,(SELECT post_user.post_id, post_user.user_id, post_user.created_at, post_user.is_read FROM adonis.post_user where post_user.post_id in (SELECT posts.id FROM adonis.posts where user_id = ?)) as a where posts.id = a.post_id) as b where b.user_id = users.id and b.user_id <> ? order by b.created_at desc limit 50',[ auth.user.id, auth.user.id ])
- }
- }
- module.exports = NotificationController
- 'use strict'
- const Model = use('Model')
- class User extends Model {
- }
- module.exports = User
- const Model = use('Model')
- class User extends Model {
- profile () {
- return this.hasOne('App/Models/Profile')
- }
- }
- module.exports = User
- const User = use('App/Models/User')
- const user = await User.find(1)
- const userProfile = await user.profile().fetch()
- async update ({ params, request, response, session, auth }) {
- const { title, content, user_id, tags } = request.all()
- const post = await Post.findOrFail(params.id)
- post.merge({ title, content})
- await post.save()
- await post.tags().sync(tags)
- session.flash({
- type: 'primary',
- message: 'Post updated successfully.'
- })
- return response.redirect(
- Route.url('PostController.show', {
- id: post.id
- })
- )
- }
- @loggedIn
- <h2> You are logged in </h2>
- @else
- <p> <a href="/login">Click here</a> to login </p>
- @endloggedIn
- export NVM_DIR="$HOME/.nvm"
- [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
- [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
- -> v10.13.0
- v11.2.0
- system
- default -> v10.13.0
- node -> stable (-> v11.2.0) (default)
- stable -> 11.2 (-> v11.2.0) (default)
- iojs -> N/A (default)
- lts/* -> lts/dubnium (-> v10.13.0)
- lts/argon -> v4.9.1 (-> N/A)
- lts/boron -> v6.14.4 (-> N/A)
- lts/carbon -> v8.13.0 (-> N/A)
- lts/dubnium -> v10.13.0
- HOST=0.0.0.0
- PORT=3333
- ...
- [PM2] Applying action restartProcessId on App [server](ids: 0)
- [PM2] [server](0)
- [PM2] Process successfully started
- server {
- listen 80;
- location / {
- proxy_pass http://127.0.0.1:3333;
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection 'upgrade';
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-Proto $scheme;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_cache_bypass $http_upgrade;
- }
- }
- pm2 stop server.JS #停止项目
- pm2 start server.JS #启动项目
- server {
- listen 80;
- listen 443 ssl http2; #SSL
- server_name a.lishaoy.NET; #域名
- ssl on;
- ssl_certificate /etc/letsencrypt/live/a.lishaoy.NET/server.pem; #证书目录
- ssl_certificate_key /etc/letsencrypt/live/a.lishaoy.NET/server.key; #证书目录
- ssl_protocols TLSv1.1 TLSv1.2;
- ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
- ssl_prefer_server_ciphers on;
- ssl_session_cache shared:SSL:10m;
- ssl_session_timeout 10m;
- if ($ssl_protocol = "") {
- rewrite ^(.*) https://$host$1 permanent;
- }
- error_page 497 https://$host$request_uri;
- error_page 404 /404.html;
- error_page 502 /502.HTML;
- location / {
- proxy_pass http://localhost:3333;
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection 'upgrade';
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-Proto $scheme;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_cache_bypass $http_upgrade;
- }
- }
来源: https://juejin.im/post/5c184e396fb9a049dc022ab5