这篇文章是无关业务逻辑代码的基础配置

目录

一、相关配置

1. 数据库相关配置

2.日志系统相关配置

二、开发框架搭建

1.设置返回接口标准类

2.自定义异常枚举类

3. 自定义异常处理类

4. 全局异常处理类

三、全局校验

1. 全局常量参数

2. 用户身份校验

3. 管理员权限校验

四、全局校验配置

1. 用户校验配置

2. 管理员校验配置

3. 文件存储实际位置与虚拟位置转化

总结


前言

最近学习java项目开发,对springboot项目进行总结,该文章是对于非业务代码的总结

一、相关配置

1. 数据库相关配置

根据Mybatis-generator插件生成对应的实体类与Mapper

pom.xml配置

        <plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.3.7</version><configuration><verbose>true</verbose><overwrite>true</overwrite></configuration></plugin>

首先得有配置文件generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfigurationPUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration><!-- 配置文件,放在resource目录下即可 --><!--数据库驱动个人配置,此处遵循mvn的下载地址--><classPathEntry location="maven-repo\mysql\mysql-connector-java\8.0.18\mysql-connector-java-8.0.18.jar"/><context id="MysqlTables" targetRuntime="MyBatis3"><property name="autoDelimitKeywords" value="true"/><!--可以使用``包括字段名,避免字段名与sql保留字冲突报错--><property name="beginningDelimiter" value="`"/><property name="endingDelimiter" value="`"/><!-- optional,旨在创建class时,对注释进行控制 --><commentGenerator><property name="suppressDate" value="true"/><property name="suppressAllComments" value="true"/></commentGenerator<!--数据库链接地址账号密码--><jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"connectionURL="jdbc:mysql://127.0.0.1:3306/imooc_mall?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=Asia/Shanghai&amp;zeroDateTimeBehavior=convertToNull"userId="root" password="123456"><property name="nullCatalogMeansCurrent" value="true"/></jdbcConnection><!-- 非必需,类型处理器,在数据库类型和java类型之间的转换控制--><javaTypeResolver><property name="forceBigDecimals" value="false"/></javaTypeResolver><!--生成Model类存放位置--><javaModelGenerator targetPackage="com.imooc.mall.model.pojo"targetProject="src/main/java"><!-- 是否允许子包,即targetPackage.schemaName.tableName --><property name="enableSubPackages" value="true"/><!-- 是否对类CHAR类型的列的数据进行trim操作 --><property name="trimStrings" value="true"/><!-- 建立的Model对象是否 不可改变  即生成的Model对象不会有 setter方法,只有构造方法 --><property name="immutable" value="false"/></javaModelGenerator><!--生成mapper映射文件存放位置--><sqlMapGenerator targetPackage="mappers" targetProject="src/main/resources"><property name="enableSubPackages" value="true"/></sqlMapGenerator><!--生成Dao类存放位置--><javaClientGenerator type="XMLMAPPER" targetPackage="com.imooc.mall.model.dao"targetProject="src/main/java"><property name="enableSubPackages" value="true"/></javaClientGenerator><!--生成对应表及类名--><table schema="root" tableName="imooc_mall_cart" domainObjectName="Cart"enableCountByExample="false"enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"selectByExampleQueryId="false"></table><table tableName="imooc_mall_category" domainObjectName="Category" enableCountByExample="false"enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"selectByExampleQueryId="false"></table><table tableName="imooc_mall_order" domainObjectName="Order" enableCountByExample="false"enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"selectByExampleQueryId="false"></table><table tableName="imooc_mall_order_item" domainObjectName="OrderItem"enableCountByExample="false"enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"selectByExampleQueryId="false"></table><table tableName="imooc_mall_product" domainObjectName="Product" enableCountByExample="false"enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"selectByExampleQueryId="false"></table><table tableName="imooc_mall_user" domainObjectName="User" enableCountByExample="false"enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false"selectByExampleQueryId="false"></table></context>
</generatorConfiguration>

然后如下图双击生成实体类型以及xml和DAO接口

在application.properties中配置数据库

指明mappers的位置

