工具idea , 模块化项目搭建
1:先创建一个project 删掉其中的src等多余目录 ,留一个 pom.xml
pom.xml 如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.text</groupId>
<artifactId>demo</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 定义版本-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
</parent>
</project>
2:右键项目,创建一个module 项目 【demoAdmin】 , 注:创建项目后,外层pom会多个 modules
此模块 pom.xml 如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>demo</artifactId>
<groupId>com.text</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>demoAdmin</artifactId>
<dependencies>
<!-- 支持web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--get set data 等插件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--mybatis-plus 核心包 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.0.5</version>
</dependency>
<!-- mybatis-plus velocity 模板引擎, 默认-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
<!-- 连接池 6以上版本在连接属性中要加上[ &serverTimezone=Asia/Shanghai ] 6.0 版本以上必须配置此参数-->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.0.4.RELEASE</version>
</dependency>
<!-- swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<!-- 自定义jar ,名字随便起,尽量统一规范(此处防止打包时,打不进去第三方jar)-->
<!-- <dependency>
<groupId>custom</groupId>
<artifactId>customSelf</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/lib/custom-3.3.1.jar</systemPath>
</dependency>-->
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource> <!-- 将jar统一打进lib目录下 -->
<directory>src/main/resources/lib</directory>
<targetPath>BOOT-INF/lib</targetPath>
</resource>
</resources>
<!-- 配置打包及打包后的项目存放路径 outputDirectory -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<finalName>${project.name}</finalName>
<jvmArguments>-Dfile.encoding=UTF-8</jvmArguments>
<outputDirectory>E:/compose/demoJar</outputDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project>
3:代码写法 项目结构如下图:
包文件解释:
common: 公共类配置
config: 配置文件
config.interceptor: 拦截器配置
controller: 控制器
dao: dao层
model.dto: 入参类
model.entity: 实体类
model.vo : 出参类
service : 接口类
service.impl: 接口实现类
shiro: 权限类
util: 工具类
AdminApplication.class : 启动入口
3-1:resources 配置
application.yml 如下图:
# 服务器配置 以自己的配置为主
server:
port: 8070
servlet:
context-path: /admin
mybatis-plus:
mapper-locations: classpath:/mapper/*.xml
type-aliases-package: com.demo.model.entity
logging:
config: classpath:logback-spring.xml
spring:
profiles:
#active: main # 正式环境
active: demo #测试环境
application-demo.yml 如下图:
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
hikari:
maximum-pool-size: 15
max-lifetime: 180000
idle-timeout: 60000
connection-timeout: 20000
minimum-idle: 5
redis:
port: 6379
host: 127.0.0.1
password:123456
banner.txt 如下图:
${AnsiColor.BRIGHT_YELLOW}
// _ooOoo_ //
// o8888888o //
// 88" . "88 //
// (| ^_^ |) //
// O\ = /O //
// ____/`---'\____ //
// .' \\| |// `. //
// / \\||| : |||// \ //
// / _||||| -:- |||||- \ //
// | | \\\ - /// | | //
// | \_| ''\---/'' | | //
// \ .-\__ `-` ___/-. / //
// ___`. .' /--.--\ `. . ___ //
// ."" '< `.___\_<|>_/___.' >'"". //
// | | : `- \`.;`\ _ /`;.`/ - ` : | | //
// \ \ `-. \_ __\ /__ _/ .-` / / //
// ========`-.____`-.___\_____/___.-`____.-'======== //
// `=---=' //
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
// 佛祖保佑 Admin 永不宕机 永无BUG //
${AnsiColor.BRIGHT_RED}
Application Version: ${application.version}${application.formatted-version}
Spring Boot Version: ${spring-boot.version}${spring-boot.formatted-version}
logback-spring.xml 如下图:
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="false">
<springProperty scop="context" name="spring.application.name" source="spring.application.name" defaultValue="home"/>
<property name="LOG_HOME" value="/home/demo/logs/admin" />
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%yellow(%d{yyyy-MM-dd HH:mm:ss}) [%-5level] [ %boldMagenta(%logger{50}) ] - %cyan(%msg%n)
</pattern>
</encoder>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/admin.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<fileNamePattern>${LOG_HOME}/admin.log.%d{yyyy-MM-dd}.part%i.gz</fileNamePattern>
<!-- 同时按照大小和日期分割日志文件 -->
<maxFileSize>2GB</maxFileSize>
<maxHistory>10</maxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<logger name="com.demo.dao" level="DEBUG" additivity="false">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
</logger>
<!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 -->
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE"/>
</root>
</configuration>
3-2 common 包结构class如下图:
类文件解释:
ApiCommonController: 自定义父类 ,封装了自定义异常监控
BaseController: 自定义父类 ,封装了返回结果对象,获取ip
BaseDto: 分页类,用于传参对象继承使用
BusinessException: 自定义异常
CodeGeneration: mybatisPlus 代码生成器
Result: 返回结果对象
ApiCommonController.java 代码如下
package com.demo.common;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@Slf4j
public class ApiCommonController extends BaseController {
/**
* 抛出自定义BusinessException异常
*/
@ExceptionHandler({BusinessException.class})
@ResponseBody
public Result business(BusinessException ex) {
log.info(ex.toString());
return new Result(Result.ERROR,ex.getMessage());
}
protected void check(String code ,Object obj){
if (obj==null||obj.toString().trim().equals("null")||obj.toString().trim().length()==0) {
throw new BusinessException("参数[" +code+ "]不能为空");
}
}
}
BaseController.java 如下图:
package com.demo.common;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
@Slf4j
public class BaseController {
@Autowired
protected HttpServletRequest request;
/**
* 返回成功结果集
*/
protected Result ajaxDoneSuccess(Object data) {
return new Result(Result.SUCCESS, Result.SUCCESSMSG, data);
}
protected Result ajaxDoneSuccess(Object data,Integer total) {
return new Result(Result.SUCCESS, Result.SUCCESSMSG, data,total);
}
/**
* 返回成功结果
*/
protected Result ajaxDoneSuccess(String message) {
return new Result(Result.SUCCESS, message);
}
/**
* 返回成功结果和对象
*/
protected Result ajaxDoneSuccess(String message,Object data) {
return new Result(Result.SUCCESS, message,data);
}
/**
* 返回失败结果集
*/
protected Result ajaxDoneError(String message) {
return new Result(Result.ERROR, message);
}
/**
* 获取ip
*/
protected String getRealIp(){
String ip = request.getHeader("X-Real-IP");
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("x-forwarded-for");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}
BaseDto.java 代码如下图:
package com.demo.common;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class BaseDto {
@ApiModelProperty(value = "当前第几页")
private Integer pageIndex = 1;//当前第几页
@ApiModelProperty(value = "每页显示数")
private Integer pageSize = 10; //每页显示数
@ApiModelProperty(value = "开始时间 -查询")
private String beginTime;
@ApiModelProperty(value = "结束时间 -查询")
private String endTime;//结束时间 -查询
}
BusinessException.java 如下图:
package com.demo.common;
/**
* 自定义异常
*/
public class BusinessException extends RuntimeException {
public BusinessException(String msg){
super(msg);
}
}
Result.java 如下图:
package com.demo.common;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class Result {
public static final int SUCCESS = 200;
public static final int ERROR= 500;
public static final String SUCCESSMSG = "成功";
@ApiModelProperty(value = "状态码 200")
private int code = 0;
@ApiModelProperty(value = "说明信息")
private String msg = "";
@ApiModelProperty(value = "数据")
private Object data;
@ApiModelProperty(value = "数据总条数")
private Integer total=0; //条数
public Result(int code,String msg){
this.code=code;
this.msg=msg;
}
public Result(int code,String msg,Object data){
this.code=code;
this.msg=msg;
this.data=data;
}
public Result(int code,String msg,Object data ,Integer total){
this.code=code;
this.msg=msg;
this.data=data;
this.total=total;
}
}
CodeGeneration.java 代码生成器 如下图:
package com.demo.common;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
public class CodeGeneration {
/**
*
* @Title: main
* @Description: 文件生成器 运行main方法即可
* @param args
*/
public static void main(String[] args) {
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
gc.setOutputDir("E://generation//temp");
gc.setFileOverride(true);
gc.setActiveRecord(false);// 不需要ActiveRecord特性的请改为false
gc.setEnableCache(false);// XML 二级缓存
gc.setBaseResultMap(true);// XML ResultMap
gc.setBaseColumnList(false);// XML columList
gc.setAuthor("ccm");// 作者
// 自定义文件命名,注意 %s 会自动填充表实体属性!
//gc.setControllerName("%sAction");
gc.setServiceName("%sService");
gc.setServiceImplName("%sServiceImpl");
gc.setMapperName("%sDao");
gc.setXmlName("%sMapper");
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("root");
dsc.setUrl("jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf-8");
mpg.setDataSource(dsc);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
//strategy.setTablePrefix(new String[] { "sys_" });// 此处可以修改为您的表前缀
strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
//strategy.setInclude(new String[] { "sys_user" }); // 需要生成的表
strategy.setSuperServiceClass(null);
strategy.setSuperServiceImplClass(null);
strategy.setSuperMapperClass(null);
mpg.setStrategy(strategy);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setParent("com.demo");
//pc.setController("controller");
pc.setService("service");
pc.setServiceImpl("service.serviceImpl");
pc.setMapper("dao");
pc.setEntity("model.entity");
pc.setXml("xml");
mpg.setPackageInfo(pc);
// 执行生成
mpg.execute();
}
}
3-3 config 包结构class如下图:
类文件解释:
HandlerInterceptorConfig: 拦截器
MyHandlerInterceptorConfig: 自定义拦截
corsFilter: 跨域
MybatisPlusConfig: MybatisPlus配置
RedisConfig: Redis配置
SwaggerConfig: Swagger2配置
HandlerInterceptorConfig.java 代码如下:
package com.demo.config.interceptor;
import com.demo.common.BusinessException;
import com.demo.config.RedisConfig;
import com.demo.shiro.ShiroAdmin;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
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;
import java.util.concurrent.TimeUnit;
@Slf4j
@Component
public class HandlerInterceptorConfig implements HandlerInterceptor {
@Autowired
private RedisTemplate redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
HttpSession session= request.getSession();
String keyName=RedisConfig.reids_prefix+session.getId();
ShiroAdmin shiroAdmin= (ShiroAdmin) redisTemplate.opsForValue().get(keyName);
if (shiroAdmin==null){
throw new BusinessException("当前账号未登录,请先登陆");
}
String token = request.getHeader("token");
if (token == null || token.trim().length() == 0) {
throw new BusinessException("token 禁止为空");
}
if (!shiroAdmin.getToken().equals(token)) {
throw new BusinessException("账号在其他地方登录,请重新登录");
}
shiroAdmin.setSessionId(" 被拦截 当前会话:"+session.getId());
request.getSession().setAttribute("shiroAdmin",shiroAdmin);
redisTemplate.expire(keyName,2,TimeUnit.HOURS);
return true;
}
}
CorsConfig.java 代码如下:
package com.demo.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 跨域配置
*/
@Configuration
public class CorsConfig {
// CORS
@Bean
FilterRegistrationBean corsFilter(@Value("*") String origin) {
return new FilterRegistrationBean(new Filter() {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String method = request.getMethod();
response.setHeader("Access-Control-Allow-Origin", request.getHeader("origin"));
response.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,DELETE");
response.setHeader("Access-Control-Max-Age", Long.toString(60 * 60));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", "token,Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization");
if ("OPTIONS".equals(method)) {
response.setStatus(HttpStatus.OK.value());
} else {
chain.doFilter(req, res);
}
}
public void init(FilterConfig filterConfig) {
}
public void destroy() {
}
});
}
}
MyHandlerInterceptorConfig.java 代码如下:
package com.demo.config.interceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyHandlerInterceptorConfig implements WebMvcConfigurer {
@Autowired
private HandlerInterceptor handlerInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(handlerInterceptor).addPathPatterns("/**")
.excludePathPatterns("/login/**")
.excludePathPatterns("/*.html")
.excludePathPatterns("/webjars/**")
.excludePathPatterns("//swagger-resources/**");
}
}
MybatisPlusConfig.java 代码如下:
package com.demo.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan({"com.demo.dao"})
public class MybatisPlusConfig {
/**
* 性能优化 复杂查询可能会报错 建议关掉
* @return
*/
@Bean
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
/*<!-- SQL 执行性能分析,开发环境使用,线上不推荐。 maxTime 指的是 sql 最大执行时长 -->*/
performanceInterceptor.setMaxTime(1000);
/*<!--SQL是否格式化 默认false-->*/
performanceInterceptor.setFormat(false);
return performanceInterceptor;
}
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
RedisConfig.java 代码如下 :
package com.demo.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
public final static String reids_prefix="demo_admin_" ; //redis前缀
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
ObjectMapper mapper = new ObjectMapper();
template.setConnectionFactory(connectionFactory);
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(mapper);
template.setValueSerializer(serializer);
//使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
}
SwaggerConfig.java 代码如下
package com.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
@EnableSwagger2
@Configuration
public class SwaggerConfig {
@Bean
public Docket createRestApi(){
ParameterBuilder ticketPar = new ParameterBuilder();
List<Parameter> pars = new ArrayList<Parameter>();
ticketPar.name("token").description("登录校验token")//name表示对象名称,description表示描述
.modelRef(new ModelRef("string")).parameterType("header")
.required(false).build();//required表示是否必填,defaultvalue表示默认值
pars.add(ticketPar.build());//添加完此处一定要把下边的带***的也加上否则不生效
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.demo.controller"))
.paths(PathSelectors.any())
.build()
.globalOperationParameters(pars);//************把消息头添加
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("测试接口")
.description("admin端接口")
.termsOfServiceUrl("none")
.version("1.0").build();
}
}
3-4 shiro包结构class如下图:
ShiroAdmin.java 封装对象 代码如下:
package com.demo.shiro;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 登陆对象
*/
@Data
public class ShiroAdmin {
@ApiModelProperty(value = "管理员id")
private Integer adminId;
@ApiModelProperty(value = "token")
private String token;
@ApiModelProperty(value = "登陆id")
private String loginCode;
@ApiModelProperty(value = "权限id")
private Integer roleId;
@ApiModelProperty(value = "手机号")
private String phone;
@ApiModelProperty(value = "会话id")
private String sessionId;
}
AuthManager.java 获取当前登陆的对象
package com.demo.shiro;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
public class AuthManager {
public static ShiroAdmin getShiroAdmin() {
return (ShiroAdmin)getSession().getAttribute("shiroAdmin");
}
public static String getSessionId(){
return getSession().getId();
}
public static HttpSession getSession(){
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
return request.getSession();
}
}
3-5 : 控制器 LoginController.java 代码如下s
package com.demo.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.demo.common.ApiCommonController;
import com.demo.common.Result;
import com.demo.config.RedisConfig;
import com.demo.model.dto.LoginDto;
import com.demo.model.entity.TSysAdmin;
import com.demo.service.TSysAdminService;
import com.demo.shiro.AuthManager;
import com.demo.shiro.ShiroAdmin;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
@RestController
@RequestMapping("/login")
@Api(description = "登陆注册")
public class LoginController extends ApiCommonController {
@Autowired
private TSysAdminService tSysAdminService;
@Autowired
private RedisTemplate redisTemplate;
@ApiOperation(value = "登陆", response = String.class)
@PostMapping("/loginDo")
public Result loginDo(@RequestBody LoginDto dto){
if (AuthManager.getSessionId()==null){
return ajaxDoneError("登陆异常,错误代码-10000");
}
TSysAdmin tSystemAdmin=tSysAdminService.getOne(new QueryWrapper<TSysAdmin>().eq("login_code",dto.getLoginCode()).eq("pwd",dto.getPwd()));
if (tSystemAdmin==null){
return ajaxDoneError("账号或密码有误");
}
System.out.println("--------------------------------------");
ShiroAdmin shiroAdmin=new ShiroAdmin();
shiroAdmin.setAdminId(tSystemAdmin.getId());
shiroAdmin.setLoginCode(tSystemAdmin.getLoginCode());
shiroAdmin.setPhone(tSystemAdmin.getPhone());
shiroAdmin.setRoleId(tSystemAdmin.getRoleId());
shiroAdmin.setSessionId(AuthManager.getSessionId());
shiroAdmin.setToken(RandomStringUtils.randomAlphanumeric(24)+tSystemAdmin.getId());
String keyName=RedisConfig.reids_prefix+shiroAdmin.getSessionId();
redisTemplate.opsForValue().set(keyName,shiroAdmin,2,TimeUnit.HOURS);
return ajaxDoneSuccess("登陆成功 good",shiroAdmin.getToken());
}
}
3-6 : 入口类 AdminApplication.java
package com.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EnableTransactionManagement //开启事务
@ComponentScan(basePackages = {"com.demo.*"})
public class AdminApplication {
public static void main(String[] args) {
SpringApplication.run(AdminApplication.class,args);
}
}
4: 项目配置完成 项目完整接口入下图:
**
项目demo地址:https://download.csdn.net/download/qq_24232123/10802950
下载后 1:将CodeGeneration.java文件中的数据库连接改成实际的
2:将配置文件中的数据库,redis 改成实际的