前言
近期想自己做个项目,仿发卡网的java web应用,集成支付宝的当面付功能。这是近期的一个总体规划,具体的计划还没有定下来。初步打算是,先完善后台管理系统部分,包括用户管理、角色管理、菜单管理、系统参数配置。再扩展业务功能模块,个人用户信息,商品管理,库存管理等。最后再做支付相关功能,支付平台配置,商户平台配置,支付接入。
目前来说,是做第一步的准备工作。很久之前搭建过一个后台管理的系统,使用的larryCms后端框架+Spring Mvc+mybatis+mysql。仅完成了登录、用户管理模块、用户管理关联角色功能等。计划是基于这个项目,先将其改造为spring boot结构,再进行继续开发。
一、原项目介绍
1、项目结构 两个应用工程+一个服务工程
2、后端使用spring mvc+mybatis集成
3、前端使用html+js 、layui前端框架,模块化结构;直接访问html页面,再通过ajax请求数据的模式。
二、项目改造
1、项目名称修改(可跳过)
由于新的项目想修改个名字,将原来的zxwa直接修改成zxw。于是先进行了名称的修改,包括pom.xml的groupId、artifactId,项目中的包名,以及引入包名等。
2、pom.xml文件修改
由于本身就是Maven多模块项目,集成spring boot需要引入一个parent标签,而子模块项目中本身就有parent标签了,所以将其写在主项目的pom.xml文件中。
在主pom文件中添加
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent>
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> </configuration> </plugin>
在zxw-service工程的pom.xml中添加
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.0</version> </dependency>
在zxw-admin工程pom.xml文件中,需要将resources标签注释掉,否则后面将静态文件放到resources目录下时将无法访问,jdk使用1.8版本
3、application.properties文件配置
在resources目录下创建该文件
#设置true时,控制台会打印spring自动配置的服务 debug=false #自定义参数配置 应用名称 com.zjh.appName="智选网平台" #自定义参数配置 上传路径 com.zjh.uploadPath=J:\\zxwUpload\\ #spring boot日志路径 logging.path=J:\\springboot\\log #spring boot日志级别 com.zjh logging.level.com.zjh=INFO #spring boot日志级别 org.springframework.web logging.level.org.springframework.web=INFO #打印sql部分 log4j.logger.java.sql=DEBUG log4j.logger.java.sql.Connection = DEBUG log4j.logger.java.sql.Statement = DEBUG log4j.logger.java.sql.PreparedStatement = DEBUG log4j.logger.java.sql.ResultSet = DEBUG #配置logger扫描的包路径 这样才会打印sql log4j.logger.com.zjh.zxw=DEBUG #应用断开 server.port=9999 #session超时时间,单位为s server.session.timeout= 1800 #数据源配置 spring.datasource.url=jdbc:mysql://***:3306/zxwa?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true spring.datasource.username=*** spring.datasource.password=*** spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.initialSize=5 spring.datasource.minIdle=5 spring.datasource.maxActive=20 # 配置获取连接等待超时的时间 spring.datasource.maxWait=60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 spring.datasource.timeBetweenEvictionRunsMillis=60000 # 配置一个连接在池中最小生存的时间,单位是毫秒 spring.datasource.minEvictableIdleTimeMillis=300000 spring.datasource.validationQuery=SELECT 1 FROM DUAL spring.datasource.testWhileIdle=true spring.datasource.testOnBorrow=false spring.datasource.testOnReturn=false # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 spring.datasource.filters=stat,wall spring.datasource.logSlowSql=true #mybatis实体别名目录 mybatis.type-aliases-package=com.zjh.zxw.domain.entity #mybatis sqlMap的xml文件目录 mybatis.mapper-locations=classpath*:sqlmap/*.xml #mybatis.config-location=classpath*:zxw-config.mybatis.xml #开启驼峰命名 mybatis.configuration.map-underscore-to-camel-case=true #sql日志打印设置 mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl # Redis数据库索引(默认为0) spring.redis.database=0 # Redis服务器地址 spring.redis.host=localhost # Redis服务器连接端口 spring.redis.port=6379 # Redis服务器连接密码(默认为空) spring.redis.password= # 连接池最大连接数(使用负值表示没有限制) 默认 8 spring.redis.lettuce.pool.max-active=8 # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1 spring.redis.lettuce.pool.max-wait=-1 # 连接池中的最大空闲连接 默认 8 spring.redis.lettuce.pool.max-idle=8 # 连接池中的最小空闲连接 默认 0 spring.redis.lettuce.pool.min-idle=0
4、创建SpringbootApplication文件
在com.zjh.zxw目录下创建java类
package com.zjh.zxw; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.transaction.annotation.EnableTransactionManagement; /** * @SpringBootApplication其实就是以下三个注解的总和 * @Configuration: 用于定义一个配置类 * @EnableAutoConfiguration :Spring Boot会自动根据你jar包的依赖来自动配置项目。 * @ComponentScan: 告诉Spring 哪个packages 的用注解标识的类 会被spring自动扫描并且装入bean容器 * @ServletComponentScan 开启过滤器扫描 过滤器注解配置方式需要开启该注解 * @EnableTransactionManagement 开启注解事务管理,等同于xml配置方式的 <tx:annotation-driven /> * @MapperScan 指定mapper的路径,如果不设置,需要每个mapper上面添加@mapper注解 */ @SpringBootApplication @ServletComponentScan @EnableTransactionManagement @MapperScan("com.zjh.zxw.dao.mapper") public class SpringbootApplication { public static void main(String[] args) { SpringApplication.run(SpringbootApplication.class, args); } }
5、配置MvcConfigurer(处理静态资源访问以及乱码问题)
在com.zjh.zxw.manager中创建MvcConfigurer
/** * <p>项目名称:zxw-admin * <p>Package名称:com.zjh.zxw.manager * 文件名称:MvcConfigurer.java * 版本:1.00 * 创建日期:2020年1月20日 * */ package com.zjh.zxw.manager; import java.nio.charset.Charset; import java.util.List; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; /** *<p>类说明:MVC配置类 *@author:zhengjianhua *@version 1.00 * */ @Configuration public class MvcConfigurer extends WebMvcConfigurationSupport{ /** * 上传路径 比如J:\\zxwUpload\\ */ @Value("${com.zjh.uploadPath}") private String uploadPath; @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { //静态资源访问路径配置 registry.addResourceHandler("/**").addResourceLocations("classpath:/static/"); //本地资源访问路径配置 registry.addResourceHandler("/uploadPath/**").addResourceLocations("file:"+uploadPath); } /** * 编码设置 * (non-Javadoc) * @see org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#extendMessageConverters(java.util.List) */ @Override protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) { converters.forEach(converter -> { if (converter instanceof StringHttpMessageConverter){ ((StringHttpMessageConverter) converter).setDefaultCharset(Charset.forName("UTF-8")); } }); } }
6、静态资源文件(html,css,js,图片等)
在zxw-admin工程中,将原webapp目录下的静态资源文件,拷贝到resources/static目录下
在zxw-service工程中,将原src/main/java目录下的sqlmap文件,拷贝到resources/sqlmap目录下
7、filter配置(登录session验证)
在com.zjh.zxw.manager.filter下创建LoginFilter类
仅过滤html文件和.do请求,排除登录、验证码等请求地址
/* * Copyright (c) 2017-2020 Founder. All Rights Reserved. * * This software is the confidential and proprietary information of * Founder. You shall not disclose such Confidential Information * and shall use it only in accordance with the terms of the agreements * you entered into with Founder. * */ package com.zjh.zxw.manager.filter; import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.springframework.core.annotation.Order; import com.zjh.zxw.domain.entity.AdminUser; @Order(1) @WebFilter(filterName = "loginFilter",urlPatterns ={"*.html","*.do"} ) public class LoginFilter implements Filter{ private FilterConfig _filterConfig; /** * 登录地址 */ private String _loginUrl="/module/login/login.html"; /** * 允许访问地址 */ private static final Set<String> ALLOWED_PATHS = Collections.unmodifiableSet(new HashSet<>( Arrays.asList("/login/getVerifyCode.do", "/login/loginUser.do", "/login/logout.do","/module/login/login.html"))); @Override public void destroy() { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { if (!(req instanceof HttpServletRequest)) { throw new IllegalArgumentException ("Request is not an HttpServletRequest: " + req); } HttpServletRequest httpReq = (HttpServletRequest) req; HttpServletResponse httpRes = (HttpServletResponse) res; httpReq.setCharacterEncoding ("utf-8"); httpRes.setCharacterEncoding ("utf-8"); // 访问路径 String requestURI = httpReq.getRequestURI (); StringBuffer sb = new StringBuffer (); sb.append ("http://").append (httpReq.getServerName ()).append (":").append (httpReq.getServerPort ()) .append (httpReq.getContextPath ()); //若存在会话则返回该会话,否则返回NULL HttpSession httpSession = httpReq.getSession (false); //判断是否允许访问 boolean allowedPath = ALLOWED_PATHS.contains(requestURI); //判断是否存在会话 if(httpSession==null){ if(allowedPath){ chain.doFilter(httpReq, httpRes); return; }else{ //跳转到登陆界面 sb.append(_loginUrl); String url=sb.toString(); httpRes.sendRedirect(url); return; } }else{ //查询session中的用户 AdminUser adminUser=(AdminUser)httpSession.getAttribute("adminUser"); if(adminUser!=null){ //存在则直接跳转 chain.doFilter(httpReq, httpRes); return; }else{ if(allowedPath){ chain.doFilter(httpReq, httpRes); return; }else{ //跳转到登陆界面 sb.append(_loginUrl); String url=sb.toString(); httpRes.sendRedirect(url); return; } } } } @Override public void init(FilterConfig filterConfig) throws ServletException { _filterConfig =filterConfig; } }
8、junit单页测试
如果注解导入失败,可能是pom依赖没引入进来,在zxw-admin的pom.xml中再次添加
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
/* * Copyright (c) 2017-2020 Founder. All Rights Reserved. * * This software is the confidential and proprietary information of * Founder. You shall not disclose such Confidential Information * and shall use it only in accordance with the terms of the agreements * you entered into with Founder. * */ package com.zjh.zxw.test; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import com.zjh.zxw.domain.entity.AdminUser; import com.zjh.zxw.service.IAdminUserService; /** * 后台用户管理服务测试 * @author zhengjianhua * 2017年11月6日 上午10:19:53 */ @RunWith(SpringRunner.class) @SpringBootTest public class AdminUserTest { @Autowired private IAdminUserService _adminUserService; @Test public void findAdminUser(){ AdminUser adminUser =new AdminUser(); adminUser.setUserName("admin"); List<AdminUser> adminUsers=_adminUserService.findAdminUserByPage(adminUser, 0, 2); System.out.println(adminUsers); AdminUser adminUser1=_adminUserService.findAdminUserByUserName("admin"); System.out.println(adminUser1); //int count=_adminUserService.findAdminUserByPageCount(adminUser); //System.out.println(count); } @Test public void insertAdminUser(){ /* AdminUser adminUser =new AdminUser(); adminUser.setUserName("15116470634"); adminUser.setPassWord("123456"); adminUser.setUserStatus("1"); Boolean flag=_adminUserService.insertAdminUser(adminUser); System.out.println(flag);*/ } }
运行结果
9、工程运行测试
右键Run as Java Application,启动成功
访问localhost:9999/module/index/index.html 未登录,成功跳转login登录界面
页面正常显示,静态资源配置生效,验证码正常显示,本地资源访问配置生效
输入密码,登录成功,跳转index主页
选择用户管理模块,数据查询正常
初步改造就完成了
三、改造问题汇总
改造过程中问题汇总
1、添加spring boot依赖,在服务应用的pom文件中,无法添加两个parent标签,如何引入spring boot的jar包呢?
答:可以在主pom中添加。
2、静态资源配置,使用java类(MvcConfigurer)+注解方式配置,增加addResourceHandlers配置后,resources目录下的静态html文件无法访问?
答:检查一下应用的pom文件中是否设置了resources标签,需要将其注释掉才能访问静态资源文件。详情
3、应用请求返回错误信息是乱码怎么办?
答:在MvcConfigurer中添加extendMessageConverters方法,配置/**通配符转换 详情
4、本地图片文件如何访问
答:在MvcConfigurer中添加extendMessageConverters方法,配置/uploadPath/**通配符转换 详情
5、使用注解方式设置过滤器不生效怎么办?、
答:检查启动类是否添加了@ServletComponentScan注解
6、使用注解方式设置过滤器,如何设置多个通配符
答:使用大括号,urlPatterns ={"*.html","*.do"}
7、mybatis查询数据返回为null,但是查询数据库数据存在
答:1)sql查询字段需要与实体类的属性名称一致。2)配置文件中添加mybatis.configuration.map-underscore-to-camel-case=true 支持驼峰命名
发表评论