行业知识
项目-论坛系统
2026-11-03 07:28:48
来源:互联网转载
基于Spring前后���分离版本的论坛系统。
1、构建项目结构
- common公共类:统一返回结果、全局变量、异常枚举信息
- config配置类:Swagger,用于自动生成CRUD和基本对象
- controller控制器类:用于接受前端信息和控制路由
- dao数据库访问类:用于控制数据库操作
- exception自定义异常类:用以定义统一异常变量
- interceptor自定义拦截器类:用于定义拦截器
- model数据库实体对应模型类:用于定义对象
- services业务服务层接口:用于定义服务接口
- impl业务服务层接口实现类:复写接口的方法,用于实现业务
- utils辅助工具类:存放一些辅助工具,如加密、解密等
- mapper:用于存放自动生成的xml文件,以及自定义的xml文件
- mybatis:用于配置mybatis自动生成CRUD的文件
- static:前端组件
Mybatis - generator
配置数据源
5.1.492.3.01.2.16
# 配置数据源datasource: url: jdbc:mysql://127.0.0.1:3306/forum_db?characterEncoding=utf8&useSSL=false # 数据库连接串 username: root # 数据库⽤⼾名 password: 123456 # 数据库密码 driver-class-name: com.mysql.jdbc.Driver # 数据库连接驱动
编写类与映射文件
编写映射文件xxxMapper.xml
编写Dao类,xxxMapper.java
在properties标签中加入版本号,在build的plugins中加入配置
1.4.1 org.mybatis.generator mybatis-generator-maven-plugin ${mybatis-generator-plugin-version} Generate MyBatis Artifactsdeploy generate true true src/main/resources/mybatis/generatorConfig.xml创建generatorConfig.xml
创建mapper目录,在maven选项中,plugins节点下出现mybatis-generator,双击运行。
加@Mapper注解,在config包下新建MybatisConfig类,指定mybatis的扫描路径
// 配置类@Configuration// 指定Mybatis的扫描路径@MapperScan("com.bitejiuyeke.forum.dao")public class MybatisConfig {}mybatis: mapper-locations: classpath:mapper/**/*.xml # 指定 xxxMapper.xml的扫描路径
2、编写公共代码
编写状态码,用枚举类型
package com.example.forum.common;/** * 枚举结果状态码 */public enum ResultCode { SUCCESS (0, "操作成功"), FAILED (1000, "操作失败"), FAILED_UNAUTHORIZED (1001, "未授权"), FAILED_PARAMS_VALID (1002, "参数校验失败"), FAILED_FORBIDDEN (1003, "禁⽌访问"), FAILED_CREATE (1004, "新增失败"), FAILED_NOT_EXISTS (1005, "资源不存在"), //用户 FAILED_USER_EXISTS (1101, "⽤⼾已存在"), FAILED_USER_NOT_EXISTS (1102, "⽤⼾不存在"), FAILED_LOGIN (1103, "⽤⼾名或密码错误"), FAILED_USER_BANNED (1104, "您已被禁⾔, 请联系管理员, 并重新登录."), FAILED_TWO_PWD_NOT_SAME (1105, "两次输⼊的密码不⼀致"), FAILED_USER_ARTICLE_COUNT (1106,"更新帖子数量失败"), //板块 FAILED_BOARD_ARTICLE_COUNT (1201,"更新帖子数量失败"), FAILED_BOARD_BANNED (1202,"板块内部错误"), FAILED_BOARD_NOT_EXISTS (1203, "板块不存在"), FAILED_ARTICLE_NOT_EXISTS (1301, "帖子不存在"), FAILED_ARTICLE_BANNED (1302, "帖子状态异常"), //站内信 FAILED_MESSAGE_NOT_EXISTS (1401,"站内信不存在"), //服务器 ERROR_SERVICES (2000, "服务器内部错误"), ERROR_IS_NULL (2001, "IS NULL."); int code; //状态码 String message; //描述信息 ResultCode(int code, String message) { this.code = code; this.message = message; } public int getCode() { return code; } public String getMessage() { return message; } @Override public String toString() { return "code = " + code + "," + "message = " + message; }}编写统一返回结果,用AppResult对象的格式返回
package com.example.forum.common;import com.fasterxml.jackson.annotation.JsonInclude;/** * 统一对外返回格式 * @param */public class AppResult { @JsonInclude(JsonInclude.Include.ALWAYS) //无论任何情况,这个字段都要参数json序列化 private int code; //状态码 @JsonInclude(JsonInclude.Include.ALWAYS) private String message; //描述消息 @JsonInclude(JsonInclude.Include.ALWAYS) private T data; //具体的数据,通配类型,会被编译成Object //构造方法 public AppResult(int code, String message, T data) { this.code = code; this.message = message; this.data = data; } public AppResult(int code, String message) { this.code = code; this.message = message; this.data = null; } //提供给外部使用的静态方法 public static AppResult success(){ return new AppResult(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMessage()); } public static AppResult success(String message){ return new AppResult(ResultCode.SUCCESS.getCode(), message); } public static AppResult success (T data){ return new AppResult(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMessage(),data); } public static AppResult success(String message,T data){ return new AppResult(AppResult.success().getCode(),message,data); } public static AppResult failed(){ return new AppResult(ResultCode.FAILED.getCode(), ResultCode.FAILED.getMessage()); } public static AppResult failed(String message){ return new AppResult(ResultCode.FAILED.getCode(), message); } public static AppResult failed(ResultCode resultCode){ return new AppResult(resultCode.getCode(), resultCode.getMessage()); } //普通get set方法 public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public T getData() { return data; } public void setData(T data) { this.data = data; }}编写自定义全局异常类ApplicationException
package com.example.forum.exception;import com.example.forum.common.AppResult;/** * 统一异常处理,使用AppResult来包装返回值 */public class ApplicationException extends RuntimeException{ //自定义错误,在异常中持有一个错误信息对象 protected AppResult errorResult; //自定义构造方法 public ApplicationException(AppResult errorResult){ super(errorResult.getMessage()); this.errorResult = errorResult; } //重写父类方法 public ApplicationException(String message) { super(message); } public ApplicationException(String message, Throwable cause) { super(message, cause); } public ApplicationException(Throwable cause) { super(cause); } //get方法 public AppResult getErrorResult() { return errorResult; }}编写登录拦截器
package com.example.forum.interceptor;import com.example.forum.common.AppConfig;import org.springframework.beans.factory.annotation.Value;import org.springframework.stereotype.Component;import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;/** * 拦截器 */@Componentpublic class LoginInterceptor implements HandlerInterceptor { @Value("${bit-forum.login.url}") private String defaultURL; /** * 对请求的前置预处理 * @return */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session = request.getSession(false); if (session != null && session.getAttribute(AppConfig.USER_SESSION) != null){ //校验通过,已登录状态 return true; } //校验URL前面有/吗 if (!defaultURL.startsWith("/")){ defaultURL = "/" + defaultURL; } //不通过就跳转到登录界面 response.sendRedirect(defaultURL); return false; }}package com.example.forum.interceptor;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import javax.annotation.Resource;@Configurationpublic class AppInterceptorConfigurer implements WebMvcConfigurer { @Resource private LoginInterceptor loginInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { // 添加登录拦截器 registry.addInterceptor(loginInterceptor) // 添加用户登录拦截器 .addPathPatterns("/**") // 拦截所有请求 .excludePathPatterns("/sign-in.html") // 排除登录HTML .excludePathPatterns("/sign-up.html") // 排除注册HTML .excludePathPatterns("/user/login") // 排除登录api接口 .excludePathPatterns("/user/register") // 排除注册api接口 .excludePathPatterns("/user/logout") // 排除退出api接口 .excludePathPatterns("/swagger*/**") // 排除登录swagger下所有 .excludePathPatterns("/v3*/**") // 排除登录v3下所有,与swagger相关 .excludePathPatterns("/dist/**") // 排除所有静态文件 .excludePathPatterns("/image/**") .excludePathPatterns("/js/**") .excludePathPatterns("/**.ico"); }}# 项⽬⾃定义相关配置bit-forum: login: url: sign-in.html # 未登录状况下强制跳转⻚⾯
3、Swagger检测
3.0.0
io.springfox springfox-boot-starter ${springfox-boot-starter.version} org.springframework.boot spring-boot-starter-actuatorpackage com.example.forum.config;import org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties;import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;import org.springframework.boot.actuate.autoconfigure.web.server.ManagementPortType;import org.springframework.boot.actuate.endpoint.ExposableEndpoint;import org.springframework.boot.actuate.endpoint.web.*;import org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier;import org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier;import org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.env.Environment;import org.springframework.util.StringUtils;import springfox.documentation.builders.ApiInfoBuilder;import springfox.documentation.builders.PathSelectors;import springfox.documentation.builders.RequestHandlerSelectors;import springfox.documentation.oas.annotations.EnableOpenApi;import springfox.documentation.service.ApiInfo;import springfox.documentation.service.Contact;import springfox.documentation.spi.DocumentationType;import springfox.documentation.spring.web.plugins.Docket;import java.util.ArrayList;import java.util.Collection;import java.util.List;// 配置类@Configuration// 开启Springfox-Swagger@EnableOpenApipublic class SwaggerConfig { //创建基本扫描路径,与controller路径要一致 public Docket createApi() { Docket docket = new Docket(DocumentationType.OAS_30) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.example.forum.controller")) .paths(PathSelectors.any()) .build(); return docket; } // 配置API基本信息 private ApiInfo apiInfo() { ApiInfo apiInfo = new ApiInfoBuilder() .title("论坛系统API") .description("论坛系统前后端分离API测试") .contact(new Contact(" Tech", "https://", "1161245326@qq.com")) .version("1.0") .build(); return apiInfo; } /** * 解决SpringBoot 6.0以上与Swagger 3.0.0 不兼容的问题 * 复制即可 **/ @Bean public WebMvcEndpointHandlerMapping webMvcEndpointHandlerMapping ( WebEndpointsSupplier webEndpointsSupplier, ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties, WebEndpointProperties webEndpointProperties, Environment environment) { List
上一篇:怎么下根服务器?