QUESTIONS? CALL: (+84) 24 666 026 12

HiveTech Vietnam (Technology Solutions - Original Ideas - Shared Expertise)

HiveTech Vietnam (Technology Solutions - Original Ideas - Shared Expertise)

HiveTech is a technology company focus on AI and big data technologies for educational purposes.

T (+84) 24 666 026 12
Email: contact@hivetech.vn

HiveTech JSC
No. 3 Thanh Cong, Ba Dinh, Ha Noi

Open in Google Maps
  • HOME
  • SERVICES
  • OUR COMPANY
  • PARTNERS
  • CONTACT
  • RECRUITMENT
FREEQUOTE
  • Home
  • Posts tagged "#Spring_MVC"
2021-01-14

File upload trong Spring

Wednesday, 30 December 2020 by Thao Nguyen















Trong quá trình xây dựng một ứng dụng web nói chung. Việc lưu trữ, xử lý các tệp tin từ các request của người dùng là một tác vụ cơ bản cần phải có. Trong các ứng dụng Java web cũng không là ngoại lệ. Bài viết này mình xin giới thiệu cách xây dựng một ứng dụng Spring Web MCV có khả năng xử lý và lưu trữ các tệp tin được gửi lên thông qua giao thức HTTP.

Bài viết này sẽ tập trung vào cách Xư lý file được upload multilpart-form cùng một số phương pháp lưu trữ cơ bản.

Cấu hình

Xây dựng bằng Spring MVC

Spring cho phép ta xử lý file thông qua một đối tượng MultipartResolver mà Spring cung cấp, Và để nó có thể hoạt động, ta cần phải cấu hình chúng.

Đầu tiên chúng ta cần 1 dependency sau 

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>

Tiếp sau đó ta cần định nghĩa CommonsMultipartResolver Bean vào trong file cấu hình Spring của chúng ta

Java class annotation config

@Configuration
@EnableWebMvc
@ComponentScan(“hivetech.sang.*”)
public class MutilpartFileConfig {
   
    @Bean(name = “multipartResolver”)
    public CommonsMultipartResolver multipartResolver() {
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
        multipartResolver.setMaxUploadSize(100000);
        return multipartResolver;
    }
   
}

XML config

<beans xmlns=”https://www.springframework.org/schema/beans”
       xmlns:xsi=”https://www.w3.org/2001/XMLSchema-instance”
       xmlns:context=”https://www.springframework.org/schema/context”
       xsi:schemaLocation=”https://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd
       https://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd”>
 
    <context:component-scan base-package=”hivetech.sang.*”/>
    <bean id=”multipartResolver” class=”org.springframework.web.multipart.commons.CommonsMultipartResolver”>
        <property name=”maxUploadSize” value=”1000000″/>
    </bean>
</beans>

Đối tượng CommonsMultipartResolver có nhiều các property khác nhau như: uploadTempDir, defaultEncoding, maxUploadFilePerSize,… Tuỳ vào nhu cầu ta có thể thêm các trường này để config như mong muốn

Vậy là ta đã cấu hình xong. Bây giờ ứng dụng Spring WebMVC của chúng ta đã có thể hỗ trợ upload file như mong muốn.

Xây dựng bằng Spring boot

Với một ứng dụng Spring Boot. Mọi thứ ở trên đều được hỗ trợ. Thậm chí Spring Boot còn khiến nó trở nên dễ dàng hơn nữa khi mà ta không cần phải thực hiện bất cứ công đoạn cấu hình nào. Mọi thứ đã được Spring tự động thêm vào khi chúng ta thêm Web module của ứng dụng Spring boot

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>

 Việc còn lại ta cần làm là tuỳ chỉnh các thông số tương tự như với cách mà Spring MVC làm. Tất cả sẽ được định nghĩa trong file application.properties

spring.servlet.multipart.max-file-size=128KBspring.servlet.multipart.max-request-size=128KB
 #We can also control whether file uploading is enabled, and the location for temp file upload:
spring.servlet.multipart.enabled=true
#define the upload location by variable so that we can use the temporary location for different operating systems.spring.servlet.multipart.location=${java.io.tmpdir}

Các cách lưu trữ file