spring.datasource.name=imooc_mall_datasource
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/imooc_mall?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123456
mybatis.mapper-locations=classpath:mappers/*.xml

打通Controller到service到DAO层(测试)

需要在主函数上配置basePackages说明DAO在那里

如果测试正确就代表数据库配置完成。

2.日志系统相关配置

移除logback 使用log4j配置pom.xml

   <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions></dependency><!--log4j2日志依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId></dependency>

引入log4j包后需要配置log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="fatal"><Properties><!--   value中是所包含存储日志的地方--><Property name="baseDir" value="D:/logs/mallLog"/></Properties><Appenders><Console name="Console" target="SYSTEM_OUT"><!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) --><ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/><PatternLayoutpattern="[%d{MM:dd HH:mm:ss.SSS}] [%level] [%logger{36}] - %msg%n"/></Console><!--debug级别日志文件输出--><RollingFile name="debug_appender" fileName="${baseDir}/debug.log"filePattern="${baseDir}/debug_%i.log.%d{yyyy-MM-dd}"><!-- 过滤器 --><Filters><!-- 限制日志级别在debug及以上在info以下 --><ThresholdFilter level="debug"/><ThresholdFilter level="info" onMatch="DENY" onMismatch="NEUTRAL"/></Filters><!-- 日志格式 --><PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/><!-- 策略 --><Policies><!-- 每隔一天转存 --><TimeBasedTriggeringPolicy interval="1" modulate="true"/><!-- 文件大小 --><SizeBasedTriggeringPolicy size="100 MB"/></Policies></RollingFile><!-- info级别日志文件输出 --><RollingFile name="info_appender" fileName="${baseDir}/info.log"filePattern="${baseDir}/info_%i.log.%d{yyyy-MM-dd}"><!-- 过滤器 --><Filters><!-- 限制日志级别在info及以上在error以下 --><ThresholdFilter level="info"/><ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/></Filters><!-- 日志格式 --><PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/><!-- 策略 --><Policies><!-- 每隔一天转存 --><TimeBasedTriggeringPolicy interval="1" modulate="true"/><!-- 文件大小 --><SizeBasedTriggeringPolicy size="100 MB"/></Policies></RollingFile><!-- error级别日志文件输出 --><RollingFile name="error_appender" fileName="${baseDir}/error.log"filePattern="${baseDir}/error_%i.log.%d{yyyy-MM-dd}"><!-- 过滤器 --><Filters><!-- 限制日志级别在error及以上 --><ThresholdFilter level="error"/></Filters><!-- 日志格式 --><PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/><Policies><!-- 每隔一天转存 --><TimeBasedTriggeringPolicy interval="1" modulate="true"/><!-- 文件大小 --><SizeBasedTriggeringPolicy size="100 MB"/></Policies></RollingFile></Appenders><Loggers><Root level="debug"><AppenderRef ref="Console"/><AppenderRef ref="debug_appender"/><AppenderRef ref="info_appender"/><AppenderRef ref="error_appender"/></Root></Loggers>
</Configuration>

然后配置截断器,也就是一切流量都会经过日志,新建Filter目录下WebLogAspect.xml

package com.imooc.mall.Filter;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;@Aspect
@Component
public class WebLogAspect {private final Logger log = LoggerFactory.getLogger(WebLogAspect.class);//经过控制器的所有流量@Pointcut("execution(public * com.imooc.mall.Controller.*.*(..))")public void webLog() {}@Before("webLog()")//请求发生之前public  void doBefore(JoinPoint joinPoint){ServletRequestAttributes requestAttributes =                 (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();HttpServletRequest request = requestAttributes.getRequest();log.info("URL: "+request.getRequestURI().toString());log.info("HTTP_METHOD: "+request.getMethod());log.info("IP: "+request.getRemoteAddr());log.info("CLASS_METHOD" + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());log.info("ARGS :" + Arrays.toString(joinPoint.getArgs()));}//请求发生以后@AfterReturning(returning = "res", pointcut = "webLog()")public void doAfterReturning(Object res) throws JsonProcessingException {//处理完请求,返回内容log.info("RESPONSE :" + new ObjectMapper().writeValueAsString(res));}}

二、开发框架搭建

1.设置返回接口标准类

接口需要返回状态代码code,以及返回成功与否msg,成功时需要携带得数据data:

由于data得类型不确定所

package com.imooc.mall.common;
import com.imooc.mall.Exception.MallExceptionEnum;
public class ApiRestResponse<T> {private Integer status;private String  msg;private T data;private static final  int OK_CODE = 1000;private static final  String OK_MSG="success";/*不返回data时,使用的构造函数*/ApiRestResponse(Integer status,String msg){this.status = status;this.msg = msg;}ApiRestResponse(Integer status,String msg,T data){this.status = status;this.msg = msg;this.data = data;}public ApiRestResponse() {this(OK_CODE, OK_MSG);}public Integer getStatus() {return status;}public void setStatus(Integer status) {this.status = status;}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;}/*** 请求成功 data=null* @return*/public static <T> ApiRestResponse<T> success(){return new ApiRestResponse<>();}/*** 请求成功* @param result data数据* @param <T>* @return*/public static <T> ApiRestResponse<T> success(T result){ApiRestResponse<T> arr = new ApiRestResponse<>();arr.setData(result);return  arr;}/*** 请求失败* @param status* @param msg* @param <T>* @return*/public static <T> ApiRestResponse<T> fail(Integer status ,String msg){return new ApiRestResponse<>(status,msg);}/*与自定义的异常搭配使用*/public static <T> ApiRestResponse<T> error(MallExceptionEnum ex){return  new ApiRestResponse<>(ex.getCode(),ex.getMsg());}}

