springboot搭建web应用

一、学习情景:

作为Java程序员,现在领导要求你负责新闻信息系统后端中用户模块,要求你实现该模块的用户注册和登录功能。
要求技术栈:idea、springboot、maven、mybatis、swagger、lombok

二、前置环境:

  • 浏览器:chrome(建议)
  • Java:Jdk1.8
  • 项目管理工具:Maven
  • IDE: IntelliJ Idea
  • 数据库: Mysql(教师统一在服务器端配置好)

三、创建项目

  1. 打开idea


    image.png
  2. 新建项目


    image.png

    设置项目的基本信息,其中注意jdk版本要与Java版本匹配,这里使用jdk1.8和java8


    image.png

    下一步选择springboot版本和项目依赖
    image.png

    选择新窗口编辑器


    image.png
  3. 目录结构(初始)


    image.png

四、Mysql数据库

数据库下载安装和配置

参见:windows下安装mysql - (jianshu.com)

脚本建库、建表导入

脚本:

-- 零、删库:
-- DROP DATABASE IF EXISTS `db_news`;

-- 一、建库
CREATE DATABASE IF NOT EXISTS `db_news` CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_general_ci';

-- 二、建表、索引等
-- -------------------------------------------------------------------------------------------------------
use db_news;

DROP TABLE IF EXISTS `dt_user`;

-- 用户表:
CREATE TABLE IF NOT EXISTS `dt_user`(
    `id` INT AUTO_INCREMENT PRIMARY KEY COMMENT '用户编号',
    `username` VARCHAR(32) NOT NULL UNIQUE COMMENT '用户名',
    `password` VARCHAR(32) NOT NULL COMMENT '密码',
    `mobile` CHAR(11) NOT NULL COMMENT '手机号',
    `age` TINYINT UNSIGNED NOT NULL DEFAULT 18 COMMENT '年龄'
) ENGINE=InnoDB COMMENT = '用户表' DEFAULT CHARSET=utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

使用ideaDatabase插件连接Mysql数据库

image.png

image.png

image.png

至此可以看到用户表:dt_user

五、项目架构

image.png

六、根据架构调整项目目录

pom.xml配置

pom.xml



    4.0.0

    
        org.springframework.boot
        spring-boot-starter-parent
        2.7.5
         
    

    com.sunning
    news
    0.0.1-SNAPSHOT
    news
    news

    
        1.8
    

    
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
        
        
            mysql
            mysql-connector-java
            runtime
        

        
        
            com.alibaba
            druid
            1.1.19
        

        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            2.1.0
        

        
        
            org.projectlombok
            lombok
            true
        

        
        
            io.springfox
            springfox-swagger2
            2.9.2
        
        
            io.springfox
            springfox-swagger-ui
            2.9.2
        


    

    
        
        AppNews
        
            
                org.springframework.boot
                
                spring-boot-maven-plugin
                
                2.7.5
            
        
    




application.yml配置

application.yml

server:
  host: localhost
  port: 8081

spring:
  application:
    name: news
  # 数据源配置
  datasource:
    url: jdbc:mysql://${server.host}:3306/mysql?useUnicode=true&characterEncoding=utf8&autoReconnect=true&failOverReadOnly=false&rewriteBatchedStatements=TRUE
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: '123456'
    type: com.alibaba.druid.pool.DruidDataSource
    # 数据源其他配置
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    poolPreparedStatements: true
    #   配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
    filters: stat,wall,logback
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
  # 路径匹配策略
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher

# 日志配置
logging:
  level:
    com:
      dxy:
        odr:
          referee:
            dao:
              mapper: debug

mybatis:
  configuration:
    # 字段下划线转驼峰
    map-underscore-to-camel-case: true
    # 打印sql+查询结果
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

开发目录结构

image.png

七、用户注册、登录功能实现

dao层之user实体类定义

User.java

package com.sunning.news.dao.pojo;

import lombok.*;

/**
 * 用户实体类
 *
 * @author ckk
 * @create 2022-11-02 14:47
 **/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class User {
    private Integer id;
    private String username;
    private String password;
    private String mobile;
    private Integer age;

}