Lưu trữ file có nhiều phương pháp khác nhau, Tuỳ từng trường hợp ta có thể lựa chọn các cách lưu trữ phù hợp, Các cách lưu trữ phổ biến nhất hiện nay ta có thể kể tới:

  • Lưu trữ trực tiếp vào bộ nhớ của server và lưu tên file vào cơ sở dữ liệu
  • Lưu trữ thẳng vào database dưới dạng binary 
  • Lưu trữ trên các nền tảng đám mây, các server lưu trữ chuyên biệt như GoogleDrive, MinIO, AWS S3,… thông qua các API được cung cấp

Lưu trữ trực tiếp

Đây là phương pháp thường thấy trong các ứng dụng nhỏ, dung lượng các file không lớn do sự đơn giản của nó. Tuy nhiên phương pháp này có nhiều nhược điểm khi mà dữ liệu được lưu trực tiếp sẽ gây tốn cho tài nguyên máy chủ, cùng với đó sẽ khó nâng cấp được khi hệ thống  mở rộng

Ta tạo một đối tượng để có thể lấy ra thông tin về các custom setting được chúng ta tự định nghĩa trong file application.properties

Spring.servlet.multipart.max-file-size=128KB
spring.servlet.multipart.max-request-size=128KB
storage.location=D:/storage
mimes.type=image/jpg,image/png

Tạo một object để đọc config ở trên

@ConfigurationProperties(prefix = “storage”)
public class FileStoreConfig {
    /**
     * Folder location for storing files
     */
    private String location;
 
    public String getLocation() {
        return location;
    }
 
    public void setLocation(String location) {
        this.location = location;
    }
}

Tiếp đó ta sẽ tạo một đối tượng Service gồm các function cơ bản như lưu file, hiển thị

@Configuration
@EnableWebMvc
@ComponentScan("hivetech.sang.*")
public class MutilpartFileConfig {
   
    @Bean(name = "multipartResolver")
    public CommonsMultipartResolver multipartResolver() {
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
        multipartResolver.setMaxUploadSize(100000);
        return multipartResolver;
    }
   
}

Tiếp đó ta sẽ tạo một Controller để xử lý request

@RestController
public class FileManagerLocal {
 
    @Autowired
    private FileManagerLocalService fileManagerLocalService;
 
    @GetMapping(“/hello”)
    public String hello() {
        return “hello”;
    }
 
    @GetMapping(“/list-file”)
    public List<Object> listUploadedFiles() throws IOException {
        return Arrays.asList(fileManagerLocalService.loadAll().toArray());
    }
 
    @GetMapping(“/files/{filename:.+}”)
    public ResponseEntity<Resource> serveFile(@PathVariable String filename) {
 
        Resource file = fileManagerLocalService.loadAsResource(filename);
        return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION,
                “attachment; filename=\”” + file.getFilename() + “\””).body(file);
    }
 
    @PostMapping(“/add-file”)
    public ResponseEntity handleFileUpload(@RequestParam(“file”) MultipartFile[] file, @RequestParam(“description”) String desc) {
        return ResponseEntity.ok().body(fileManagerLocalService.store(file));
    }
 
    @ExceptionHandler(FileStoreException.class)
    public ResponseEntity<?> handleStorageFileNotFound(FileStoreException exc) {
        return new ResponseEntity(exc.getMessage(), HttpStatus.I_AM_A_TEAPOT);
    }
}

Ta sẽ test ứng dụng bằng Postman như sau 

Lưu trữ trực tiếp vào database dưới dạng binary

Đây là phương pháp ít được sử dụng hơn do có nhiều nhược điểm như giới hạn về dung lượng, gây khó khăn trong truy xuất dữ liệu,… Tuy nhiên nếu như các tệp tin nhỏ có thể sử dụng phương pháp này nhưng không khuyến khích

Đầu tiên ta tạo một Entity với một trường annotation Lob với kiểu dữ liệu byte[]

@Table(name = "file_entity")public class FileEntity {
@Id
@GeneratedValue
@Column(name = "id")private Long id; 
private String name; 
private String type;
@Lob
private byte[] content;
}

Tiếp đó ta tạo một Repository để thao tác với CSDL

@Repository
public interface FileDBRepo extends JpaRepository<FileEntity, Long> {
    FileEntity findByNameEquals(String filename);
    void deleteByNameEquals(String fileName);
}

Rồi sau đó ta cũng tạo một đối tượng Service cùng một số function cơ bản

@Service
public class FileManagerDBServiceIlpm implements FileManagerDBService {
    @Autowired
    FileDBRepo fileDBRepo;
 