2.自定义异常枚举类

异常枚举类是定义在程序运行过程中需要处理的异常类型

package com.imooc.mall.Exception;public enum MallExceptionEnum {NEED_USER_NAME(10001,"用户名不能空"),NEED_PASSWORD(10002,"密码不能为空"),PASSWORD_TOO_SHORT(10003,"密码长度不能小于8位"),NAME_EXIST(10004,"名称已经存在"),INSERT_FAIL(10005,"用户注册失败"),LOGIN_FAIL(10007,"用户名或者密码错误"),NEED_LOGIN(10008,"用户未登录"),UPDATE_FAILED(10009,"更新失败"),NEED_ADMIN(10010,"非管理员用户"),NAME_NOT_NULL(10011,"参数不能为空"),PARAM_ERROR(10012,"参数不合法"),DELETE_ERROR(10013,"删除失败"),PARAM_NOT_EXIST(10014,"缺失参数"),MKDIR_FAILED(10015,"文件夹创建失败"),UPLOAD_FAIL(10016,"文件上传失败"),PRODUCT_NOT_EXISTED(10017,"该商品不可售出"),NOT_ENOUGH(10018,"商品库存不足"),CART_SELECTED_EMPTY(10019,"购物车勾选商品为空"),ORDER_NOT_EXISTED(10020,"订单不存在"),NOT_YOU(10021,"未授权访问"),NOT_ENUM(10022,"不存在此代码"),WRONG_ORDER_STATUS(10023,"当前订单状态不为未支付"),USERNAME_NOT_EXISTED(10024,"用户名不能更改"),SYSTEM_ERROR(20001,"系统错误");/*code 是API接口返回的codemsg 是API接口返回的msg
*/Integer code;String msg;MallExceptionEnum(Integer code, String msg) {this.code = code;this.msg = msg;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}
}

3. 自定义异常处理类

Service层在进行操作时会产生各种异常,我们需要将异常统一归类,方便全局处理

package com.imooc.mall.Exception;public class MallException extends Exception{private Integer code;private String msg;public MallException(Integer code,String msg){this.code =code;this.msg = msg;}public MallException(MallExceptionEnum exceptionEnum){this.code =exceptionEnum.getCode();this.msg = exceptionEnum.getMsg();}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}
}

这里存在两种初始化,实际上用得多的是第二种类型。

4. 全局异常处理类