dao层之mapper数据访问层

UserMapper.java

package com.sunning.news.dao.mapper;

import com.sunning.news.dao.pojo.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;

/**
 * 用户管理mapper
 * 
 * @author ckk
 * @create 2022-11-02 14:48
 **/
@Repository
public interface UserMapper {

    /**
     * 新增用户记录,返回自增主键
     * username 不重复才新增
     * @param user
     * @return
     */
    @Insert(" insert into db_news.`dt_user`(username, password, mobile, age)" +
            " select #{username}, #{password}, #{mobile}, #{age}" +
            " where not exists(select username from db_news.`dt_user` where username = #{username})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int register(User user);

    /**
     * 用户登录,获取用户信息
     * @param username
     * @param password
     * @return
     */
    @Select(" select *" +
            " from db_news.`dt_user`" +
            " where username = #{username} and password = #{password}")
    User login(@Param("username") String username, @Param("password") String password);

    /**
     * 根据username获取用户信息
     * @param username
     * @return
     */
    @Select(" select *" +
            " from db_news.`dt_user`" +
            " where username = #{username}")
    User findByUsername(@Param("username") String username);

    /**
     * 根据id获取用户信息
     * @param id
     * @return
     */
    @Select(" select *" +
            " from db_news.`dt_user`" +
            " where id = #{id}")
    User findByUid(@Param("id") Integer id);

}

service层之接口定义

UserService.java

package com.sunning.news.service;

import com.sunning.news.dao.pojo.User;

/**
 * 用户业务逻辑层接口
 *
 * @author ckk
 * @create 2022-11-02 14:48
 **/
public interface UserService {

    /**
     * 注册业务逻辑
     * @param user 要注册的User对象,属性中主键id要为空
     * @return
     */
    User registerService(User user);

    /**
     * 登录业务逻辑
     * @param uname 账户名
     * @param password 密码
     * @return
     */
    User loginService(String uname, String password);

}

service层之实现类

UserServiceImpl.java

package com.sunning.news.service.impl;

import com.sunning.news.dao.mapper.UserMapper;
import com.sunning.news.dao.pojo.User;
import com.sunning.news.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * 用户业务逻辑层实现类
 *
 * @author ckk
 * @create 2022-11-02 14:49
 **/
@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Override
    public User registerService(User user) {
        // 结果
        User userDTO = null;

        // 当新用户的用户名已存在时
        if(userMapper.findByUsername(user.getUsername()) != null){
            return null;
        }

        // 入库
        int id = userMapper.register(user);
        if(id > 0){
            // 查询
            userDTO = userMapper.findByUid(id);
        }

        // 抹掉密码等重要信息
        if(userDTO != null){
            userDTO.setPassword("");
        }

        // 返回结果
        return userDTO;
    }

    @Override
    public User loginService(String uname, String password) {
        // 登录
        User user = userMapper.login(uname, password);

        // 抹掉密码等重要信息
        if(user != null){
            user.setPassword("");
        }

        return user;
    }

}

controller控制层

UserController.java

package com.sunning.news.controller;

import com.sunning.news.dao.pojo.User;
import com.sunning.news.service.UserService;
import com.sunning.news.utils.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/**
 * 用户控制层
 *
 * @author ckk
 * @create 2022-11-02 14:42
 **/
@Api(tags = "用户模块")
@RestController
@RequestMapping("/user")
public class UserController {
    @Resource
    private UserService userService;

    @ApiOperation("用户注册")
    @PostMapping("/register")
    public Result registController(@RequestBody User userAO){
        User user = userService.registerService(userAO);
        if(user!=null){
            return Result.success(user,"用户注册成功!");
        }else{
            return Result.error("-1","用户名已存在!");
        }
    }

    @ApiOperation("用户登录")
    @PostMapping("/login")
    public Result loginController(@RequestParam String uname, @RequestParam String password){
        User user = userService.loginService(uname, password);
        if(user!=null){
            return Result.success(user,"用户登录成功!");
        }else{
            return Result.error("-2","账号或密码错误!");
        }
    }


}