    @Override
    public FileEntity store(MultipartFile file) {
        String fileName = StringUtils.cleanPath(file.getOriginalFilename());
        try {
            FileEntity FileDB = FileEntity.builder()
                    .name(fileName)
                    .type(file.getContentType())
                    .content(file.getBytes())
                    .build();
            return fileDBRepo.save(FileDB);
        } catch (IOException e) {
            throw new FileStoreException(“Cant save file with cause “+e.getMessage(), e);
        }
    }
 
    @Override
    public List<FileEntity> store(MultipartFile[] files) {
        return Arrays.asList(files).stream().map(this::store).collect(Collectors.toList());
    }
 
    @Override
    public void delete(String filename) {
        fileDBRepo.deleteByNameEquals(filename);
    }
 
    @Override
    public Resource loadAsResource(String filename) {
        return new ByteArrayResource(fileDBRepo.findByNameEquals(filename).getContent());
    }
}

Tạo Controller để xử lý Request 

@RestController()
@RequestMapping(path = “/db-manager”)
public class FileManagerDB {
    @Autowired
    FileManagerDBService fileManagerDBService;
 
    @GetMapping(“/hello”)
    public String hello() {
        return “hello”;
    }
 
    @GetMapping(“/files/{filename:.+}”)
    public ResponseEntity<Resource> serveFile(@PathVariable String filename) {
 
        Resource file = fileManagerDBService.loadAsResource(filename);
        return ResponseEntity.ok().body(file);
    }
 
    @PostMapping(“/add-file”)
    public ResponseEntity handleFileUpload(@RequestParam(“file”) MultipartFile[] file, @RequestParam(“description”) String desc) {
        return ResponseEntity.ok().body(fileManagerDBService.store(file));
    }
}
 

Ta tiến hành upload một ảnh 

Dữ liệu đã được lưu trong database dưới dạng nhị phân

Kiểu dữ liệu Blob trong mySQL có dung lượng lưu trữ lên tới 4GB (LONGBLOB)

Kết luận

Từ các ví dụ trên ta có thể thấy các cách lưu trữ khác nhau và tự rút ra được ưu nhược điểm. Cùng với đó là cách khởi tạo mà triển khai một ứng dụng Spring web hỗ trợ thao tác và xử lý file.

Ngoài ra chủ đề về upload và lưu trữ file trên các nền tảng đám mây sẽ được bổ sung trong 1 chủ đề khác.

Phần code chi tiết có thể xem tại đây Link

Phạm Đức Sang

#Spring_MVC
Read more
  • Published in Uncategorized
No Comments

Spring-MVC

Tuesday, 06 October 2020 by Thao Nguyen

 












Spring Framework là một khung mã nguồn mở để xây dựng các ứng dụng Java Web, nó mạnh và nhẹ dễ dàng sử dụng và hỗ trợ phát triển các ứng dụng Java. Spring framework hiện tại phiên bản 5.0 và nó có các thành phần cơ bản Spring MVC, Spring Security, Spring Data, Spring Web Services …. Spring MVC thuộc trong các phần cơ bản của Spring Framework, nếu bạn muốn nâng cấp sử dụng Spring Boot hay các phần nâng cao hơn bạn phải có kiến thức nền vững.

Trong bài viết này tôi giới thiệu về Spring MVC, gồm các phần chính:

  1. Khái quát Spring MVC
  2. DispatcherServlet
  3. Tạo một project Spring MVC
  4. Tổng kết

I. Khái quát Spring-MVC

Spring web MVC là web framework ban đầu được xây dựng trên Servlet API và được đưa vào Spring Framework từ đầu. Tên đầy đủ của nó là “Spring Web MVC” thường gọi là “Spring MVC”. Spring MVC cung cấp bộ khung, kiến trúc Model-View-Controller và các thành phần khác có sẵn trong thư viện để phát triển các ứng dụng web

Mô hình MVC dùng phân tách rõ ràng nhiệm vụ của từng phần ví dụ như phần logic đầu vào, logic business, giao diện người dùng và cung kết nối giữa các yếu tố.

  • Model gồm các POJO, Service, DAO, POJO là ?? … Plain Old Java Object là đối tượng Java thông thường không bị ràng buộc bởi bất kỳ hạn chế đặc biệt nào chỉ đơn giản có các thuộc tính và các phương thức  
  • View được hiểu là xem, hiển thị cho người dùng tức phía client thấy được Model, phần này có chứa các file HTML hiển thị ra trình duyệt: HTML, JSP ..
  • Controller xử lý yêu cầu của người dùng tức phía client ,xây dựng Model phù hợp và chuyển nó qua View: Dispatcher Controller, Handler Mapping, Controller