package com.imooc.mall.Exception;import com.imooc.mall.Annotation.OperationLogAnnotation;
import com.imooc.mall.common.ApiRestResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;import java.util.ArrayList;
import java.util.List;/*ControllerAdvice 全局Controller异常接受*/
@ControllerAdvice
public class GlobalExceptionHandler {private final Logger log=LoggerFactory.getLogger(GlobalExceptionHandler.class);@ExceptionHandler(Exception.class)@ResponseBodypublic ApiRestResponse handleException(Exception e){log.error("System Exception:",e);return ApiRestResponse.error(MallExceptionEnum.SYSTEM_ERROR);}@ExceptionHandler(MallException.class)@ResponseBodypublic ApiRestResponse handleMallException(MallException e){log.error("Projection Exception:",e);return ApiRestResponse.fail(e.getCode(),e.getMsg());}@ExceptionHandler(MethodArgumentNotValidException.class)@ResponseBodypublic ApiRestResponse handleVaildException(MethodArgumentNotValidException e){log.error("MethodArgumentNotValidException:",e);return handleBindingResult(e.getBindingResult());}private ApiRestResponse handleBindingResult(BindingResult result) {List<String> list = new ArrayList<>();if (result.hasErrors()) {//如果BindingResult中,包含错误,就获取其中所有的错误信息;List<ObjectError> allErrors = result.getAllErrors();//遍历所有的错误信息;for (int i = 0; i < allErrors.size(); i++) {ObjectError objectError = allErrors.get(i);//提取具体的错误信息;String message = objectError.getDefaultMessage();//将错误信息,添加到list集合中list.add(message);}}if (list.size() == 0) {return ApiRestResponse.error(MallExceptionEnum.PARAM_ERROR);}//根据MethodArgumentNotValidException异常的具体错误信息,构建ApiRestResponse统一返回对象;return ApiRestResponse.fail(MallExceptionEnum.PARAM_ERROR.getCode(), list.toString());}@ExceptionHandler(MissingServletRequestParameterException.class)@ResponseBodypublic ApiRestResponse handleParamException(MissingServletRequestParameterException e){log.error("MissingServletRequestParameterException:",e);return ApiRestResponse.error(MallExceptionEnum.PARAM_NOT_EXIST);}
}

@ControllerAdvice注解,用于对Controller层抛出的异常处理

我们这里处理了4种类型的异常

  • 系统异常
  • 自定义异常
  • 参数输入步骤缺,入如参数确实,参数为空
  • 参数有特定的范围时,输入不在此范围之类会抛出异常

三、全局校验

1. 全局常量参数

package com.imooc.mall.common;import com.google.common.collect.Sets;
import com.imooc.mall.Exception.MallException;
import com.imooc.mall.Exception.MallExceptionEnum;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import java.util.Set;@Component
public class Constant {public static  final String salt = "hasu9fhdsiofjiosa}{x";public static  final String MALL_USER = "mall_user";public static  String FILE_UPLOAD_DIR;@Value("${file.upload.dir}")public void setFileUploadDir(String fileUploadDir){FILE_UPLOAD_DIR = fileUploadDir;}public interface ProductListOrderBy{Set<String> PRICE_ASC_DESC = Sets.newHashSet("price desc","price asc");}public enum OrderStatusEnum{CANCELED(0, "用户已取消"),NOT_PAY(10, "未付款"),PAID(20,"已付款"),DELIVERED(30,"已发货"),FINISHED(40,"交易完成");private int code;private String value;OrderStatusEnum(int code, String value) {this.code = code;this.value = value;}public static String codeOf(int code) throws MallException{for(OrderStatusEnum ose:values()){if(ose.getCode()==code){return ose.getValue();}}throw new MallException(MallExceptionEnum.NOT_YOU);}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getValue() {return value;}public void setValue(String value) {this.value = value;}}
}

全局参数包括:

