当前位置: 首页 > news >正文

SpringBoot项目开发实战销售管理系统——项目框架搭建!

项目框架搭建

在完成项目的分析和数据库设计后,一般由架构师完成项目框架的搭建,包括项目依赖的添加、项目的配置和项目日志的配置,完成后再开始业务代码的编写。

技术栈的搭建

新建一个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等。这些工具类的代码就不一一列出,请读者下载后自行查看。

至此就完成了整个项目的搭建工作,解决了通用部分的代码编写,后续需要完成业务代码的开发工作,实现所有的业务功能,最后进行调试。

http://www.lqws.cn/news/584947.html

相关文章:

  • 【windows上VScode开发STM32】
  • C#数字格式化全解析:从基础到进阶的实战指南
  • 电铸Socket弹片测试全解析:如何提升5G连接器稳定性?
  • 华为物联网认证:开启万物互联的钥匙
  • uni-app开发app保持登录状态
  • 【C++】简单学——模板初阶
  • 中证500股指期货一手多少钱呢?风险如何?
  • 易语言-登录UI演示
  • 一个代理对象被调用时,方法调用的链路是怎样的?
  • 【Kafka使用方式以及原理】
  • 安卓获取图片(相机拍摄/相册选择)
  • Android Telephony 网络状态中的 NAS 信息
  • window显示驱动开发—在注册表中设置 DXGI 信息
  • 【C语言】知识总结·内存函数
  • 三态门Multisim电路仿真——硬件工程师笔记
  • 优雅草蜻蜓HR人才招聘系统v2.0.9上线概要 -优雅草新产品上线
  • Amazon Athena:无服务器交互式查询服务的终极解决方案
  • 33. 搜索旋转排序数组
  • pytorch底层原理学习--PyTorch 架构梳理
  • FreePDFv3.0.0:颠覆你的文献阅读习惯
  • 16014.rtsp推流服务器
  • C++ 第四阶段 STL 容器 - 第五讲:详解 std::set 与 std::unordered_set
  • TDH社区开发版安装教程
  • [学习]M-QAM的数学原理与调制解调原理详解(仿真示例)
  • [面试]手写题-Promise.all() Promise.race()
  • 机器学习20-线性网络思考
  • 第三十六章 CAN——控制器局域网络接口
  • 字节跳动 C++ QT PC客户端面试
  • 论文中用matplotlib画的图,如何保持大小一致。
  • Vue2中使用DHTMLX Gantt