II. DispatcherServlet

MVC Framework được thiết kế xoay quanh DispatcherServlet. Giới thiệu sơ qua về DispatcherServlet và  mở rộng thành phần:

  •  DispatcherServlet là một lớp đứng ra quản lý toàn bộ các hành động của framework (front controller) trong suốt quá trình thực thi các lệnh thông qua HTTP request
  • HandlerMapping: chọn một đối tượng sẽ  xử lý các request dựa trên các thuộc tính và điều kiện của các request đó 
  • Handleradapter: thực thi các handler đã chọn 
  • HandlerInterceptor: ngăn chặn lọc các request từ user nó được coi như Servlet filter không bị quản lý bởi DispatcherServlet 
  • LocaleResolver: xử lý và lưu một phần các thông tin của user 
  • MultipartResolver:  làm cho việc  upload file dễ dàng hơn bằng cách gói các request lại 

Cách thức hoạt động Spring MVC hoạt động 

Set 1: Khi client (browser) gửi một yêu cầu HTTP request đến một URL.

DispatcherServlet của Spring MVC  nhận được yêu cầu   

Set 2: DispatcherServlet đi vào Handler Mapper xác định bộ điều khiển nào chịu trách nhiệm xử lý yêu cầu HTTP 

Set 3: Handler Mapper chọn bộ khiển được ánh xạ tới URL yêu cầu đến và trả về (selected Handler) và (Controller detail to dispatcherServlet) điều khiển chi tiết cho DispatcherServlet 

Set 4: Bây giờ DispatcherServlet hiểu bộ điều khiển nào chịu trách nhiệm xử lý yêu cầu nên DispatcherServlet sẽ chuyển yêu cầu đó đến bộ điều khiển(Controller)

Set 5 :  Bây giờ Controller xử lý yêu cầu ,xác thực yêu cầu,và tạo model with data. Sau đó Controller trả về tên logic của view và model cho dispatcherServlet 

Set 6: DispatcherServlet đẩy vào ViewResolver xử giải quyết một chế độ xem logic với chế độ xem vật lý tồn tại application

Set7: ViewResolver chịu trách nhiệm ánh xạ chế độ xem logic với chế độ xem thực tế và trả lại chi tiết chế độ xem thực tế trở lại DispatcherServlet

Set 8: DispatcherServlet gửi kết quả view và model đến View component

Set 9: View component merge view và model và form HTML, thành phần View component gửi đầu ra HTML trở lại DispatcherServlet

Set 10: DispatcherServlet cuối cùng gửi đầu ra HTML dưới dạng phản hồi trở lại trình duyệt để hiển thị

III. Tạo project spring mvc

  1. Công cụ và công nghệ sử dụng 
  • Spring MVC – 5.1.0 RELEASE
  • JDK – 1.8 or later
  • Maven – 3.5.1
  • Apache Tomcat – 8.5
  • IDE – STS/Eclipse Neon.3
  • JSTL – 1.2.1

Mô hình :

  1. Các bước tiến hành

2.1 Create Maven Web Application

Khởi tạo project maven tools  Eclipse IDE

2.2 Add Dependencies – pom.xml File