  • 盐值
  • session存储参数
  • 文件上传存储位置
  • order by 排序类型
  • 订单状态枚举

2. 用户身份校验

package com.imooc.mall.Filter;import com.imooc.mall.common.Constant;
import com.imooc.mall.model.pojo.User;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.IOException;
import java.io.PrintWriter;public class UserFilter implements Filter {public static User currentuser;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request= (HttpServletRequest)servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;currentuser =   (User)request.getSession().getAttribute(Constant.MALL_USER);if(currentuser==null){PrintWriter out  = new HttpServletResponseWrapper(response).getWriter();out.write("{\n" +"    \"status\": 10008,\n" +"    \"msg\": \"NEED LOGIN\",\n" +"    \"data\": null\n" +"}");out.flush();out.close();return;}filterChain.doFilter(servletRequest,servletResponse);}@Overridepublic void destroy() {}
}

其中Constant类是用来定义常量的,会话管理的方法是利用java原生的session

3. 管理员权限校验

package com.imooc.mall.Filter;import com.imooc.mall.common.Constant;
import com.imooc.mall.model.pojo.User;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.IOException;
import java.io.PrintWriter;public class AdminFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}/*** 统一身份认证接口* @param servletRequest* @param servletResponse* @param filterChain* @throws IOException* @throws ServletException*/@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request= (HttpServletRequest)servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;User currentuser = (User)request.getSession().getAttribute(Constant.MALL_USER);if(currentuser==null){PrintWriter out  = new HttpServletResponseWrapper(response).getWriter();out.write("{\n" +"    \"status\": 10008,\n" +"    \"msg\": \"NEED LOGIN\",\n" +"    \"data\": null\n" +"}");out.flush();out.close();}if(currentuser.getRole().equals(2)){filterChain.doFilter(servletRequest,servletResponse);}else{PrintWriter out = new HttpServletResponseWrapper(response).getWriter();out.write("{\n" +"    \"status\": 10010,\n" +"    \"msg\": \"ADMIN NEED\",\n" +"    \"data\": null\n" +"}");out.flush();out.close();return;
}}@Overridepublic void destroy() {}
}

四、全局校验配置

我们在(三)中设置了过滤器,必须在有相应的配置才能让spring知晓

1. 用户校验配置

package com.imooc.mall.Config;import com.imooc.mall.Filter.UserFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class UserFilterConfig {@Beanpublic UserFilter userFilter(){return new UserFilter();}@Bean(name="userFilterConf")public FilterRegistrationBean adminFilterConifg(){FilterRegistrationBean frb = new FilterRegistrationBean();frb.setFilter(userFilter());frb.addUrlPatterns("/user/*");frb.addUrlPatterns("/cart/*");frb.addUrlPatterns("/order/*");frb.setName("userFilterConf");return frb;}}

2. 管理员校验配置

package com.imooc.mall.Config;import com.imooc.mall.Filter.AdminFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class AdminFilterConfig {@Beanpublic AdminFilter adminFilter(){return new AdminFilter();}@Bean(name="adminFilterConf")public FilterRegistrationBean adminFilterConifg(){FilterRegistrationBean frb = new FilterRegistrationBean();frb.setFilter(adminFilter());frb.addUrlPatterns("/admin/*");frb.setName("adminFilterConf");return frb;}
}

3. 文件存储实际位置与虚拟位置转化

package com.imooc.mall.Config;import com.imooc.mall.common.Constant;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class MallWebConfig implements WebMvcConfigurer {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry){registry.addResourceHandler("/images/**").addResourceLocations("file:"+ Constant.FILE_UPLOAD_DIR);}}

总结

