搞点事情 01-项目初始化

项目初始化

一、背景

学一点新东西

二、技术选型

SpringBoot + MybatisPlus+mysql +Vue
说明:为了简单点
后端:SpringBoot + MybatisPlus
前端:开源的模板 vue-admin-template

三、项目构建

1、后端

1.1 新建项目

初始化后的最终目录如下
在这里插入图片描述

1.2 配置pom.xml

需要启动项+mysql+mvc+lombak

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
<!--		<version>2.5.3-SNAPSHOT</version>-->
		<version>2.5.0</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.leiyuee</groupId>
	<artifactId>manage</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>manage</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<!--MVC 支持-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
<!--lombok-->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
<!--数据库支持-->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
<!--数据库连接-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>
<!--对mybatisplus的自动化配置-->
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>3.4.2</version>
		</dependency>
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-generator</artifactId>
			<version>3.5.0</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>


1.3 配置 yml 文件
###################  项目启动端口  ###################
server:
  port: 8888
  max-http-header-size: 10000000

################### 通用mapper设置  ###################
mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true
    auto-mapping-behavior: full
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath*:mapper/**/*Mapper.xml
  global-config:
    # 逻辑删除配置
    db-config:
      # 删除前
      logic-not-delete-value: 1
      # 删除后
      logic-delete-value: 0

###################  spring配置  ###################
spring:
  main:
    allow-bean-definition-overriding: true
  datasource:
    url: jdbc:mysql://localhost:3306/manage?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

1.4 配置启动项
@SpringBootApplication
@MapperScan("com.leiyuee.manage.web.mapper")
public class ManageApplication {
	public static void main(String[] args) {
		SpringApplication.run(ManageApplication.class, args);
	}
}
1.5 编写测试
@RestController
public class LoginController {
    @GetMapping("login/test")
    public String LoginTest(){
        return "登录";
    }
}
1.6 启动

在这里插入图片描述
在这里插入图片描述

2、 前端

#克隆项目
git clone https://github.com/PanJiaChen/vue-admin-template.git

#进入项目目录
cd vue-admin-template

#安装依赖
npm install

#开发
npm run dev

# 自动打开
http://localhost:9528

在这里插入图片描述

四、统一配置

1、统一结果返回

目前的前后端开发大部分数据的传输格式都是json,因此定义一个统一规范的数据格式有利于前后端的交互与UI的展示

1.1 状态码
/**
 * 返回状态码
 */
public interface HttpStatus{
    /**
     * 操作成功
     */
    public static final int SUCCESS = 200;
    /**
     * 对象创建成功
     */
    public static final int CREATED = 201;
    /**
     * 请求已经被接受
     */
    public static final int ACCEPTED = 202;
    /**
     * 操作已经执行成功,但是没有返回数据
     */
    public static final int NO_CONTENT = 204;
    /**
     * 资源已被移除
     */
    public static final int MOVED_PERM = 301;
    /**
     * 重定向
     */
    public static final int SEE_OTHER = 303;
    /**
     * 资源没有被修改
     */
    public static final int NOT_MODIFIED = 304;
    /**
     * 参数列表错误(缺少,格式不匹配)
     */
    public static final int BAD_REQUEST = 400;
    /**
     * 未授权
     */
    public static final int UNAUTHORIZED = 401;
    /**
     * 访问受限,授权过期
     */
    public static final int FORBIDDEN = 403;
    /**
     * 资源,服务未找到
     */
    public static final int NOT_FOUND = 404;
    /**
     * 不允许的http方法
     */
    public static final int BAD_METHOD = 405;
    /**
     * 资源冲突,或者资源被锁
     */
    public static final int CONFLICT = 409;
    /**
     * 不支持的数据,媒体类型
     */
    public static final int UNSUPPORTED_TYPE = 415;
    /**
     * 系统内部错误
     */
    public static final int ERROR = 500;
    /**
     * 接口未实现
     */
    public static final int NOT_IMPLEMENTED = 501;
}