<project xmlns=”https://maven.apache.org/POM/4.0.0″ xmlns:xsi=”https://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd”>    <modelVersion>4.0.0</modelVersion>    <groupId>net.javaguides.springmvc</groupId>    <artifactId>springmvc5-helloworld-exmaple</artifactId>    <packaging>war</packaging>    <version>0.0.1-SNAPSHOT</version>    <name>springmvc5-helloworld-exmaple Maven Webapp</name>    <url>https://maven.apache.org</url>    <properties>       <failOnMissingWebXml>false</failOnMissingWebXml>    </properties>    <dependencies>        <!– https://mvnrepository.com/artifact/org.springframework/spring-webmvc –>        <dependency>            <groupId>org.springframework</groupId>            <artifactId>spring-webmvc</artifactId>            <version>5.1.0.RELEASE</version>        </dependency>
        <!– JSTL Dependency –>        <dependency>            <groupId>javax.servlet.jsp.jstl</groupId>            <artifactId>javax.servlet.jsp.jstl-api</artifactId>            <version>1.2.1</version>        </dependency>        <dependency>            <groupId>taglibs</groupId>            <artifactId>standard</artifactId>            <version>1.1.2</version>        </dependency>
        <!– Servlet Dependency –>        <dependency>             <groupId>javax.servlet</groupId>             <artifactId>javax.servlet-api</artifactId>             <version>3.1.0</version>             <scope>provided</scope>        </dependency>
        <!– JSP Dependency –>        <dependency>            <groupId>javax.servlet.jsp</groupId>            <artifactId>javax.servlet.jsp-api</artifactId>            <version>2.3.1</version>            <scope>provided</scope>        </dependency>     </dependencies>    <build>        <sourceDirectory>src/main/java</sourceDirectory>        <plugins>            <plugin>                <artifactId>maven-compiler-plugin</artifactId>                <version>3.5.1</version>                <configuration>                    <source>1.8</source>                    <target>1.8</target>                </configuration>            </plugin>        </plugins>     </build></project>

2.3 Project Structure

Chú ý : 

Model – HelloWorld.java

View – helloworld.java

Controller – HelloWorldController.java

2.4 Spring Configuration – AppConfig.java

Khởi tạo AppConfig  sử dụng các annotated @Configuration , @EnableWebMvc và @ComponentScan 

package net.javaguides.springmvc.helloworld.config;
import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.EnableWebMvc;import org.springframework.web.servlet.view.InternalResourceViewResolver;import org.springframework.web.servlet.view.JstlView;
/** * @author Ramesh Fadatare */
@Configuration@EnableWebMvc@ComponentScan(basePackages = {    “net.javaguides.springmvc.helloworld”})public class AppConfig {
    @Bean    public InternalResourceViewResolver resolver() {        InternalResourceViewResolver resolver = new InternalResourceViewResolver();        resolver.setViewClass(JstlView.class);        resolver.setPrefix(“/WEB-INF/views/”);        resolver.setSuffix(“.jsp”);        return resolver;    }}

Giải thích một số thành phần : 

@Configuration : chú thích cấp lớp chỉ ra rằng một đối tượng là nguồn định nghĩa Bean 

@EnableWebMvc :cho phép cấu hình mặc định Spring MVC , chức năng tương đương mvc:annotation-driven/ trong XML 

@ComponentScan : quét các đầu annotation (ví dụ @Controller , @Service ..vv ) trong một gói được chỉ định bởi thuộc tính basePackages

InternalResourceViewResolver

  @Bean    public InternalResourceViewResolver resolver() {        InternalResourceViewResolver resolver = new InternalResourceViewResolver();        resolver.setViewClass(JstlView.class);        resolver.setPrefix(“/WEB-INF/views/”);        resolver.setSuffix(“.jsp”);        return resolver;    }

Với cấu tạo trên đây ta có thể đọc được file jsp .tạo link đến file này 

2.5 Servlet Container Initialization – MySpringMvcDispatcherServletInitializer.java

package net.javaguides.springmvc.helloworld.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
/** * @author Ramesh Fadatare */public class SpringMvcDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override    protected Class <?> [] getRootConfigClasses() {        // TODO Auto-generated method stub        return null;    }
    @Override    protected Class <?> [] getServletConfigClasses() {        return new Class[] {            AppConfig.class        };    }
    @Override    protected String[] getServletMappings() {        return new String[] {            “/”        };    }}

Cấu hình Spring MVC DispatcherServlet và thiết lập ánh xạ Url tới MVC 

DispatcherServlet

2.6 Model Class – HelloWorld.java

Khởi tạo model hiển thị trên một view 

package net.javaguides.springmvc.helloworld.model;
public class HelloWorld {    private String message;    private String dateTime;    public String getMessage() {        return message;    }    public void setMessage(String message) {        this.message = message;    }    public String getDateTime() {        return dateTime;    }    public void setDateTime(String dateTime) {        this.dateTime = dateTime;    }}

2.7 Controller Class – HelloWorldController.java

