A quick tutorial of building server project based on Hunt Framework 3.2.0

Keywords: Go Database git MySQL Laravel

Hunt Framework is a full stack Web framework developed in D language, similar to Laravel / SpringBoot / Django, etc., which enables D language developers to create projects quickly. The built-in super multi business specifications are convenient for developers to use out of the box, and convenient for managers to review project code more easily.

This sample code is based on the latest version 3.2.0 of Hunt Framework. Next, let's feel the pleasure of using DLang to develop:)

1. Create a normal template page rendering project

1.1 create empty project based on skeleton project

First, use the git command to clone the skeleton project locally.

git clone https://github.com/huntlabs/hunt-skeleton.git myproject
cd myproject

1.2 modify the http listening address and listening port of the project

http related configuration items in config/application.conf The following content can be found in. The ip we are listening to is 127.0.0.1 port is 8080:

http.address = 127.0.0.1
http.port = 8080

1.3 controller

We can see the source code of source/app/controller/IndexController.d. This is a common controller. The code is as follows:

module app.controller.IndexController;

import hunt.framework;

class IndexController : Controller
{
    mixin MakeController;

    @Action
    string index()
    {
        return view.render("index");
    }
}

We can see that the index controller also has an index method, which is marked as an accessible page with @ Action, and the page is rendered with view view view index.html Template (where the extension of the template is omitted for security reasons).

The view here renders resources/views/default/index.html Template file.

1.4 route configuration

The default route configuration table, config/routes, can be found in the configuration file directory. The skeleton project has a record as follows:

GET    /    index.index

This semantics is to use GET method to access / this path will map to index method of index controller.

1.5 compile and run the project

The whole project is managed by dub package manager, and can be compiled and run in one command:

dub run -v

At this time, according to the ip and port access configured by you, you can:

http://127.0.0.1:8080

So far, your D language project is running, isn't it cool? 😎 Let's talk about database operation in the next chapter.

2 create an API project for adding, deleting, modifying and querying

Before creating the add, delete, modify and query API, we need to do some preparatory work. First, we need to create the table structure of the database. Second, we need to enable the routing group support of the framework so that users can use the example.com/api/ Or api.example.com The form can be accessed.

2.1 first, we turn on the routing group

In config/application.conf Configuration item found route.groups Amend to read:

route.groups = api:path:api

Let me explain api:path : the meaning of API: {KEY of routing group}: {way to access routing group}: {custom value of routing group}. After the above setting, our API access address prefix should be:

http://127.0.0.1:8080/api/

If we set to route.groups = api:domain:api.example.com The prefix to access the API address is:

http://api.example.com/

2.2 our table structure design

You can execute this SQL to create tables. Our database uses MySQL 5.7.x as an example.


SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for my_user
-- ----------------------------
DROP TABLE IF EXISTS `my_users`;
CREATE TABLE `my_users` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  `created` bigint(11) DEFAULT NULL,
  `updated` bigint(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

SET FOREIGN_KEY_CHECKS = 1;

2.3 modify database related configuration files

Database configuration item file in config/application.conf Modify it to find the following configuration and set it according to your local database environment:

# Database
database.driver = mysql
database.host = 127.0.0.1
database.port = 3306
database.database = myproject
database.username = root
database.password = 123456
database.charset = utf8
database.prefix = my_
database.enabled = true

2.4 create database model

Hunt Framework is also a built-in Model model. We create the Model class app/model/User.d:

module app.model.User;

import hunt.entity;

@Table("users")
class User : Model
{
    mixin MakeModel;

    @AutoIncrement
    @PrimaryKey
    ulong id;

    string username;
    string password;
    string email;
    
    uint created;
    uint updated;
}

Note that @ PrimaryKey is used to mark the id as the primary key, and @ AutoIncrement is used to mark the AutoIncrement, @ Table("users") is to let you fill in the real name of your own table, and the real name of our table is my_users, because all table prefixes are already in config/application.conf Configuration items in database.prefix = my_ It has been configured, so we only need to write users for the value here.

2.5 creating Repository objects

As long as this object inherits EntityRepository, it already contains many rich operation methods, app/repository/UserRepository.d:

module app.repository.UserRepository;

import hunt.framework;

import app.model.User;

class UserRepostiroy : EntityRepository!(User, ulong)
{

}

Here we define that the EntityRepository inherited by UserRepository is a kind of class that comes with the ORM library hunt entity. We use the template to pass the User class and the primary key type ulong that we defined. This compilation will help us deal with many things. We just need to remember how to write.

2.6 create a form validation class

As an API, it is difficult to receive and verify POST forms. Hunt Framework has built-in form verification mechanism. We need to implement an object app/form/UserForm.d for form verification:

module app.form.UserForm;

import hunt.framework;

class UserForm : Form
{
    mixin MakeForm;

    @Length(4, 30, "User name length must be in {{min}} reach {{max}} Between bits.")
    string username;

    @Length(8, 32, "Password length must be in {{min}} reach {{max}} Between bits.")
    string password;
    
    @NotEmpty("Email Address cannot be empty.")
    string email;
}

2.7 create controller corresponding to API

Because our API uses independent routing groups, we need to create a subdirectory API under the app/controller / directory to save the corresponding controller class file when creating a controller. Therefore, our class file is named app/controller/api/UserController.d:

module app.controller.api.UserController;

import hunt.framework;

import app.repository.UserRepostiroy;
import app.model.User;
import app.message.ResultMessage;
import app.form.UserForm;

class UserController : Controller
{
    mixin MakeController;

    @Action
    Response add(UserForm form)
    {
        // ResultMessage is the json message body to be returned
        auto resultMessage = new ResultMessage;

        // Get a validation result object using the valid() method
        auto valid = form.valid();
        if (!valid.isValid())
        {
            // Give an error code
            resultMessage.code = 10001;

            // valid.messages() method can get all error information. Here we simply get one error to return
            foreach (message; valid.messages())
            {
                resultMessage.message = message;
                break;
            }
        }
        else
        {
            auto repository = new UserRepository;

            auto user = new User;
            user.username = form.username;
            user.password = form.password;
            user.email = form.email;

            // Save model data to database
            repository.save(user);

            // Since there is no error, you do not need to set the error code. You will be prompted that the addition is successful
            import std.format : format;

            resultMessage.message = format!"user( %d )Added successfully!"(user.id);
        }

        // The returned result object will be automatically serialized from JsonResponse to json and returned to the client
        return new JsonResponse(resultMessage);
    }
}

Here is the code of ReusltMessage:
app/message/ReusultMessage.d

module app.message.ResultMessage;

class ResultMessage
{
    uint code = 0;
    string message;
}

2.8 API routing profile

Each routing group has its own routing configuration table. The API's routing configuration table is config/api.routes Is the rule simple? Let's look at adding routing configuration items for user interface:

POST    /user/add    user.add

Isn't it simple? Because it's api.routes So the controller will find the corresponding user controller and add method in the app/controller/api / directory.

2.9 test add user interface

Here we use Firefox plug-in for interface request. We add three fields according to the form requirements, namely username, password and email. We also fill in the fields according to the validation rules in UserForm. When we submit the form, we can see the following interface:

Here the user (9) is prompted to add successfully! , the number 9 here is actually the primary key ID returned after the user data is written into the library.

In order to test the function of form verification, we changed the password from 8-bit to 6-bit, because our rule in UserForm is set between 8-32-bit. Submit the form again as follows:

Here's how our form validation works:)

3 Summary

The most completed project directory structure is as follows:

MYRPOJECT/
├── config
│   ├── api.routes
│   ├── application.conf
│   └── routes
├── data
│   └── mysql.sql
├── dub.sdl
├── resources
│   ├── translations
│   │   ├── en-us
│   │   │   └── message.ini
│   │   └── zh-cn
│   │       └── message.ini
│   └── views
│       └── default
│           ├── footer.html
│           ├── header.html
│           └── index.html
├── source
│   ├── app
│   │   ├── controller
│   │   │   ├── IndexController.d
│   │   │   └── api
│   │   │       └── UserController.d
│   │   ├── form
│   │   │   └── UserForm.d
│   │   ├── message
│   │   │   └── ResultMessage.d
│   │   ├── model
│   │   │   └── User.d
│   │   └── repository
│   │       └── UserRepository.d
│   └── main.d
└── wwwroot
    └── favicon.ico

The whole project is also clear and clear. It is familiar with the use of the framework. Hunt Framework has the development efficiency as fast as Laravel, the standard database operation as spring boot, and the convenient deployment way as golang with native language after compilation.

Related resource address

Posted by jesse_james on Thu, 18 Jun 2020 02:11:58 -0700