1.2 结果集
/**
 * 返回数据
 *
 */
public class R extends HashMap<String, Object> {
	private static final long serialVersionUID = 1L;
	public R() {
		put("code", 0);
		put("msg", "success");
	}
	public static R error() {
		return error(HttpStatus.ERROR, "未知异常,请联系管理员");
	}
	public static R error(String msg) {
		return error(HttpStatus.ERROR, msg);
	}
	public static R error(int code, String msg) {
		R r = new R();
		r.put("code", code);
		r.put("msg", msg);
		return r;
	}
	public static R ok(String msg) {
		R r = new R();
		r.put("msg", msg);
		return r;
	}
	public static R ok(Map<String, Object> map) {
		R r = new R();
		r.putAll(map);
		return r;
	}
	public static R ok() {
		return new R();
	}
	public R put(String key, Object value) {
		super.put(key, value);
		return this;
	}
	public  Integer getCode() {
		return (Integer) this.get("code");
	}
	public static R error(int code, Object msg,Object data) {
		R r = new R();
		r.put("code", code);
		r.put("msg", msg);
		r.put("data",data);

		return r;
	}

	public static R ok(int code, Object msg,Object data) {
		R r = new R();
		r.put("code", code);
		r.put("msg", msg);
		r.put("data",data);
		return r;
	}
}

1.3 控制层返回
    @RequestMapping("/getAll")
    public R getAll(){
        sysUserService.list();
        return R.ok().put("userList", sysUserService.list());
    }

    @RequestMapping("/getOne")
    public R getOne(){
        SysUser sysUser = sysUserService.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getPassword,"123456"));
        return R.ok().put("sysUser", sysUser);
    }

2、统一异常处理

使用统一返回结果时,还有一种情况,就是程序的保存是由于运行时异常导致的结果,有些异常我们可以无法提前预知,不能正常走到我们return的R对象返回。

2.1 自定义异常
/**
 * 自定义异常
 */
public class MyException extends RuntimeException {
    private static final long serialVersionUID = 1L;
    private String msg;
    private int code = 500;
    public MyException(String msg) {
        super(msg);
        this.msg = msg;
    }
    public MyException(String msg, Throwable e) {
        super(msg, e);
        this.msg = msg;
    }
    public MyException(String msg, int code) {
        super(msg);
        this.msg = msg;
        this.code = code;
    }
    public MyException(String msg, int code, Throwable e) {
        super(msg, e);
        this.msg = msg;
        this.code = code;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
}
2.2 异常处理
/*
异常处理器
 */
@RestControllerAdvice
public class MyExceptionhandler {
    private Logger logger = LoggerFactory.getLogger(getClass());
    /**
     * 处理自定义异常
     */
    @ExceptionHandler(MyException.class)
    public R handleRRException(MyException e){
        R r = new R();
        r.put("code", e.getCode());
        r.put("msg", e.getMessage());

        return r;
    }
    @ExceptionHandler(NoHandlerFoundException.class)
    public R handlerNoFoundException(Exception e) {
        logger.error(e.getMessage(), e);
        return R.error(404, "路径不存在,请检查路径是否正确");
    }
    @ExceptionHandler(DuplicateKeyException.class)
    public R handleDuplicateKeyException(DuplicateKeyException e){
        logger.error(e.getMessage(), e);
        return R.error("数据库中已存在该记录");
    }
/*    @ExceptionHandler(AuthorizationException.class)
    public R handleAuthorizationException(AuthorizationException e){
        logger.error(e.getMessage(), e);
        return R.error("没有权限,请联系管理员授权");
    }*/
    @ExceptionHandler(Exception.class)
    public R handleException(Exception e){
        logger.error(e.getMessage(), e);
        return R.error();
    }
}

3、统一日志

日志是追踪错误定位问题的关键,尤其在生产环境中,需要及时修复热部署,不会提供开发者debug的环境,此时日志将会是最快解决问题的关键

3.1 yml添加
logging:
  file:
    path: src\main\resources\logger\ # logger文件夹需要提前生成

五、跨域处理

因为浏览器的同源策略会阻止一个域的js脚本和另外一个域的内容进行交互,两个页面需要有相同的协议,主机,和端口,三者之间任何一个不同即为跨域
常用CROS跨域资源分享来解决
1、普通跨域请求:只需服务器端设置Access-Control-Allow-Origin
2、带cookie跨域请求:前后端都需要进行设置

1、后端

1.1 跨域设置
/**
 * 设置跨域:这里有5种跨域方法
 */
//实现 WebMvcConfigurer
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addCorsMappings(CorsRegistry registry){
        registry.addMapping("/**") //拦截所有请求
                //放入哪些原始域
               // .allowedOrigins("*")//注意:springboot 升级后这里要改成下面这个
                .allowedOriginPatterns("*")
                //是否发送Cookie信息
                .allowCredentials(true)
                .allowedMethods("GET","POST","PUT","DELETE")
                .allowedHeaders("*");
                //暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
                //.exposedHeaders(HttpHeaders.SET_COOKIE)
    }
}

