`
zweichxu
  • 浏览: 135164 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

spring boot开发web api应用实践(二)操作数据库

阅读更多

在上一篇文章(spring boot开发web api应用实践(一)入门),简单介绍了如何利用spring boot搭建一个web应用,但是没有数据库操作层,本篇介绍如何引用数据库操作层。

 

 步骤:1.前置准备---创建数据库

            2.编辑pom.xml文件添加spring-boot-starter-jdbc依赖

            3.编辑application.properties文件配置数据源

            4.编写DAO接口代码

            5.编写Service接口代码

            6.修改Controller层LoginController

 

 

一、前置准备

      在mysql中新建test数据,并创建tbl_user表

CREATE TABLE `tbl_user` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `account` varchar(32) NOT NULL COMMENT '账户名 account name',
  `password` varchar(128) NOT NULL COMMENT '密码 password',
  `name` varchar(256) NOT NULL COMMENT '名字',
  `email` varchar(256) NOT NULL COMMENT 'email',
  `last_login_date` datetime DEFAULT NULL COMMENT '最近登录时间',
  `incorrect_login_attempt` int(10) NOT NULL DEFAULT '0' COMMENT '错误登录次数,登录成功后会重置为0',
  `is_locked_out` int(1) NOT NULL DEFAULT '0' COMMENT '用户是否锁定'
   PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

 

 

二、编辑pom.xml文件:

   在<dependencies>里面增加jdbc相关依赖:

 

    <!-- 开启数据库访问层:自动注入数据源、默认采用tomcat-jdbc连接池,默认使用spring-jdbc
         默认自动开启事务配置,在需要事务的类或方法上使用@Transactional 
    -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>

 

 

三、配置数据源:

    在工程的src\main\resources目录下面创建application.properties文件,这是spring boot的默认配置文件,可以做一些定制化的配置,如数据库配置:

 

spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.max-idle=20
spring.datasource.min-idle=5
spring.datasource.initial-size=5
spring.datasource.max-wait=10000
spring.datasource.validation-query=SELECT 1
spring.datasource.test-on-borrow=false
spring.datasource.test-while-idle=true
spring.datasource.time-between-eviction-runs-millis=18800
spring.datasource.jdbc-interceptors=ConnectionState;SlowQueryReport(threshold=3)

   

   上一篇入门中,结尾提到修改默认访问端口,即在application.properties文件配置server.port即可:

server.port=18081

    还可以配置tomcat相关配置项,如:

server.tomcat.minSpareThreads=5
server.tomcat.maxThreads=150
server.tomcat.uriEncoding=utf-8

 

 

    这些都是spring boot默认支持的配置项,更多配置项请自行参考spring boot的官方文档。

  

四、编写dao层

       JdbcBaseDAO.java

package com.zweichxu.springboot.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;

import com.google.common.collect.Lists;
import com.zweichxu.platform.entity.SqlParams;

public class JdbcBaseDAO{
    public static final int MAX_IN_SIZE = 1000;
    
    @Autowired
    protected JdbcTemplate jdbcTemplate;

    //移除集合中的重复值
    private <M> void removeDupData(List<M> inList){
        int size = inList.size();
        List<M> retList = new ArrayList<M>(size);
        inList.forEach(m -> {
            if(!retList.contains(m)){
                retList.add(m);
            }
        });

        inList.clear();
        inList.addAll(retList);
    }

    //将in集合分组
    protected <M> List<List<M>> divideArrayForSqlIn(List<M> inList){
        removeDupData(inList);
        return Lists.partition(inList, MAX_IN_SIZE);
    }

    protected <M> String whereIn(List<M> c, SqlParams params){
        int size = c.size();
        if(size <= 0){
            throw new RuntimeException("数据集合为空,无法拼装 where in 语句");
        }
        StringBuilder sb = new StringBuilder();
        c.forEach(m -> {
            sb.append("?,");
            params.addParam(m);
        });

        return sb.substring(0, sb.length() - 1);
    }

    protected String whereIn(Object[] c, SqlParams params){
        int size = c.length;
        if(size <= 0){
            throw new RuntimeException("数据集合为空,无法拼装 where in 语句");
        }
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < size; i++){
            sb.append("?,");
            params.addParam(c[i]);
        }

        return sb.substring(0, sb.length() - 1);
    }
    
    protected <M> String multiValue(List<M> c, SqlParams params){
        int size = c.size();
        if(size <= 0){
            throw new RuntimeException("数据集合为空,无法拼装 where in 语句");
        }

        StringBuilder sb = new StringBuilder();
        if (size > 1){
            sb.append(" in (").append(whereIn(c, params)).append(")");
        }else{
            sb.append("=?");
            params.addParam(c.get(0));
        }

        return sb.toString();
    }
}

 

 

        UserDAO.java

package com.zweichxu.springboot.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import com.zweichxu.springboot.model.User;

/**
 * @author zweichxu
 * @date 2017年3月30日 15:40:56
 * @version 1.0
 */
@Repository(UserDAO.ANNOTATION_NAME)
public class UserDAO extends JdbcBaseDAO {
    public final static String ANNOTATION_NAME = "userDAO";

    public User findUserByAccount(String acct){
        String sql = "select `id`, `account`, `password`, `name`, `email` from tbl_user where `account`=?";
        
        return jdbcTemplate.query(sql, new ResultSetExtractor<User>(){
            @Override
            public User extractData(ResultSet rs) throws SQLException, DataAccessException{
                if (rs.next()){ 
                    return parseUser(rs);
                }
                
                return null;
            }
        }, acct);
    }
    
    public User findUserById(int id){
        String sql = "select `id`, `account`, `password`, `name`, `email` from tbl_user where `id`=?";
        
        return jdbcTemplate.query(sql, new ResultSetExtractor<User>(){
            @Override
            public User extractData(ResultSet rs) throws SQLException, DataAccessException{
                if (rs.next()){ 
                    return parseUser(rs);
                }
                
                return null;
            }
        }, id);
    }
     
    public void updateUserLoginInfo(int id, int isLockedOut, int incorrectLoginAttempt){
        String sql = "update tbl_user set is_locked_out =?, incorrect_login_attempt =?," 
                   + " last_login_date =now() where `id`=?";
        
        jdbcTemplate.update(sql, isLockedOut, incorrectLoginAttempt, id);
    }
    private User parseUser(ResultSet rs) throws SQLException{
        User user = new User();
        user.setId(rs.getInt("id"));
        user.setAccount(rs.getString("account"));
        user.setPassword(rs.getString("password"));
        user.setName(rs.getString("name"));
        user.setEmail(rs.getString("email")); 
        user.setIsLockedOut(covert(rs.getInt("is_locked_out")));
        user.setIncorrectLoginAttempt(rs.getInt("incorrect_login_attempt"));
        user.setLastLoginDate(rs.getTimestamp("last_login_date"));
        return user;
    } 

    private boolean covert(Integer value){
        return value==null?false:(value==1?true:false);
    }
}

 

五、编写Service层代码

 

    UserService.java

package com.zweichxu.springboot.service;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;
import org.springframework.stereotype.Service;

import com.zweichxu.platform.entity.BaseResp;
import com.zweichxu.platform.entity.ServiceException;
import com.zweichxu.springboot.dao.UserDAO;
import com.zweichxu.springboot.model.User;

@Service(UserService.ANNOTATION_NAME)
public class UserService {
    public final static String ANNOTATION_NAME = "userService";
    
    @Resource(name=UserDAO.ANNOTATION_NAME)
    private UserDAO userDao;
    
    public User doLogin(String acct, String pwd){
        User user = userDao.findUserByAccount(acct);
        
        if (user == null || !pwd.equals(user.getPassword())){
            int maxErr = 5;
            int errCnt = 0;
            if (user != null){
                errCnt = user.getIncorrectLoginAttempt() + 1;
                userDao.updateUserLoginInfo(user.getId(), errCnt>=maxErr?1:0, errCnt);
            }
            
            throw new ServiceException(BaseResp.DATA_NOT_EXIST, errCnt>=maxErr?"用户名或密码错误,您已尝试多次,帐号已被锁定":"用户名或密码错误");
        }
        
        if (user.getIsLockedOut()){
            throw new ServiceException(BaseResp.DATA_NOT_EXIST, "您的帐号已被锁定,请联系管理员");
        }
        
        userDao.updateUserLoginInfo(user.getId(), 0, 0);
        
        return user;
    }
}

 

六、修改LoginController(参见spring boot开发web api应用实践(一)入门

   @Resource(name=UserService.ANNOTATION_NAME)
   private UserService userService;   //注入Service类
    
    @RequestMapping(value="login")
    public BaseResp doLogin(@RequestParam("acct") String userName, @RequestParam("pwd") String password){
        if (Util.isEmpty(userName) || Util.isEmpty(password)){
            return BaseResp.fail(BaseResp.RET_CODE_PROTOCOL_ERROR, "用户名及密码均不能为空");
        }
       
        //do something
        try{
            User user = userService.doLogin(userName, password); 
            return BaseResp.success().setRetMsg("登录成功").addProperty("loginUser", user);
        }catch(ServiceException e){
            return BaseResp.fail(e.getRetCode(), e.getMessage());
        } 
    }

 

   要想引入数据库操作,关键在于添加spring-boot-starter-jdbc依赖,然后spring boot会根据配置的数据库信息及连接池参数,自动装配tomcat-jdbc连接池,并自动初始化数据源及JdbcTemplate;

 然后在浏览器地址栏访问:http://localhost:8080/login?acct=zweichxu&pwd=123,可以看到浏览器页面返回值

 

下一篇介绍如何将tomcat-jdbc连接池换成proxool连接池(个人喜欢proxool连接池 ^_^)

分享到:
评论

相关推荐

    《Spring Boot企业级开发教程》配套资料

    《Spring Boot企业级开发教程》配套资料是一份全面学习Spring Boot技术栈的宝贵资源,它涵盖了从基础到进阶的企业级应用开发知识。这个压缩包包含的教学材料多样,旨在帮助学习者深入理解并掌握Spring Boot的核心...

    spring-boot中文API文档

    Spring Boot是Java开发中的一个流行框架,它简化了创建独立的、生产级别的基于Spring的应用程序。这个"spring-boot-中文参考手册.pdf"是为开发者提供的一份详细且全面的中文API文档,旨在帮助中文使用者更好地理解和...

    《Spring Boot企业级开发教程》配套资源.zip

    总的来说,这个压缩包资源为Spring Boot的学习者提供了一个全方位的学习平台,从理论到实践,从基础知识到高级应用,覆盖了企业级开发中可能遇到的各种场景。无论你是初学者还是经验丰富的开发者,都能从中受益匪浅...

    Spring Boot 教程、技术栈示例代码,快速简单上手教程。

    Spring Boot 是一个由 Pivotal 团队开发的框架,旨在简化 Spring 应用程序的初始搭建以及开发过程。它集成了大量常用的第三方库配置,如 JDBC、MongoDB、RabbitMQ、Quartz 等,使得开发者可以“零配置”地启动项目,...

    《Vue Spring Boot前后端分离开发实战》源码Vue+Spring Boot前后端分离开发实战教学课件(PPT)

    在现代Web应用开发中,Vue.js和Spring Boot的结合已经成为了一种常见的前后端分离架构模式。这本《Vue Spring Boot前后端分离开发实战》的源码提供了深入学习和实践这一技术栈的机会。以下是对其中涉及知识点的详细...

    spring boot api chm

    7. **Web开发**:Spring Boot支持使用Spring MVC或Thymeleaf等模板引擎进行Web开发,提供了RESTful API开发的强大支持。 8. **数据访问**:Spring Boot简化了与各种数据库的交互,包括JPA、Hibernate和MyBatis等,...

    Spring Boot-RESTfull API入门.rar

    Spring Boot 是一个由 Pivotal 团队开发的框架,旨在简化 Spring 应用程序的初始设置和开发过程。它集成了大量常用的第三方库配置,如 JDBC、MongoDB、JPA、RabbitMQ、Quartz 等,使得开发者能够快速地创建生产级别...

    Spring Boot开发实战:基于Spring Boot的RESTful API服务的实验心得与案例解析

    ### Spring Boot开发实战:基于Spring Boot的RESTful API服务的实验心得与案例解析 #### 一、引言 Spring Boot自发布以来,以其强大的自动配置能力、简洁的开发模式以及丰富的社区支持,迅速成为了Java开发者构建...

    基于Vue3 + Spring Boot开发的云共享资源应用系统.zip

    综上所述,基于Vue3和Spring Boot开发的云共享资源应用系统利用了现代Web开发的最佳实践,实现了前端与后端的高效协作,同时兼顾了性能、可扩展性和安全性。这样的系统设计为企业级的资源共享和协作提供了可靠的技术...

    Netty+Spring Boot仿微信 全栈开发高性能后台及客户端

    在这个项目中,前端可能包括Web界面和移动端应用,而后端则涉及到服务器逻辑和数据库操作。通过使用Netty和Spring Boot,我们可以构建出高效的服务器端,同时利用它们提供的API与前端进行交互。 4. 微信功能实现: ...

    Spring Boot2企业应用实战

    《Spring Boot2企业应用实战》一书主要涵盖了Spring Boot 2在现代企业级应用程序开发中的核心概念和技术。Spring Boot作为Spring框架的一个子项目,旨在简化Java应用的初始搭建以及开发过程,尤其对于微服务架构来说...

    Spring Boot 快速入门与应用开发指南

    内容概要:本文档全面介绍了 Spring Boot 的入门方法及其应用场景,包括环境准备、...阅读建议:阅读时可以跟随文档的步骤实际动手练习,同时参照提供的官方文档和书籍深入学习,逐步提升 Spring Boot 的应用开发能力。

    Spring Boot应用开发框架 v3.0.12.zip

    Spring Boot是Java领域的一款热门应用开发框架,它简化了基于Spring的应用程序开发流程,通过预配置的设置使得开发者能够快速构建可运行的应用程序。在"Spring Boot应用开发框架 v3.0.12.zip"中,包含了一份详细的...

    Spring Boot 2 Cookbook 第二版

    总的来说,《Spring Boot 2 Cookbook 第二版》是一本全面而实用的参考书,无论你是初学者还是有经验的开发者,都能从中获益,提升你的Spring Boot应用开发技能。书中的例子和实践指导将帮助你更好地理解和应用Spring...

    spring boot资料以及项目

    Spring Boot是Java开发领域中的一款热门框架,它简化了基于Spring的应用程序的初始设置和配置。这个压缩包包含了丰富的Spring Boot学习资料以及实际项目案例,是深入理解和掌握Spring Boot技术的宝贵资源。 首先,...

    Spring Boot-实战

    《Spring Boot-实战》这本书是针对Java开发人员的一份实用指南,主要聚焦于Spring Boot框架的应用与实践。Spring Boot是Spring生态系统中的一个关键组件,它旨在简化Spring应用程序的初始搭建以及开发过程,使得...

    spring-boot实战PDF 完整版和随书源码.7z

    《Spring Boot实战》是一本深度剖析Spring Boot框架的实践指南,...通过阅读这本书和实践源码,开发者不仅能了解Spring Boot的基本用法,还能掌握其高级特性和最佳实践,从而提升开发效率,打造高质量的微服务应用。

    Spring+Boot实战

    其次,Spring Boot集成了许多流行的技术,如Spring MVC、Thymeleaf、MyBatis等,使得开发RESTful API、模板引擎驱动的Web页面以及数据库操作变得简单易行。这部分内容会涵盖如何使用Spring Data JPA进行数据库操作,...

    spring-boot-web-restfulcrud代码示例

    这涵盖了从项目的初始化、Controller 的编写、服务层的设计到与数据库的交互等多个方面,是学习和实践 Spring Boot Web 开发的一个很好的起点。通过这个项目,你可以深入理解 Spring Boot 的自动化配置、RESTful API...

    Spring Boot + Vue3 完整开发全栈项目附资料.zip

    在现代Web开发领域,Spring Boot和Vue3已经成为构建高效、可扩展应用的热门选择。本项目实战将深入讲解如何结合这两个强大的技术栈,实现一个全栈应用。下面,我们将详细探讨Spring Boot后端框架与Vue3前端框架的...

Global site tag (gtag.js) - Google Analytics