SpringBoot项目开发实战销售管理系统——项目框架搭建!
ccwgpt 2025-07-27 19:15 1 浏览 0 评论
项目框架搭建
在完成项目的分析和数据库设计后,一般由架构师完成项目框架的搭建,包括项目依赖的添加、项目的配置和项目日志的配置,完成后再开始业务代码的编写。
技术栈的搭建
新建一个Spring Boot项目,选择的Spring Boot版本为2.3.10.RELEASE,使用Maven构建依赖,项目名称为sell-manager,设置当前项目的Maven坐标,其中groupId为com.onyx,artifactId为sell-manager。
(1)pom.xml的主要内容如下:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.10.RELEASE</version>
<relativePath/>
</parent>
<name>sell-manager</name>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-
8</project.reporting.outputEncoding>
<java.version>11</java.version>
</properties>
(2)在项目中添加依赖,代码如下:
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot 测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Spring Boot AOP -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- Spring Boot JDBC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- Spring Boot 日志-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!--html 解析引擎 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-MyBatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!--MySQL驱动 -->
<dependency> <groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<!--fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.55</version>
</dependency>
<!--Log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
<scope>compile</scope>
</dependency>
<!--guava-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.0.1-jre</version>
</dependency>
<dependency>
<groupId>com.belerweb</groupId> <artifactId>pinyin4j</artifactId>
<version>2.5.1</version>
</dependency>
<!-- common-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10</version>
</dependency>
<!--commons-fileupload-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
<!-- 随机生成数据 -->
<dependency>
<groupId>com.github.jsonzou</groupId>
<artifactId>jmockdata</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
</dependencies>
(3)添加完依赖后,在application.properties中添加项目的相关配置信息,代码如下:
#端口号
server.port=8085#加载日志配置文件
logging.config=classpath:log4j2.xml
(4)配置数据库的连接信息,代码如下:
#druid
# 数据库访问配置
# 默认的主数据源
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/sell-manager?
useUnicode=
true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
#数据库的账号和密码
spring.datasource.username=root
spring.datasource.password=123456
#数据库连接池的配置
spring.datasource.removeAbandoned=true
spring.datasource.removeAbandonedTimeout=180
spring.datasource.logAbandoned=true
# 连接池的补充设置,将其应用到上面的所有数据源中
spring.datasource.initialSize=5 #数据库连接池初始化数量spring.datasource.minIdle=5 #数据库连接池最小数量
spring.datasource.maxActive=20 #数据库连接池最大数量# 配置获取连接等待超时时间
spring.datasource.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是ms(毫秒)
spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最短生存的时间,单位是ms(毫秒)
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
# 打开PSCache,并且指定每个连接中PSCache的大小
spring.datasource.poolPreparedStatements=truespring.datasource.maxPoolPreparedStatementPerConnectionSize=20
# 配置监控统计拦截的filters,将其去掉后监控界面的SQL无法统计,wall用于防火墙
spring.datasource.filters=stat,wall,log4j
# 通过connectProperties属性开启mergeSql功能,并记录慢SQL
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.
stat.slowSqlMillis=5000
# 合并多个DruidDataSource监控数据
#spring.datasource.useGlobalDataSourceStat=true
(5)配置MyBatis,代码如下:
#当查询数据为空时字段返回null,不加查询数据为空时,字段将被隐藏
mybatis.configuration.call-setters-on-nulls=true
#开启驼峰命名并设置实体类的包位置
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.type-aliases-package=com.xisuo.sellmanager.entity
mybatis.mapper-locations=classpath:mapper/*.xml
(6)配置Freemaker模板引擎,代码如下:
#freemaker start
spring.freemarker.cache=false
spring.freemarker.charset=UTF-8
spring.freemarker.content-type=text/html
#文件的后缀为.ftl
spring.freemarker.suffix=.ftl
spring.freemarker.expose-request-attributes=true
spring.freemarker.expose-session-attributes=true
spring.freemarker.expose-spring-macro-helpers=true
#模板的位置
spring.freemarker.template-loader-path=classpath:/templates/
#编码方式全部是UTF-8
spring.freemarker.settings.default_encoding=UTF-8
spring.freemarker.settings.output_encoding=UTF-8
spring.freemarker.settings.url_escaping_charset=UTF-8#maxFileSize 单个数据大小#maxRequestSize 总数据大小
spring.servlet.multipart.maxFileSize = 5MB
spring.servlet.multipart.maxRequestSize=10MB
#freemaker end
(7)至此完成了项目最基本的技术栈的搭建工作。
注意:要设置整个项目的编码方式为UTF-8。
(8)完成项目各个分包的建立,为项目准备必要的开发文件,最终完成的目录结构如图9.8所示。
需要说明一下,在图9.8中,src的com.xisuo.sellmanager包下的目录含义如下:
aop:使用切面完成业务功能的实现。
config:项目的配置信息。
constant:项目中用到的常量。
controller:项目的所有控制器。
dao:项目的dao接口。
entity:数据库的实体类。
exception:异常处理。
interceptor:拦截器。
service:业务处理实现类。
utils:工具类。
在resources目录下的下一级目录的含义如下:
mapper:存放dao对应的xml目录。
pdf:存放pdf文件。
static:存放所有的静态文件,包括各种图片、js脚本文件和css文件。
templates:存放Freemaker模板。
application.properties:存放项目配置文件。
log4j2.xml:存放日志的配置文件。
(9)添加项目的所有静态文件到resources的static目录中,再新建日志配置文件log4j2.xml。当前保存用户的日志最长时间为90天,每天创建一个日志文件。log4j2.xml文件的内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="log.path" value="/web/xisuo/logs" />
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread]
%-5level%logger{20} - [%method,%line] - %msg%n" /> <!-- 控制台输出 -->
<appender name="console"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-info.log</file>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天回滚 daily -->
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log
</fileNamePattern>
<!-- 日志最长的时间为90天 -->
<maxHistory>90</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-error.log</file>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log
</fileNamePattern>
<!-- 日志最长的时间为90天 -->
<maxHistory>90</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder> <filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 用户访问日志输出 -->
<appender name="sys-user"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/sys-user.log</file>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 按天回滚 daily -->
<fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log
</fileNamePattern>
<!-- 日志最长的时间为90天 -->
<maxHistory>90</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 显示形成的SQL、使用的参数和结果集 -->
<!--
<logger name="java.sql" level="debug" />
<logger name="org.springframework.jdbc" level="debug" /> -->
<logger name="com.xisuo" level="info" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
<!--系统用户操作日志-->
<logger name="sys-user" level="info">
<appender-ref ref="sys-user"/>
</logger>
</configuration>
(10)添加Spring Boot项目的启动类App,标记@EnableScheduling注解,从而开始定时任务,通过@MapperScan("com.xisuo.sellmanager.dao")注解扫描数据库接口的包,代码如下:
package com.xisuo.sellmanager;
//启动类
@EnableScheduling
@MapperScan("com.xisuo.sellmanager.dao")
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class,args); //必须有这个方法
}
}
项目的搭建
完成上面的基础框架搭建后,开始编写项目的通用代码,包括项目的配置、日志记录的处理、拦截器的编写和异常的处理等。
(1)配置日志的切面处理类WebLogAspect,记录所有的请求入参,代码如下:
package com.xisuo.sellmanager.aop;
//切面日志的处理
@Aspect
@Component
@Order(1)
public class WebLogAspect {
private static Logger logger =
LoggerFactory.getLogger(WebLogAspect.class);
//定义切入点,切入点为com.example.aop下的所有函数
@Pointcut("execution(public *com.xisuo.sellmanager.controller..*.*(..))")
public void webLog() {
}
//前置通知:在连接点之前执行的通知
@Before("webLog()")
public void doBefore(JoinPoint joinPoint) throws Exception {
// 接收请求,记录请求内容
ServletRequestAttributes attributes =
(ServletRequestAttributes)
RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//打印请求内容
logger.info("请求内容开始 请求地址:{} 请求方式:{}",
request.getRequest
URL().toString(), request.getMethod());
logger.info("请求类方法: {} 请求类方法参数: {} ",
joinPoint.getSignature(),
Arrays.toString(joinPoint.getArgs()));
}
@After("webLog()")
public void doAfter(JoinPoint joinPoint) throws Exception {
}
@AfterReturning(returning = "obj", pointcut = "webLog()")
public void doAfterReturning(Object obj) throws Throwable {
}
}
(2)配置项目的数据库连接池类
DruidDataSourceConfiguration,将application. properties中数据库的连接配置成自定义的连接Bean。配置代码如下:
package com.xisuo.sellmanager.config;
//数据库的配置
@Configuration
public class DruidDataSourceConfiguration {
private Logger logger = LoggerFactory.getLogger(DruidDataSource
Configuration.class); @Value("${spring.datasource.url}")
private String dbUrl;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.driver-class-name}")
……//省略部分代码
@Bean //声明其为Bean实例
@Primary //在同样的DataSource中,首先使用被标注的
DataSource
public DataSource dataSource() {
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(dbUrl);
datasource.setUsername(username);
datasource.setPassword(password);
……//省略部分代码
datasource.setConnectionProperties(connectionProperties);
return datasource;
}
//注册一个StatViewServlet
@Bean
public ServletRegistrationBean DruidStatViewServle2() {
ServletRegistrationBean servletRegistrationBean = new Servlet
RegistrationBean(new StatViewServlet(), "/druid/*");
//添加初始化参数initParams
/** 白名单,如果不配置或value为空,则允许所有的IP访问 */
//
servletRegistrationBean.addInitParameter("allow","127.0.0.1,192.0.0.1"
);
/** 黑名单,与白名单存在相同的IP时,优先于白名单 */
//
servletRegistrationBean.addInitParameter("deny","192.0.0.1");
/** 用户名 */
servletRegistrationBean.addInitParameter("loginUsername",
"admin");
/** 密码 */
servletRegistrationBean.addInitParameter("loginPassword",
"admin");
/** 禁用页面上的Reset All功能 */
servletRegistrationBean.addInitParameter("resetEnable","false");
return servletRegistrationBean;
}
//注册一个WebStatFilter
@Bean
public FilterRegistrationBean druidStatFilter2() {
FilterRegistrationBean filterRegistrationBean = new Filter
RegistrationBean(new WebStatFilter());
/** 过滤规则 */
filterRegistrationBean.addUrlPatterns("/*");
/** 忽略资源 */
filterRegistrationBean.addInitParameter("exclusions",
"*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid2/*");
return filterRegistrationBean;
}
}
(3)本项目有HTML渲染需要用到js、css和图片等静态文件。静态文件的访问不需要登录,而直接根据URL请求静态文件即可。配置静态文件过滤器类ResourceConfig的代码如下:
package com.xisuo.sellmanager.config;
//静态文件过滤器的配置
@Configuration
public class ResourceConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//设置静态文件的存放目录
registry.addInterceptor(new ResourceInterceptor()).excludePath
Patterns("/static/**");
}
@Override
//需要告知系统,这里处理的文件要被当成静态文件
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
//设置上传的文件不拦截
TaleUtils.getUplodFilePath()//registry.addResourceHandler("/upload/**").addResourceLocations
("file:"+ "/" +"upload/");
//第一个方法设置访问路径前缀,第二个方法设置资源路径
registry.addResourceHandler("/static/**").addResourceLocations
("classpath:/static/");
}
}
(4)因为本例是Web项目,所以每一个对服务器的请求都需要判断是否合法,判断当前请求的用户是否已经成功登录系统,如果未登录,则不是合法的请求。对一些特殊的URL请求,可以设置不需要登录即可访问,例如登录请求、静态资源请求和错误页请求都不需要拦截。
package com.xisuo.sellmanager.config;
//拦截器的配置
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
//这里不要直接使用new LoginInterceptor,否则拦截器中的service会为null
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/", "/login","/static/**",
"/error");
//为了开发时不用登录即可测试接口
//registry.addInterceptor(loginInterceptor).excludePathPatterns
("/**");
}
}
(5)设置项目接口统一返回结果的实体类Result:
package com.xisuo.sellmanager.config.result;
/**对输出结果的封装,只要get方法而不要set方法*/
public class Result<T> {
private int code;
private String msg;
private T data;
private Result(T data){
this.code=0;
this.msg="success";
this.data=data;
}
private Result(CodeMsg mg) {
if (mg==null){
return;
}
this.code=mg.getCode();
this.msg=mg.getMsg();
}
//成功
public static <T> Result<T> success(T data){
return new Result<T>(data);
}
//失败
public static <T> Result<T> fail(CodeMsg mg){
return new Result<T>(mg);
}
//其他忽略
}
(6)新建项目全局异常处理类ExceptionHandle,捕获项目中
HttpRequestMethodNot-SupportedException不支持的方法异常及Exception异常,这些异常分别处理会得到不同的返回值,代码如下:
package com.xisuo.sellmanager.exception;
//异常的处理
@ControllerAdvicepublic class ExceptionHandle {
private static Logger logger =
LoggerFactory.getLogger(ExceptionHandle.class);
//异常的处理
@ExceptionHandler({Exception.class})
@ResponseStatus(HttpStatus.OK)
public ModelAndView handleException(Exception e){
ModelAndView m = new ModelAndView();
logger.error("服务器发生了异常,原因是:{}",e.toString());
m.addObject("error", e.getCause());
e.printStackTrace();
m.setViewName("error/500");
return m;
}
//不支持的方法
@ExceptionHandler({HttpRequestMethodNotSupportedException.class})
@ResponseStatus(HttpStatus.OK)
public ModelAndView methodSupport(Exception e){
ModelAndView m = new ModelAndView();
logger.error("不正确的访问方法,原因是:{}",e.getCause());
m.addObject("error", "不正确的访问方法");
e.printStackTrace();
m.setViewName("error/404");
return m;
}
}
(7)新建项目的登录拦截器LoginInterceptor.java文件,判断当前用户是否已经登录。如果没有登录,则跳转到登录页面,如果已经登录,则从cache中获取用户的信息并将其保存在ThreadLocal中,以方便在开发时获取用户的信息。处理完请求后执行afterCompletion方法,并清空ThreadLocal中的信息,以防止内存泄漏。
package com.xisuo.sellmanager.interceptor;
//登录过滤器
@Componentpublic class LoginInterceptor implements HandlerInterceptor {
private static Logger logger =
LoggerFactory.getLogger(LoginInterceptor.class);
@Autowired
@Qualifier("userService")
private UserService userService;
//在业务处理器处理请求之前调用。在企业开发中还可以进行编码、安全控制和权限校验等
预处理
@Override
public boolean preHandle(HttpServletRequest request, HttpServlet
Response response, Object handler) throws Exception {
//使用Cookie作为是否登录的判断依据
String value = CookieUtil.getCookieValue(request,
Constant.COOKIE_NAME);
String id = DESUtil.decrypt(value);
if (StringUtils.isBlank(value) || StringUtils.isBlank(id)) {
response.sendRedirect("/");
return false;
}
Object o = CacheUtils.get(Constant.USER_CACHE_PREFIX + id);
User user = null;
if (o != null) {
user = (User) o;
} else {
user = (User) CacheUtils.get(Constant.USER_CACHE_PREFIX +
id, () -> {
logger.info("拦截器缓存中没有用户{}的信息,去数据库中进行查询",
id);
return userService.getUserDetail(Long.parseLong(id));
});
}
if (user == null) {
response.sendRedirect("/");
return false;
}
CacheUtils.put(Constant.USER_CACHE_PREFIX + (user.getId()),
user);
UserContext.setUser(user);
return true;
} //在业务处理器处理执行请求完成后返回并生成视图之前执行
@Override
public void postHandle(HttpServletRequest request,
HttpServletResponse
response, Object handler, ModelAndView modelAndView) throws Exception
{
}
//在DispatcherServlet完全处理请求后被调用
//返回处理(已经渲染了页面)
@Override
public void afterCompletion(HttpServletRequest request,
HttpServlet
Response response, Object handler, Exception ex) throws Exception {
UserContext.remove();
}
}
(8)新建资源拦截器ResourceInterceptor.java文件,对静态资源进行过滤,代码如下:
package com.xisuo.sellmanager.interceptor;
//自定义的静态资源拦截器
public class ResourceInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServlet
Response response, Object handler) throws Exception {
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, Http
ServletResponse httpServletResponse, Object o, ModelAndView
modelAndView)
throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, Object o, Exception e) throwsException {
}
}
(9)新建当前访问用户的存储容器UserContext,每次登录时把用户信息放在当前的ThreadLocal容器中,以方便开发时获取用户信息,代码如下:
package com.xisuo.sellmanager.interceptor;
//持有用户的线程
public class UserContext {
private static ThreadLocal<User> userHolder=new ThreadLocal<>();
public static void setUser(User user){
userHolder.set(user);
}
public static User getUser(){
return userHolder.get();
}
public static void remove(){
userHolder.remove();
}
}
(10)新建分页实体类Page,在请求列表时返回分页信息,代码如下:
package com.xisuo.sellmanager.utils;
//分页的工具类
public class Page<T> implements Serializable {
private static final long serialVersionUID = 1L;
private int pageNo; //当前页数
private int pageSize; //每页显示的记录数
private int totalCounts; //总记录数
private int totalPages; //总页数
private int pageNum; //索引页数 private List<T> data; //列表数据
/* pageNo表示当前页,totalCounts表示总记录数,data表示数据*/
public Page(int pageNo, int totalCounts, List<T> data) {
this(pageNo, Constant.PAGE_SIZE, totalCounts, data);
}
/** 默认是第一页,一页15个,totalCounts表示总记录数,data表示数据*/
public Page(int totalCounts, List<T> data) {
this(Constant.PAGE, Constant.PAGE_SIZE, totalCounts, data);
}
/** pageNo表示第几页,pageSize表示一页多少个,totalCounts表示总记录数
*/
public Page(int pageNo, int pageSize, int totalCounts, List<T>
data) {
this.pageNo = pageNo;
this.pageSize = pageSize;
this.totalCounts = totalCounts;
this.totalPages = (totalCounts % pageSize == 0) ? totalCounts
/
pageSize : totalCounts / pageSize + 1;
this.pageNum = (pageNo - 1) * pageSize;
this.data = data;
}
private Page() {
}
//省略Get和Set方法
}
分页处理方法
因为很多列表的接口都会涉及分页参数的设置,考虑到参数设置的共性,这里抽取了一个参数处理类的服务类ParamService来处理所有的分页参数,其部分代码如下:
package com.xisuo.sellmanager.service.impl;
//参数服务类@Service("paramService")
public class ParamService {
private static Logger logger =
LoggerFactory.getLogger(ParamService.class);
//判断并处理传递的页码参数
public Map<String, Object> handlePageData(Integer pageNo) {
Map<String, Object> map = new HashMap<>(4);
if (pageNo == null || pageNo < 0) {
map.put("pageNum", (Constant.PAGE - 1) *
Constant.PAGE_SIZE);
map.put("pageNo", Constant.PAGE);
} else {
map.put("pageNum", (pageNo - 1) * Constant.PAGE_SIZE);
map.put("pageNo", pageNo);
}
map.put("pageSize", Constant.PAGE_SIZE);
return map;
}
/** 非空判断,不为空则放入数据,拼接前后的%,pair前面是名字,后面是值 */
public Map<String, Object> handleKeyLike(Map<String, Object> map,
Pair<String, String>... pair) {
if (map == null) {
return map;
}
for (Pair<String, String> immutablePair : pair) {
String right = immutablePair.getRight();
if (StringUtils.isNotBlank(right)) {
map.put(immutablePair.getLeft(), "%" + right + "%");
}
}
return map;
}
/** Integer不为空的判断,为空就保存默认值,不为空就放入数据
* @param triples 前面是名字,中间是值,第3个是默认值*/
public Map<String, Object> handleInt(Map<String, Object> map,
Triple
<String, Integer, Integer>... triples) {
if (map == null) {
return map;
}
for (Triple<String, Integer, Integer> triple : triples) { Integer middle = triple.getMiddle();
if (middle != null) {
map.put(triple.getLeft(), middle);
} else {
map.put(triple.getLeft(), triple.getRight());
}
}
return map;
}
//省略其他方法
}
本例还有一些很重要的工具类:MD5加密工具类MD5Util、时间工具类DateUtil等。这些工具类的代码就不一一列出,请读者下载后自行查看。
至此就完成了整个项目的搭建工作,解决了通用部分的代码编写,后续需要完成业务代码的开发工作,实现所有的业务功能,最后进行调试。
相关推荐
- Spring框架基础知识-第四节内容(Spring基础配置)
-
Spring基础配置Spring框架本身有四大原则:(1)使用POJO进行轻量级和最小侵入式开发。(2)通过依赖注入和基于接口编程实现松耦合。(3)通过AOP和默认习惯进行声明式编程。(4)使...
- SpringBoot项目开发实战销售管理系统——项目框架搭建!
-
项目框架搭建在完成项目的分析和数据库设计后,一般由架构师完成项目框架的搭建,包括项目依赖的添加、项目的配置和项目日志的配置,完成后再开始业务代码的编写。技术栈的搭建新建一个SpringBoot项目,...
- 从零到一:独立运行若依框架系统并进行本地二次开发
-
####一、环境准备1.**基础环境**:-JDK1.8+(推荐JDK17)-Maven3.6+-MySQL5.7+(推荐8.0)-Redis5.0+-Node.js16...
- 单片机时间片轮询程序架构(单片机如何实现精准的时间周期)
-
时间片轮询法有很多时候都是与操作系统一起被提到,也就是说很多时候是操作系统中使用了这一方法:STM32单片机开发中的RTOS。下文将参考别人的代码,演示建立的一个时间片轮询架构程序的...
- Netty主要组件和服务器启动源码分析
-
1.Netty服务端启动代码publicclassNettyServer{publicstaticvoidmain(String[]args)throwsInterrup...
- 前端定时任务的神库!快把它加到你的项目中去!
-
我们常会遇到定时刷新数据、轮询接口、发送提醒等场景,我们常会遇到定时刷新数据、轮询接口、发送提醒等场景。为什么选择cron库?定时任务开发痛点原生setInterval的时间误差累积难以实现复杂的...
- 如何正确实现一个后台(定时)任务(后台定时任务怎么实现)
-
相信大家都知道如何在.NET中执行后台(定时)任务。首先我们会选择实现IHostedService接口或者继承BackgroundService来实现后台任务。然后注册到容器内,然后注册到容...
- 秒杀传统的Linux Crontab,这款开源的定时任务管理系统绝了!
-
Gocron是一款开源的定时任务管理系统,基于Go语言开发,旨在替代传统的LinuxCrontab。它通过Web界面提供直观的任务管理功能,支持精确到秒的Crontab时间表达式,并具备任务重试、超...
- Python 定时任务:schedule 自动执行脚本太方便。
-
2025年了,还在为Python定时任务头疼?轻量级需求搞什么Celery,schedule三行代码就搞定。这库把定时任务简化到像说人话,但新手直接抄文档容易踩坑。文档只会告诉你怎么设置每10分钟执行...
- SpringBoot扩展——定时任务!(基于springboot的校园宿舍管理系统的设计与实现)
-
定时任务项目开发中会涉及很多需要定时执行的代码,如每日凌晨对前一日的数据进行汇总,或者系统缓存的清理、对每日的数据进行分析和总结等需求,这些都是定时任务。单体系统和分布式系统的分布式任务有很大的区别,...
- 适合普通开发者和产品经理的PHP应用模板开发AI的SaaS应用框架
-
简单到傻!Liang_SaaS适合普通开发者和产品经理的PHP应用模板开发AI的SaaS应用框架,利用Php开发AI的SaaS应用框架,是一个强大的内容管理仪表板模板,基于Bootstrap和...
- 非常实用的15款开源PHP类库(php开源管理系统)
-
PHP库给开发者提供了一个标准接口,它帮助开发者在PHP里充分利用面向对象编程。这些库为特定类型的内置功能提供了一个标准的API,允许类可以与PHP引擎进行无缝的交互。此外,开发者使用这些类库还可以简...
- 蜂神榜苹果商店也凑热闹:“520”我爱玩家!
-
各位看官,今天被朋友圈各类“520”刷屏呢?有没有给你亲爱的家人一份“520”模式的红包呢?苹果商店也给了玩家一个“520”模式的惊喜---再一次提供了多款“1元”价格的游戏!并且此次降价的游戏品质都...
- 变成气球的猫咪《气球》十一正式推出
-
墨西哥游戏公司NoodlecakeGames曾开发过《致命框架》、《阿尔托冒险》等优秀佳作,而它旗下的最新游戏《气球》(TheBalloons)在十一的时候就要和大家见面了。游戏中,玩家要操控娃娃...
- 星座超游爱:狮子遇挑战,处女手抓牢~
-
teemo跟大家讲了三期太阳星座,也许有很多不热心的小伙伴并不知道是什么东西,今天就小科普一番~在出生的那一天,太阳所落的那个星座,就是每个人的太阳星座,而这恰好就是大家的性格中心,是权势驱力、人格的...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- Spring框架基础知识-第四节内容(Spring基础配置)
- SpringBoot项目开发实战销售管理系统——项目框架搭建!
- 从零到一:独立运行若依框架系统并进行本地二次开发
- 单片机时间片轮询程序架构(单片机如何实现精准的时间周期)
- Netty主要组件和服务器启动源码分析
- 前端定时任务的神库!快把它加到你的项目中去!
- 如何正确实现一个后台(定时)任务(后台定时任务怎么实现)
- 秒杀传统的Linux Crontab,这款开源的定时任务管理系统绝了!
- Python 定时任务:schedule 自动执行脚本太方便。
- SpringBoot扩展——定时任务!(基于springboot的校园宿舍管理系统的设计与实现)
- 标签列表
-
- 框架图 (58)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- jpa框架 (47)
- springmvc框架 (49)
- 分布式事务框架 (65)
- scrapy框架 (56)
- shiro框架 (61)
- 定时任务框架 (56)
- java日志框架 (61)
- JAVA集合框架 (47)
- mfc框架 (52)
- abb框架断路器 (48)
- beego框架 (52)
- java框架spring (58)
- grpc框架 (65)
- tornado框架 (48)
- 前端框架bootstrap (54)
- orm框架有哪些 (51)
- ppt框架 (48)
- 内联框架 (52)
- cad怎么画框架 (58)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)