/*
继承 HandlerInterceptorAdapter
 @Component
public class CrossInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        return true;
    }
}
* */
/*
使用Filter过滤器来过滤服务请求,向请求端设置Response Header(响应头部)的Access-Control-Allow-Origin属性声明允许跨域访问。
@WebFilter
public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "*");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        chain.doFilter(req, res);
    }
}*/
/*
* 使用@CrossOrgin 注解
如果只是想部分接口跨域,且不想使用配置来管理的话,可以使用这种方式
在controller  或者在方法前
* */
/*Spring Cloud Gateway 跨域配置
spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            # 允许跨域的源(网站域名/ip),设置*为全部
            # 允许跨域请求里的head字段,设置*为全部
            # 允许跨域的method, 默认为GET和OPTIONS,设置*为全部
            allow-credentials: true
            allowed-origins:
              - "http://xb.abc.com"
              - "http://sf.xx.com"
            allowed-headers: "*"
            allowed-methods:
              - OPTIONS
              - GET
              - POST
              - DELETE
              - PUT
              - PATCH
            max-age: 3600
* */
1.2 登录

项目初始化暂时没有涉及到数据库

@RestController
public class LoginController {
   // @CrossOrigin
    @PostMapping("vue-admin-template/user/login")
    @ResponseBody
    public R Login(SysUser user){
        HashMap<String ,Object> responseData = new HashMap<>();
        responseData.put("token",1);
        return R.ok(20000,"登录成功",responseData);
    }

  //  @CrossOrigin
    @GetMapping("vue-admin-template/user/info")
    @ResponseBody
    public R info(SysUser user){
        HashMap<String ,Object> responseData = new HashMap<>();
        responseData.put("roles","admin");
        responseData.put("name","Super admin");
        responseData.put("avator","https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
        return R.ok(20000,"登录成功",responseData);
    }
}

2、前端

2.1 修改vue.config.js
  publicPath: '/',
  outputDir: 'dist',
  assetsDir: 'static',
  lintOnSave: process.env.NODE_ENV === 'development',
  productionSourceMap: false,
  devServer: {
    port: port,
    open: true,
    overlay: {
      warnings: false,
      errors: true
    },
   // before: require('./mock/mock-server.js')
2.2 修改 env.development
# just a flag
ENV = 'development'

# base api
# VUE_APP_BASE_API = '/dev-api'
VUE_APP_BASE_API= 'http://localhost:8888'
port=8880
2.3 修改main.js
// if (process.env.NODE_ENV === 'production') {
//   const { mockXHR } = require('../mock')
//   mockXHR()
// }

3、项目启动后

前端:控制台输入npm run dev
后端:启动项在这里插入图片描述
页面显示
在这里插入图片描述
直接登录,数据是后台接口提供的,初始化完成

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值