package net.javaguides.springmvc.helloworld.controller;
import java.time.LocalDateTime;
import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;
import net.javaguides.springmvc.helloworld.model.HelloWorld;
/** * @author Ramesh Fadatare */@Controllerpublic class HelloWorldController {
    @RequestMapping(“/helloworld”)    public String handler(Model model) {
        HelloWorld helloWorld = new HelloWorld();        helloWorld.setMessage(“Hello World Example Using Spring MVC 5!!!”);        helloWorld.setDateTime(LocalDateTime.now().toString());        model.addAttribute(“helloWorld”, helloWorld);        return “helloworld”;    }}

Tạo lớp HelloController  có annotation @ Controller

2.8 View – helloworld.jsp

<%@ page language=”java” contentType=”text/html; charset=ISO-8859-1″ pageEncoding=”ISO-8859-1″%><%@ taglib uri=”https://java.sun.com/jsp/jstl/core” prefix=”c”%><!DOCTYPE html><html><head><%@ page isELIgnored=”false” %><meta charset=”ISO-8859-1″><title>Spring 5 MVC – Hello World Example | javaguides.net</title></head>   <body>      <h2>${helloWorld.message}</h2>      <h4>Server date time is : ${helloWorld.dateTime}</h4>   </body></html>

Tạo file helloworld.jsp  trong  src/main/webapp/WEB-INF/views

2.9 Build + Deploy + Run an application

Build thành công,chúng ta sẽ chạy trên máy chủ Tomcat  

2.10 Demo: Ok Good Luck 

(Nguồn: Internet)

VI. Tổng kết

Vừa rồi là góc nhìn về mô hình MVC với một vài lưu ý:

  • Cách thức hoạt động của DispatcherServlet là mấu chốt vấn đề, DispatcherServlet xử lý các luồng hoạt động của MVC
  • Trong project ta sử dụng class : AppConfig.class cấu hình thay vì sử dụng file XML. AppConfig.class quản lý các Bean kết nối với file.jsp trong bài này tôi sử dụng , nếu bạn thích bạn có thể cấu hình với thymeleaf, File  Spring Mvc Dispatcher ServletInitializer.class đóng vai trò là DispatcherServlet sử dụng các Bean làm cầu nối.

Hẹn gặp lại các bạn vào bài viết tiếp theo.

Đoàn Văn Hiệu

#Spring_MVCHTMLJava WebSpring Framework
Read more
  • Published in Posts, Technology
No Comments

Recent Posts

  • FRONT END DEVELOPER (HTML/CSS)

    1. Mô Tả Công Việc Cắt giao diện website từ fil...
  • File upload trong Spring

    Trong quá trình xây dựng một ứng dụng web nói c...
  • (Fresher/Junior) NodeJS/Fullstack (NodeJS/ReactJS)

    1. Mô Tả Công Việc Tham gia các dự án outsourci...
  • Hệ cơ sở dữ liệu – MariaDB

        Trong bài viết tôi giới thiệ...
  • [Junior/Senior] Automation Tester

    1. Mô Tả Công Việc Xây dựng dụng cụ cho automat...

Recent Comments

  • hivequeen on [Tuyển Dụng] Junior/Fresher Frontend Developers (jQuery, Angular, VueJS, ReactJS) Full-time 2019
  • nguyễn viết đạt on [Tuyển Dụng] Junior/Fresher Frontend Developers (jQuery, Angular, VueJS, ReactJS) Full-time 2019

Archives

  • January 2021
  • December 2020
  • November 2020
  • October 2020
  • September 2020
  • August 2020
  • July 2020
  • June 2020
  • May 2020
  • April 2020
  • March 2020
  • February 2020
  • January 2020
  • December 2019
  • November 2019
  • September 2019
  • July 2019
  • June 2019

Categories

  • Networking
  • Posts
  • Recruitment
  • Sale
  • Technology
  • Uncategorized

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org

Featured Posts

  • FRONT END DEVELOPER (HTML/CSS)

    0 comments
  • File upload trong Spring

    0 comments
  • (Fresher/Junior) NodeJS/Fullstack (NodeJS/ReactJS)

    0 comments
  • Hệ cơ sở dữ liệu – MariaDB

    0 comments
  • [Junior/Senior] Automation Tester

    0 comments
  • DISCLAIMER
  • SUPPORT POLICY
  • LEGAL
HiveTech Vietnam (Technology Solutions - Original Ideas - Shared Expertise)

© HiveTech 2019 All rights reserved

TOP