前言
近期想自己做个项目,仿发卡网的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 支持驼峰命名




















发表评论