SpringBoot电商后台开发项目总结(1)相关推荐

  1. 电商项目总结java_Vue 电商后台管理项目阶段性总结(推荐)

    一.阶段总结 该项目偏向前端更多一点,后端 API 服务是已经搭建好了的,我们只需要用既可以,(但是作为一个 全栈开发人员,它的数据库的表设计,Restful API 的设计是我们要着重学习的!!!) ...

  2. Vue全家桶 - 电商后台管理系统项目开发实录(详)

    目录 1. 项目概述 1.1 电商项目基本业务概述 1.2 电商后台管理系统的功能 1.3 电商后台管理系统的开发模式(前.后端分离) 2. 项目初始化 2.1 前端项目初始化步骤 码云相关操作 2. ...

  3. Vue电商后台管理系统项目开发实战(一)

    前言 当下根据不同的应用场景,电商系统一般都提供了PC端,移动APP,移动Web,微信等多种访问方式.如下图. 不同的客户端共用同一个服务器,数据库,API.本次项目着重设计PC后台管理,供电商后台管 ...

  4. Vue全家桶-电商后台管理系统项目开发

    项目效果展示: 1. 项目概述 1.1 电商项目基本业务概述 一般情况下客户使用的业务服务包括:PC端,小程序,移动web,移动app. 管理员使用的业务服务:PC后台管理端: PC后台管理端的功能 ...

  5. 电商后台管理系统项目的优化

    在面试过程中,面试官除了对基础知识的盘查之外,还会了解你所做的项目,单单知识谈项目所用到的技术已经满足不了面试官对我们的好奇心了,每次面试问到优化这一方面,因为没怎么准备,含糊的说辞只会让面试官连连摇 ...

  6. 字节 抖音电商后台开发日常实习 一二面面经(已凉)

    恭喜发现宝藏!搜索公众号[TechGuide]回复公司名,解锁更多新鲜好文和互联网大厂的笔经面经,目前已更新至美团.微软- 作者@TechGuide[全网同名] 背景 面试部门:字节抖音电商 面试时间 ...

  7. Vue前后端分离的电商后台管理系统项目的概述

    (1)该项目是基于前后端分离的开发模式,基于Vue技术栈的SPA单页面项目, 后端主要操作数据库并向前端暴露一些API接口 前端主要负责绘制页面同时,利用Ajax调用后端提供的接口. 这样的开发模式使 ...

  8. 电商后台开发之商品规格组合算法

    前言  最近接了私活,关于器械商城的项目,最后收尾阶段,发现发布商品还是存在着问题,对于多个相同/不同的商品规格输出成商品时,需要依据规格名对规格值进行排列组合,保证所有规格值都可以进行选择. 核心代 ...

  9. 【VUE项目】VUE+ElementUI电商后台管理系统

    电商后台管理系统 项目来源:https://www.bilibili.com/video/BV1x64y1S7S7?p=191&spm_id_from=333.1007.top_right_b ...

最新文章

  1. cocos2dx JS 游戏切到后台再进入游戏的处理
  2. webview加载本地html_安卓webview html5 自动播放本地视频,网上视频,可以循环播放...
  3. SCSS SASS Color 颜色函数用法
  4. java long double精度丢失_long long类型转double类型部分精度丢失问题
  5. Windows2008的安装
  6. labview圆环里实物动画图形_有趣的图形教案
  7. 聚类方法:DBSCAN算法研究
  8. 职场中必需修炼的七项意识
  9. 调试输出类型为dll的程序
  10. 解决flash builder 4.6安装过程中安装程序遇到错误(-1)
  11. [转]C#自定义应用程序配置文件App.config
  12. java编程——图片旋转
  13. Siemens M65...
  14. 客房管理系统类毕业论文文献都有哪些?
  15. 舵机弹跳机器人_Nature:蚂蚁机器人弹跳力惊人 还会分工合作
  16. CTF杂项-BUUCTF竞赛真题WriteUp(2)
  17. excel单元格内容拆分_Excel | 单元格内容换行方法
  18. A Game of Thrones(15)
  19. e-mobile服务器地址显示无法登陆,E-Mobile服务器安装设置手册.doc
  20. B站马士兵python入门基础版详细笔记(4)

热门文章

  1. 雷军疯了吗?一个亿+全面环绕屏,徒有噱头还是突破有佳?
  2. php仿qq群聊,用Python写一个类似qq群聊的聊天室
  3. 从零开始学DedeCms模板,模板教程,从此模板制作不求人
  4. 开车,开车,我漂亮吗?我只想看到两个字的回答
  5. 大工秋 计算机应用基础,大工秋《计算机应用基础》在线测试答案
  6. SAP 各个模块的教学视频
  7. 使用Navicat for Mysql创建数据库
  8. 爆款短视频拍摄技巧之摇、移、跟拍等,这样拍的视频才更有吸引力,速收藏
  9. Android 快速开发框架汇总
  10. 辞职如何尽快离职_如何离职:准备,辞职和过渡