其他

除了以上包之外,还有config包、utils包,这两者一个是配置类包,另一个是工具类包。

工具类

Result.java

package com.sunning.news.utils;

/**
 * 响应结果类
 *
 * @author ckk
 * @create 2022-11-02 14:51
 **/
public class Result {
    private String code;
    private String msg;
    private T data;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public Result() {
    }

    public Result(T data) {
        this.data = data;
    }

    public static Result success() {
        Result result = new Result<>();
        result.setCode("0");
        result.setMsg("成功");
        return result;
    }

    public static  Result success(T data) {
        Result result = new Result<>(data);
        result.setCode("0");
        result.setMsg("成功");
        return result;
    }

    public static  Result success(T data,String msg) {
        Result result = new Result<>(data);
        result.setCode("0");
        result.setMsg(msg);
        return result;
    }

    public static Result error(String code, String msg) {
        Result result = new Result();
        result.setCode(code);
        result.setMsg(msg);
        return result;
    }
}

配置类

swagger配置

SwaggerConfig.java

package com.sunning.news.config;

import com.google.common.base.Predicates;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * Swagger2配置类
 *
 * @author ckk
 * @create 2022-11-02 16:01
 **/
@Configuration
@EnableSwagger2
public class SwaggerConfig extends WebMvcConfigurationSupport {

    @Bean
    public Docket newsApiConfig(){
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("newsApi")
                // 调用apiInfo方法,创建一个ApiInfo实例,
                // 里面是展示在文档页面信息内容
                .apiInfo(newsApiInfo())
                .select()
                .paths(Predicates.not(PathSelectors.regex("/admin/.*")))
                .paths(Predicates.not(PathSelectors.regex("/error.*")))
                .build();

    }


    // api文档的详细信息
    private ApiInfo newsApiInfo(){

        return new ApiInfoBuilder()
                .title("新闻系统API文档接口测试")    //标题
                .description("本文档描述接口测试用例")  //描述
                .version("1.0")  //版本
                .build();
    }

    /**
     * 解决swagger-ui.html 404无法访问的问题
     */
    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 解决静态资源无法访问
        registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/static/");
        // 解决swagger无法访问
        registry.addResourceHandler("/swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        // 解决swagger的js文件无法访问
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}

跨域配置

GlobalCorsConfig.java

package com.sunning.news.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 全局跨域配置
 *
 * @author ckk
 * @create 2022-11-02 15:52
 **/
@Configuration
public class GlobalCorsConfig {
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")    //添加映射路径,“/**”表示对所有的路径实行全局跨域访问权限的设置
                        .allowedOriginPatterns("*")    //开放哪些ip、端口、域名的访问权限,不用allowedOrigins是为了适配swagger2
                        .allowCredentials(true)  //是否允许发送Cookie信息
                        .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")     //开放哪些Http方法,允许跨域访问
                        .allowedHeaders("*")     //允许HTTP请求中的携带哪些Header信息
                        .exposedHeaders("*");   //暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
            }
        };
    }
}

启动类配置

NewsApplication.java是启动类,在这里需要配置mybatis的包扫描路径,使用@MapperScan({"com.sunning.news.dao.mapper"})注解即可,如图:

image.png

八、debug运行,swagger测试

在NewsApplication.java启动类上右键点击Debug模式运行项目,如图:


image.png

看到此日志,启动成功,如图:


image.png

swagger-ui页面进行测试,访问:http://localhost:8081/swagger-ui.html

image.png

image.png

image.png

九、打成jar包运行,swagger测试

maven打包:在idea右侧边的Maven栏目中,找到news-Lifecycle-install功能,双击运行,如图:


image.png

在项目的target路径下找到maven打好的jar包:AppNews.jar文件,如图:


image.png

在该目录下启动cmd,执行命令:java -jar AppNews.jar,启动此web服务,如图:

image.png

使用swagger进行测试,同第八步骤中所示。

你可能感兴趣的:(springboot搭建web应用)