Commit f224b1bd authored by liqin's avatar liqin 💬

Initial commit

parents
Pipeline #255 failed with stages
*.class
bin
# Package Files #
*.jar
*.war
*.ear
# ignore Maven generated target folders
target
# ignore eclipse files
.project
.classpath
.settings
.metadata
# idea files
.idea
*.iml
# visual studio code
.vscode
# macOS files
.DS_Store
# IDE support files
/.classpath
/.launch
/.project
/.settings
/*.launch
/*.tmproj
/ivy*
/eclipse
# ignore Maven generated target folders
target/
out/
build/
bin/
## .gitignore for eclipse
*.pydevproject
bin/**
tmp/**
tmp/**/*
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
# logs
/stacktrace.log
/test/reports
/logs
*.log
*.log.*
/.apt_generated/
.idea/
/target/
This diff is collapsed.
package cn.wisenergy.chnmuseum.party;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
package cn.wisenergy.chnmuseum.party.auth;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.xml.bind.DatatypeConverter;
/**
* Provides a SHA-256 based implementation of the password encryption
* functionality.
*
* @author James Muehlner
*/
public class SHA256PasswordEncryptionService {
public static byte[] createPasswordHash(String password, byte[] salt) {
try {
// Build salted password, if a salt was provided
StringBuilder builder = new StringBuilder();
builder.append(password);
if (salt != null)
builder.append(DatatypeConverter.printHexBinary(salt));
// Hash UTF-8 bytes of possibly-salted password
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(builder.toString().getBytes("UTF-8"));
return md.digest();
}
// Throw hard errors if standard pieces of Java are missing
catch (UnsupportedEncodingException e) {
throw new UnsupportedOperationException("Unexpected lack of UTF-8 support.", e);
} catch (NoSuchAlgorithmException e) {
throw new UnsupportedOperationException("Unexpected lack of SHA-256 support.", e);
}
}
}
package cn.wisenergy.chnmuseum.party.auth;
import java.security.SecureRandom;
public class SecureRandomSaltService {
/**
* Instance of SecureRandom for generating the salt.
*/
private static SecureRandom secureRandom = new SecureRandom();
public static byte[] generateSalt() {
byte[] salt = new byte[32];
secureRandom.nextBytes(salt);
return salt;
}
}
package cn.wisenergy.chnmuseum.party.auth;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import cn.wisenergy.chnmuseum.party.model.PermissionInit;
import cn.wisenergy.chnmuseum.party.service.PermissionInitService;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 热加载链接权限
*/
@Service
public class ShiroService {
@Autowired
private ShiroFilterFactoryBean shiroFilterFactoryBean;
@Autowired
private PermissionInitService permissionInitService;
/**
* 初始化权限
*/
public Map<String, String> loadFilterChainDefinitions() {
// 权限控制map.从数据库获取
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
List<PermissionInit> list = this.permissionInitService.selectAll();
for (PermissionInit permissionInit : list) {
filterChainDefinitionMap.put(permissionInit.getUrl(), permissionInit.getPermissionInit());
}
return filterChainDefinitionMap;
}
/**
* 重新加载权限
*/
public void updatePermission() {
synchronized (shiroFilterFactoryBean) {
AbstractShiroFilter shiroFilter;
try {
shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean.getObject();
} catch (Exception e) {
throw new RuntimeException("get ShiroFilter from shiroFilterFactoryBean error!");
}
PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter
.getFilterChainResolver();
DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver.getFilterChainManager();
// 清空老的权限控制
manager.getFilterChains().clear();
shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();
shiroFilterFactoryBean.setFilterChainDefinitionMap(loadFilterChainDefinitions());
// 重新构建生成
Map<String, String> chains = shiroFilterFactoryBean.getFilterChainDefinitionMap();
for (Map.Entry<String, String> entry : chains.entrySet()) {
String url = entry.getKey();
String chainDefinition = entry.getValue().trim().replace(" ", "");
manager.createChain(url, chainDefinition);
}
System.out.println("更新权限成功!!");
}
}
}
package cn.wisenergy.chnmuseum.party.auth.filter;
import cn.wisenergy.chnmuseum.party.auth.token.JwtToken;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 执行流程preHandle->isAccessAllowed->isLoginAttempt->executeLogin
*/
public class JwtFilter extends BasicHttpAuthenticationFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(JwtFilter.class);
/**
* 判断用户是否想要登入。
* 检测header里面是否包含Authorization字段即可
*/
@Override
protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
HttpServletRequest req = (HttpServletRequest) request;
String authorization = req.getHeader("Authorization");
return authorization != null;
}
/**
*
*/
@Override
protected boolean executeLogin(ServletRequest servletRequest, ServletResponse servletResponse) {
HttpServletRequest request = (HttpServletRequest) servletRequest;
String authorization = request.getHeader("Authorization");
if (StringUtils.isNotBlank(authorization)) {
if (authorization.startsWith("Bearer ")) {
authorization = authorization.substring(7);
}
}
JwtToken token = new JwtToken(authorization);
// 提交给realm进行登入,如果错误他会抛出异常并被捕获
getSubject(servletRequest, servletResponse).login(token);
// 如果没有抛出异常则代表登入成功,返回true
return true;
}
/**
* 这里我们详细说明下为什么最终返回的都是true,即允许访问
* 例如我们提供一个地址 GET /article
* 登入用户和游客看到的内容是不同的
* 如果在这里返回了false,请求会被直接拦截,用户看不到任何东西
* 所以我们在这里返回true,Controller中可以通过 subject.isAuthenticated() 来判断用户是否登入
* 如果有些资源只有登入用户才能访问,我们只需要在方法上面加上 @RequiresAuthentication 注解即可
* 但是这样做有一个缺点,就是不能够对GET,POST等请求进行分别过滤鉴权(因为我们重写了官方的方法),但实际上对应用影响不大
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
if (isLoginAttempt(request, response)) {
//if (!isLoginAttempt(request, response) || !executeLogin(request,response)) {
try {
executeLogin(request, response);
} catch (UnauthorizedException | AuthenticationException e) {
return false;
}
}
return true;
}
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
//这里是个坑,如果不设置的接受的访问源,那么前端都会报跨域错误,因为这里还没到corsConfig里面
httpServletResponse.setHeader("Access-Control-Allow-Origin", ((HttpServletRequest) request).getHeader("Origin"));
httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
response401(request, response);
return false;
}
/**
* 将非法请求返回401
*/
private void response401(ServletRequest req, ServletResponse resp) {
try {
HttpServletResponse response = (HttpServletResponse) resp;
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=utf-8");
response.setStatus(401);
response.getWriter().write("{\"status\":401,\"message\":\"未登录!\"}");
} catch (IOException e) {
LOGGER.error(e.getMessage());
}
}
/**
* 将非法请求返回401
*/
private void response403(ServletRequest req, ServletResponse resp) {
try {
HttpServletResponse response = (HttpServletResponse) resp;
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=utf-8");
response.setStatus(403);
response.getWriter().write("{\"status\":403,\"message\":Unauthorized!}");
} catch (IOException e) {
LOGGER.error(e.getMessage());
}
}
}
package cn.wisenergy.chnmuseum.party.auth.filter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
public class MyFormAuthenticationFilter extends FormAuthenticationFilter {
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
if (isLoginRequest(request, response)) {
if (isLoginSubmission(request, response)) {
Subject subject = this.getSubject(request, response);
subject.logout();
}
}
return super.isAccessAllowed(request, response, mappedValue);
}
}
\ No newline at end of file
package cn.wisenergy.chnmuseum.party.auth.realm;
import cn.wisenergy.chnmuseum.party.auth.util.JwtTokenUtil;
import cn.wisenergy.chnmuseum.party.model.*;
import cn.wisenergy.chnmuseum.party.service.PermissionService;
import cn.wisenergy.chnmuseum.party.service.RolePermissionService;
import cn.wisenergy.chnmuseum.party.service.RoleService;
import cn.wisenergy.chnmuseum.party.service.impl.EmployeeRoleServiceImpl;
import cn.wisenergy.chnmuseum.party.service.impl.EmployeeServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import cn.wisenergy.chnmuseum.party.auth.token.JwtToken;
import com.cmbchina.business.hall.model.*;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import javax.annotation.Resource;
import java.util.*;
/**
* 身份校验核心类
*/
public class MyShiroRealm extends AuthorizingRealm {
private static final Logger LOGGER = LoggerFactory.getLogger(MyShiroRealm.class);
private static final String SHIRO_JWT_TOKEN = "shiro:jwt:token";
//用户登录次数计数 redisKey 前缀
private String SHIRO_LOGIN_COUNT = "shiro_login_count_";
//用户登录是否被锁定 一小时 redisKey 前缀
private String SHIRO_IS_LOCK = "shiro_is_lock_";
@Resource
private PermissionService permissionService;
@Resource
private RoleService roleService;
@Resource
private EmployeeServiceImpl employeeService;
@Resource
private EmployeeRoleServiceImpl employeeRoleService;
@Resource
private RolePermissionService rolePermissionService;
@Resource
private StringRedisTemplate stringRedisTemplate;
/**
* 必须重写此方法,不然Shiro会报错
*/
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof JwtToken;
}
/**
* 认证信息.(身份验证) : Authentication 是用来验证用户身份
*
* @param auth
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
String token = (String) auth.getCredentials();
Boolean hasToken = stringRedisTemplate.hasKey(SHIRO_JWT_TOKEN + token);
if (hasToken == null || !hasToken) {
throw new AuthenticationException("用户未登录!");
}
LOGGER.info("MyShiroRealm doGetAuthenticationInfo().token=" + token);
String username = JwtTokenUtil.getUsername(token);
if (username == null) {
throw new AuthenticationException("token invalid");
}
LOGGER.info("MyShiroRealm doGetAuthenticationInfo().username=" + username);
// 通过username从数据库中查找
// 实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法
String employeeId = JwtTokenUtil.getEmployeeId(token);
Employee employee = this.employeeService.selectByEmpId(employeeId);
if (employee == null) {
throw new AuthenticationException("User does not exist!");
}
if (JwtTokenUtil.verify(token, username) == null) {
throw new AuthenticationException("token invalid");
}
return new SimpleAuthenticationInfo(new Employee(token), token, getName());
}
/**
* 授权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("权限认证方法:MyShiroRealm.doGetAuthorizationInfo()");
Employee employee = (Employee) principals.getPrimaryPrincipal();
Boolean hasToken = stringRedisTemplate.hasKey(SHIRO_JWT_TOKEN + employee.getJwtToken());
if (hasToken == null || !hasToken) {
throw new AuthenticationException("token invalid!");
}
String employeeId = JwtTokenUtil.getEmployeeId(employee.getJwtToken());
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 根据用户ID查询角色(role),放入到Authorization里。
Map<String, Object> map = new HashMap<>();
map.put("employee_id", employeeId);
List<EmployeeRole> employeeRoleList = this.employeeRoleService.listByMap(map);
List<String> ridList = new LinkedList<>();
for (EmployeeRole employeeRole : employeeRoleList) {
ridList.add(employeeRole.getRoleId());
}
List<Role> roleList = this.roleService.listByIds(ridList);
Set<String> roleSet = new HashSet<>();
for (Role role : roleList) {
roleSet.add(role.getAlias());
}
info.setRoles(roleSet);
// 根据用户ID查询权限(permission)放入到Authorization里。
QueryWrapper<RolePermission> wrapper = new QueryWrapper<>();
wrapper.in("rid", ridList).select("pid");
List<Object> permissionIdList = this.rolePermissionService.listObjs(wrapper);
List<Permission> permissionList = new ArrayList<>();
if (permissionIdList.size() > 0) {
QueryWrapper<Permission> ew = new QueryWrapper<>();
ew.in("id", permissionIdList);
permissionList = this.permissionService.list(ew);
}
Set<String> permissionSet = new HashSet<>();
for (Permission permission : permissionList) {
permissionSet.add(permission.getUrl());
}
info.setStringPermissions(permissionSet);
return info;
}
public void clearCachedAuthenticationInfo(String token) {
SimplePrincipalCollection principals = new SimplePrincipalCollection(new Employee(token), getName());
clearCachedAuthenticationInfo(principals);
}
@Override
public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
super.clearCachedAuthorizationInfo(principals);
}
@Override
public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
super.clearCachedAuthenticationInfo(principals);
}
@Override
public void clearCache(PrincipalCollection principals) {
super.clearCache(principals);
}
private void clearAllCachedAuthorizationInfo() {
getAuthorizationCache().clear();
}
private void clearAllCachedAuthenticationInfo() {
getAuthenticationCache().clear();
}
public void clearAllCache() {
clearAllCachedAuthenticationInfo();
clearAllCachedAuthorizationInfo();
}
}
package cn.wisenergy.chnmuseum.party.auth.resolver;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
System.out.println("==============异常开始=============");
System.out.println(ex.getMessage());
// 如果是shiro无权操作,因为shiro 在操作auno等一部分不进行转发至无权限url
if (ex instanceof UnauthorizedException) {
System.out.println("==============超时未登录=============");
return new ModelAndView("login");
}
if (ex instanceof AuthorizationException) {
System.out.println("==============无权限=============");
}
System.out.println("==============异常结束=============");
return null;
}
}
package cn.wisenergy.chnmuseum.party.auth.token;
import org.apache.shiro.authc.AuthenticationToken;
public class JwtToken implements AuthenticationToken {
private static final long serialVersionUID = 1L;
// 密钥
private String token;
public JwtToken(String token) {
this.token = token;
}
@Override
public Object getPrincipal() {
return token;
}
@Override
public Object getCredentials() {
return token;
}
}
package cn.wisenergy.chnmuseum.party.auth.util;
import cn.wisenergy.chnmuseum.party.common.util.DateUtil80;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.time.LocalDateTime;
@Component
public class JwtTokenUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(JwtTokenUtil.class);
private static String jwtTokenSecret;
private static String jwtTokenIssuer;
private static String jwtTokenExpiration;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Value("${jwt.secret}")
public void setJwtTokenSecret(String jwtTokenSecret) {
JwtTokenUtil.jwtTokenSecret = jwtTokenSecret;
}
@Value("${jwt.issuer}")
public void setJwtTokenIssuer(String jwtTokenIssuer) {
JwtTokenUtil.jwtTokenIssuer = jwtTokenIssuer;
}
@Value("${jwt.expiration}")
public void setJwtTokenExpiration(String jwtTokenExpiration) {
JwtTokenUtil.jwtTokenExpiration = jwtTokenExpiration;
}
/**
* 校验token是否正确
*
* @param token 密钥
* @return 是否正确
*/
public static String verify(String token, String username) {
try {
Algorithm algorithm = Algorithm.HMAC512(jwtTokenSecret);
JWTVerifier verifier = JWT.require(algorithm).withIssuer(jwtTokenIssuer).withSubject(username).build();
DecodedJWT jwt = verifier.verify(token);
return jwt.getClaim("employee_id").asString();
} catch (Exception e) {
LOGGER.error(e.getMessage());
return null;
}
}
/**
* 获得token中的信息无需secret解密也能获得
*
* @return token中包含的用户名
*/
public static String getUsername(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getSubject();
} catch (JWTDecodeException e) {
return null;
}
}
/**
* 获得token中的信息无需secret解密也能获得
*
* @return token中包含的用户名
*/
public static String getEmployeeId(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("employee_id").asString();
} catch (JWTDecodeException e) {
return null;
}
}
/**
* 生成签名,60min后过期
*
* @param username 用户名
* @return 加密的token
*/
public static String sign(String username, String employeeId) throws UnsupportedEncodingException {
LocalDateTime currentTime = DateUtil80.getDateTimeOfTimestamp(System.currentTimeMillis());
Algorithm algorithm = Algorithm.HMAC512(jwtTokenSecret);
// 附带username信息
return JWT.create().withIssuer(jwtTokenIssuer)
// 创建时间
.withIssuedAt(DateUtil80.getCurrDateTime()).withSubject(username).withClaim("employee_id", employeeId)
.withExpiresAt(DateUtil80.asDate(currentTime.plusMinutes(240))).sign(algorithm);
}
/**
* 生成签名,30day后过期
*
* @param username 用户名
* @return 加密的token
*/
public static String signByRememberMe(String username, Integer userId) throws UnsupportedEncodingException {
LocalDateTime currentTime = DateUtil80.getDateTimeOfTimestamp(System.currentTimeMillis());
Algorithm algorithm = Algorithm.HMAC512(jwtTokenSecret);
// 附带username信息
return JWT.create().withIssuer(jwtTokenIssuer)
// 创建时间
.withIssuedAt(DateUtil80.getCurrDateTime()).withSubject(username).withClaim("userId", userId)
.withExpiresAt(DateUtil80.asDate(currentTime.plusSeconds(Integer.parseInt(jwtTokenExpiration))))
.sign(algorithm);
}
}
package cn.wisenergy.chnmuseum.party.common.checkcode;
import java.awt.*;
import java.io.OutputStream;
/**
* <p>
* 验证码抽象类,暂时不支持中文
* </p>
*
* @author: wuhongjun
* @version:1.0
*/
public abstract class Captcha extends Randoms {
protected Font font = new Font("Verdana", Font.ITALIC | Font.BOLD, 28); // 字体
protected int len = 4; // 验证码随机字符长度
protected int width = 150; // 验证码显示跨度
protected int height = 40; // 验证码显示高度
private String chars = null; // 随机字符串
/**
* 生成随机字符数组
*
* @return 字符数组
*/
protected char[] alphas() {
char[] cs = new char[len];
for (int i = 0; i < len; i++) {
cs[i] = alpha();
}
chars = new String(cs);
return cs;
}
public Font getFont() {
return font;
}
public void setFont(Font font) {
this.font = font;
}
public int getLen() {
return len;
}
public void setLen(int len) {
this.len = len;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
/**
* 给定范围获得随机颜色
*
* @return Color 随机颜色
*/
protected Color color(int fc, int bc) {
if (fc > 255)
fc = 255;
if (bc > 255)
bc = 255;
int r = fc + num(bc - fc);
int g = fc + num(bc - fc);
int b = fc + num(bc - fc);
return new Color(r, g, b);
}
/**
* 验证码输出,抽象方法,由子类实现
*
* @param os
* 输出流
*/
public abstract String out(OutputStream os);
/**
* 获取随机字符串
*
* @return string
*/
public String text() {
return chars;
}
}
\ No newline at end of file
package cn.wisenergy.chnmuseum.party.common.checkcode;
import java.io.IOException;
import java.io.OutputStream;
/**
* @author: wuhongjun
* @version:1.0
*/
public class Encoder {
private static final int EOF = -1;
private int imgW, imgH;
private byte[] pixAry;
private int initCodeSize;
private int remaining;
private int curPixel;
// GIFCOMPR.C - GIF Image compression routines
//
// Lempel-Ziv compression based on 'compress'. GIF modifications by
// David Rowley (mgardi@watdcsu.waterloo.edu)
// General DEFINEs
static final int BITS = 12;
static final int HSIZE = 5003; // 80% occupancy
// GIF Image compression - modified 'compress'
//
// Based on: compress.c - File compression ala IEEE Computer, June 1984.
//
// By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
// Jim McKie (decvax!mcvax!jim)
// Steve Davies (decvax!vax135!petsd!peora!srd)
// Ken Turkowski (decvax!decwrl!turtlevax!ken)
// James A. Woods (decvax!ihnp4!ames!jaw)
// Joe Orost (decvax!vax135!petsd!joe)
int n_bits; // number of bits/code
int maxbits = BITS; // user settable max # bits/code
int maxcode; // maximum code, given n_bits
int maxmaxcode = 1 << BITS; // should NEVER generate this code
int[] htab = new int[HSIZE];
int[] codetab = new int[HSIZE];
int hsize = HSIZE; // for dynamic table sizing
int free_ent = 0; // first unused entry
// block compression parameters -- after all codes are used up,
// and compression rate changes, start over.
boolean clear_flg = false;
// Algorithm: use open addressing double hashing (no chaining) on the
// prefix code / next character combination. We do a variant of Knuth's
// algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
// secondary probe. Here, the modular division first probe is gives way
// to a faster exclusive-or manipulation. Also do block compression with
// an adaptive reset, whereby the code table is cleared when the compression
// ratio decreases, but after the table fills. The variable-length output
// codes are re-sized at this point, and a special CLEAR code is generated
// for the decompressor. Late addition: construct the table according to
// file size for noticeable speed improvement on small files. Please direct
// questions about this implementation to ames!jaw.
int g_init_bits;
int ClearCode;
int EOFCode;
// output
//
// Output the given code.
// Inputs:
// code: A n_bits-bit integer. If == -1, then EOF. This assumes
// that n_bits =< wordsize - 1.
// Outputs:
// Outputs code to the file.
// Assumptions:
// Chars are 8 bits long.
// Algorithm:
// Maintain a BITS character long buffer (so that 8 codes will
// fit in it exactly). Use the VAX insv instruction to insert each
// code in turn. When the buffer fills up empty it and start over.
int cur_accum = 0;
int cur_bits = 0;
int masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF,
0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
// Number of characters so far in this 'packet'
int a_count;
// Define the storage for the packet accumulator
byte[] accum = new byte[256];
// ----------------------------------------------------------------------------
Encoder(int width, int height, byte[] pixels, int color_depth) {
imgW = width;
imgH = height;
pixAry = pixels;
initCodeSize = Math.max(2, color_depth);
}
// Add a character to the end of the current packet, and if it is 254
// characters, flush the packet to disk.
void char_out(byte c, OutputStream outs) throws IOException {
accum[a_count++] = c;
if (a_count >= 254)
flush_char(outs);
}
// Clear out the hash table
// table clear for block compress
void cl_block(OutputStream outs) throws IOException {
cl_hash(hsize);
free_ent = ClearCode + 2;
clear_flg = true;
output(ClearCode, outs);
}
// reset code table
void cl_hash(int hsize) {
for (int i = 0; i < hsize; ++i)
htab[i] = -1;
}
void compress(int init_bits, OutputStream outs) throws IOException {
int fcode;
int i /* = 0 */;
int c;
int ent;
int disp;
int hsize_reg;
int hshift;
// Set up the globals: g_init_bits - initial number of bits
g_init_bits = init_bits;
// Set up the necessary values
clear_flg = false;
n_bits = g_init_bits;
maxcode = MAXCODE(n_bits);
ClearCode = 1 << (init_bits - 1);
EOFCode = ClearCode + 1;
free_ent = ClearCode + 2;
a_count = 0; // clear packet
ent = nextPixel();
hshift = 0;
for (fcode = hsize; fcode < 65536; fcode *= 2)
++hshift;
hshift = 8 - hshift; // set hash code range bound
hsize_reg = hsize;
cl_hash(hsize_reg); // clear hash table
output(ClearCode, outs);
outer_loop: while ((c = nextPixel()) != EOF) {
fcode = (c << maxbits) + ent;
i = (c << hshift) ^ ent; // xor hashing
if (htab[i] == fcode) {
ent = codetab[i];
continue;
} else if (htab[i] >= 0) // non-empty slot
{
disp = hsize_reg - i; // secondary hash (after G. Knott)
if (i == 0)
disp = 1;
do {
if ((i -= disp) < 0)
i += hsize_reg;
if (htab[i] == fcode) {
ent = codetab[i];
continue outer_loop;
}
} while (htab[i] >= 0);
}
output(ent, outs);
ent = c;
if (free_ent < maxmaxcode) {
codetab[i] = free_ent++; // code -> hashtable
htab[i] = fcode;
} else
cl_block(outs);
}
// Put out the final code.
output(ent, outs);
output(EOFCode, outs);
}
// ----------------------------------------------------------------------------
void encode(OutputStream os) throws IOException {
os.write(initCodeSize); // write "initial code size" byte
remaining = imgW * imgH; // reset navigation variables
curPixel = 0;
compress(initCodeSize + 1, os); // compress and write the pixel data
os.write(0); // write block terminator
}
// Flush the packet to disk, and reset the accumulator
void flush_char(OutputStream outs) throws IOException {
if (a_count > 0) {
outs.write(a_count);
outs.write(accum, 0, a_count);
a_count = 0;
}
}
final int MAXCODE(int n_bits) {
return (1 << n_bits) - 1;
}
// ----------------------------------------------------------------------------
// Return the next pixel from the image
// ----------------------------------------------------------------------------
private int nextPixel() {
if (remaining == 0)
return EOF;
--remaining;
byte pix = pixAry[curPixel++];
return pix & 0xff;
}
void output(int code, OutputStream outs) throws IOException {
cur_accum &= masks[cur_bits];
if (cur_bits > 0)
cur_accum |= (code << cur_bits);
else
cur_accum = code;
cur_bits += n_bits;
while (cur_bits >= 8) {
char_out((byte) (cur_accum & 0xff), outs);
cur_accum >>= 8;
cur_bits -= 8;
}
// If the next entry is going to be too big for the code size,
// then increase it, if possible.
if (free_ent > maxcode || clear_flg) {
if (clear_flg) {
maxcode = MAXCODE(n_bits = g_init_bits);
clear_flg = false;
} else {
++n_bits;
if (n_bits == maxbits)
maxcode = maxmaxcode;
else
maxcode = MAXCODE(n_bits);
}
}
if (code == EOFCode) {
// At EOF, write the rest of the buffer.
while (cur_bits > 0) {
char_out((byte) (cur_accum & 0xff), outs);
cur_accum >>= 8;
cur_bits -= 8;
}
flush_char(outs);
}
}
}
package cn.wisenergy.chnmuseum.party.common.checkcode;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
/**
* <p>
* Gif验证码类
* </p>
*
* @author: wuhongjun
* @version:1.0
*/
public class GifCaptcha extends Captcha {
public GifCaptcha() {
}
public GifCaptcha(int width, int height) {
this.width = width;
this.height = height;
}
public GifCaptcha(int width, int height, int len) {
this(width, height);
this.len = len;
}
public GifCaptcha(int width, int height, int len, Font font) {
this(width, height, len);
this.font = font;
}
@Override
public String out(OutputStream os) {
try {
GifEncoder gifEncoder = new GifEncoder(); // gif编码类,这个利用了洋人写的编码类,所有类都在附件中
// 生成字符
gifEncoder.start(os);
gifEncoder.setQuality(180);
gifEncoder.setDelay(100);
gifEncoder.setRepeat(0);
BufferedImage frame;
char[] rands = alphas();
Color fontcolor[] = new Color[len];
for (int i = 0; i < len; i++) {
fontcolor[i] = new Color(20 + num(110), 20 + num(110), 20 + num(110));
}
for (int i = 0; i < len; i++) {
frame = graphicsImage(fontcolor, rands, i);
gifEncoder.addFrame(frame);
frame.flush();
}
gifEncoder.finish();
return String.valueOf(rands);
} finally {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 画随机码图
*
* @param fontcolor
* 随机字体颜色
* @param strs
* 字符数组
* @param flag
* 透明度使用
* @return BufferedImage
*/
private BufferedImage graphicsImage(Color[] fontcolor, char[] strs, int flag) {
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 或得图形上下文
// Graphics2D g2d=image.createGraphics();
Graphics2D g2d = (Graphics2D) image.getGraphics();
// 利用指定颜色填充背景
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, width, height);
AlphaComposite ac3;
int h = height - ((height - font.getSize()) >> 1);
int w = width / len;
g2d.setFont(font);
for (int i = 0; i < len; i++) {
ac3 = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, getAlpha(flag, i));
g2d.setComposite(ac3);
g2d.setColor(fontcolor[i]);
g2d.drawOval(num(width), num(height), 5 + num(10), 5 + num(10));
g2d.drawString(strs[i] + "", (width - (len - i) * w) + (w - font.getSize()) + 1, h - 4);
}
g2d.dispose();
return image;
}
/**
* 获取透明度,从0到1,自动计算步长
*
* @return float 透明度
*/
private float getAlpha(int i, int j) {
int num = i + j;
float r = (float) 1 / len, s = (len + 1) * r;
return num > len ? (num * r - s) : num * r;
}
}
package cn.wisenergy.chnmuseum.party.common.checkcode;
import java.util.Random;
/**
* <p>
* 随机工具类
* </p>
*
* @author: wuhongjun
* @version:1.0
*/
public class Randoms {
private static final Random RANDOM = new Random();
// 定义验证码字符.去除了O和I等容易混淆的字母
public static final char ALPHA[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'G', 'K', 'M', 'N', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '2', '3', '4', '5', '6', '7', '8', '9' };
/**
* 产生两个数之间的随机数
*
* @param min
* 小数
* @param max
* 比min大的数
* @return int 随机数字
*/
public static int num(int min, int max) {
return min + RANDOM.nextInt(max - min);
}
/**
* 产生0--num的随机数,不包括num
*
* @param num
* 数字
* @return int 随机数字
*/
public static int num(int num) {
return RANDOM.nextInt(num);
}
public static char alpha() {
return ALPHA[num(0, ALPHA.length)];
}
}
\ No newline at end of file
package cn.wisenergy.chnmuseum.party.common.checkcode;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
/**
* <p>
* png格式验证码
* </p>
*
* @author: wuhongjun
* @version:1.0
*/
public class SpecCaptcha extends Captcha {
public SpecCaptcha() {
}
public SpecCaptcha(int width, int height) {
this.width = width;
this.height = height;
}
public SpecCaptcha(int width, int height, int len) {
this(width, height);
this.len = len;
}
public SpecCaptcha(int width, int height, int len, Font font) {
this(width, height, len);
this.font = font;
}
/**
* 生成验证码
*
* @throws IOException IO异常
*/
@Override
public String out(OutputStream out) {
return graphicsImage(alphas(), out);
}
/**
* 画随机码图
*
* @param strs 文本
* @param out 输出流
*/
private String graphicsImage(char[] strs, OutputStream out) {
try {
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) bi.getGraphics();
AlphaComposite ac3;
Color color;
int len = strs.length;
g.setColor(Color.WHITE);
g.fillRect(0, 0, width, height);
// 随机画干扰的蛋蛋
for (int i = 0; i < 15; i++) {
color = color(150, 250);
g.setColor(color);
g.drawOval(num(width), num(height), 5 + num(10), 5 + num(10));// 画蛋蛋,有蛋的生活才精彩
color = null;
}
g.setFont(font);
int h = height - ((height - font.getSize()) >> 1), w = width / len, size = w - font.getSize() + 1;
/* 画字符串 */
for (int i = 0; i < len; i++) {
ac3 = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f);// 指定透明度
g.setComposite(ac3);
color = new Color(20 + num(110), 20 + num(110), 20 + num(110));// 对每个字符都用随机颜色
g.setColor(color);
g.drawString(strs[i] + "", (width - (len - i) * w) + size, h - 4);
color = null;
ac3 = null;
}
ImageIO.write(bi, "JPEG", out);
out.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return String.valueOf(strs);
}
}
\ No newline at end of file
package cn.wisenergy.chnmuseum.party.common.constant;
/**
* @ClassName: Constant
* @Description: TODO(这里用一句话描述这个类的作用)
* @author liqinwyyx@gmail.com
* @date 2014年8月16日 上午9:40:08
*/
public class Constant {
public static final String email = "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$";
public static final String mobile = "^((13[0-9])|(15[^4])|(18[0,1,2,3,5-9])|(17[0-8])|(147))\\d{8}$";
public static final String positiveInteger = "^\\+?[1-9][0-9]*$"; // 正整数
}
\ No newline at end of file
package cn.wisenergy.chnmuseum.party.common.constant;
public interface SecurityConstants {
String SHIRO_TOKEN_SMSCODE = "shiro:token:smscode";
/**
* 默认的处理验证码的url前缀
*/
String DEFAULT_VALIDATE_CODE_URL_PREFIX = "/code";
/**
* 当请求需要身份验证时跳转URL
*/
String DEFAULT_UNAUTHENTICATION_URL = "/authentication/require";
/**
* 默认的用户名密码登录请求处理url
*/
String DEFAULT_SIGN_IN_PROCESSING_URL_FORM = "/authentication/form";
/**
* 默认的手机验证码登录请求处理url
*/
String DEFAULT_SIGN_IN_PROCESSING_URL_MOBILE = "/authentication/mobile";
/**
* 默认的手机验证码登录请求处理url
*/
String DEFAULT_SIGN_IN_URL_MOBILE_PAGE = "/authentication/mobilePage";
/**
* 默认的用户注册请求处理url
*/
String DEFAULT_REGISTER_URL = "/authentication/register";
/**
* weixin appID
*/
String DEFAULT_SOCIAL_WEIXIN_APP_ID = "wxfd6965ab1fc6adb2";
/**
* weixin appsECRET
*/
String DEFAULT_SOCIAL_WEIXIN_APP_SECRET = "66bb4566de776ac699ec1dbed0cc3dd1";
/**
*自定义社交social拦截地址 默认/auth (SocialAuthenticationFilter)
*/
String DEFAULT_SOCIAL_PROCESS_URL = "/login";
/**
* 提供商的ID
*/
String DEFAULT_SOCIAL_QQ_PROVIDER_ID = "qq";
/**
* 提供商的ID
*/
String DEFAULT_SOCIAL_WEIXIN_PROVIDER_ID = "weixin";
/**
* 验证图片验证码时,http请求中默认的携带图片验证码信息的参数的名称
*/
String DEFAULT_PARAMETER_NAME_CODE_IMAGE = "imageCode";
/**
* 验证短信验证码时,http请求中默认的携带短信验证码信息的参数的名称
*/
String DEFAULT_PARAMETER_NAME_CODE_SMS = "smsCode";
/**
* 发送短信验证码 或 验证短信验证码时,传递手机号的参数的名称
*/
String DEFAULT_PARAMETER_NAME_MOBILE = "mobile";
}
package cn.wisenergy.chnmuseum.party.common.dfs;
import org.apache.commons.io.FilenameUtils;
import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* 上传图片到FastDFS
*/
public class FastDFSUtils {
static {
try {
ClientGlobal.initByProperties(FastDFSUtils.class.getClassLoader().getResource("fastdfs-client.properties").getPath());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (MyException e) {
e.printStackTrace();
}
}
public static String[] uploadPic(String path, String fileName, long size) {
String[] fileIds = null;
try {
// ClientGloble 读配置文件
// 老大客户端
TrackerClient trackerClient = new TrackerClient();
TrackerServer trackerServer = trackerClient.getConnection();
StorageServer storageServer = null;
StorageClient storageClient = new StorageClient(trackerServer, storageServer);
String extName = FilenameUtils.getExtension(fileName);
NameValuePair[] meta_list = new NameValuePair[3];
meta_list[0] = new NameValuePair("fileName", fileName);
meta_list[1] = new NameValuePair("fileExt", extName);
meta_list[2] = new NameValuePair("fileSize", String.valueOf(size));
// http://172.16.15.244:8081/group1/M00/00/00/rBAP9FfFG62AZsuBAADeW7MfEHA287.png
// group1/M00/00/01/wKjIgFWOYc6APpjAAAD-qk29i78248.jpg
fileIds = storageClient.upload_file(path, extName, meta_list);
} catch (Exception e) {
e.printStackTrace();
}
return fileIds;
}
public static String[] uploadPic(InputStream inStream, String fileName, long size) {
String[] fileIds = null;
try {
// ClientGloble 读配置文件
// 老大客户端
TrackerClient trackerClient = new TrackerClient();
TrackerServer trackerServer = trackerClient.getConnection();
StorageServer storageServer = null;
StorageClient storageClient = new StorageClient(trackerServer, storageServer);
String extName = FilenameUtils.getExtension(fileName);
NameValuePair[] meta_list = new NameValuePair[3];
meta_list[0] = new NameValuePair("fileName", fileName);
meta_list[1] = new NameValuePair("fileExt", extName);
meta_list[2] = new NameValuePair("fileSize", String.valueOf(size));
// http://172.16.15.244:8081/group1/M00/00/00/rBAP9FfFG62AZsuBAADeW7MfEHA287.png
// group1/M00/00/01/wKjIgFWOYc6APpjAAAD-qk29i78248.jpg
fileIds = storageClient.upload_file(null, size, new UploadFileSender(inStream), extName, meta_list);
} catch (Exception e) {
e.printStackTrace();
}
return fileIds;
}
public static String uploadPic(byte[] pic, String fileName, long size) {
String[] fileIds = null;
try {
// ClientGloble 读配置文件
// 老客户端
TrackerClient trackerClient = new TrackerClient();
TrackerServer trackerServer = trackerClient.getConnection();
StorageServer storageServer = null;
StorageClient storageClient = new StorageClient(trackerServer, storageServer);
String extName = FilenameUtils.getExtension(fileName);
// 设置图片meta信息
NameValuePair[] meta_list = new NameValuePair[3];
meta_list[0] = new NameValuePair("fileName", fileName);
meta_list[1] = new NameValuePair("fileExt", extName);
meta_list[2] = new NameValuePair("fileSize", String.valueOf(size));
// 上传且返回path
fileIds = storageClient.upload_file(pic, extName, meta_list);
return fileIds[0] + "/" + fileIds[1];
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static boolean deletePic(String fileUrl) {
try {
TrackerClient tracker = new TrackerClient();
TrackerServer trackerServer = tracker.getConnection();
StorageServer storageServer = null;
StorageClient storageClient = new StorageClient(trackerServer, storageServer);
StorePath storePath = StorePath.praseFromUrl(fileUrl);
int i = storageClient.delete_file(storePath.getGroup(), storePath.getPath());
System.out.println(i == 0 ? "删除成功" : "删除失败:" + i);
return i == 0;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
public static String deletePic(String[] fileIds) {
try {
TrackerClient tracker = new TrackerClient();
TrackerServer trackerServer = tracker.getConnection();
StorageServer storageServer = null;
StorageClient storageClient = new StorageClient(trackerServer, storageServer);
int i = storageClient.delete_file(fileIds[0], fileIds[1]);
System.out.println(i == 0 ? "删除成功" : "删除失败:" + i);
} catch (Exception e) {
e.printStackTrace();
}
return fileIds[1];
}
private static class UploadFileSender implements UploadCallback {
private InputStream inStream;
public UploadFileSender(InputStream inStream) {
this.inStream = inStream;
}
public int send(OutputStream out) throws IOException {
int readBytes;
while ((readBytes = inStream.read()) > 0) {
out.write(readBytes);
}
return 0;
}
}
}
\ No newline at end of file
package cn.wisenergy.chnmuseum.party.common.dfs;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Date;
import javax.imageio.ImageIO;
import org.apache.commons.io.FilenameUtils;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* ueditor
*/
public class FastdfsUtil {
private static final Logger logger = LoggerFactory.getLogger(FastdfsUtil.class);
private static boolean isInit = false;
private static void init() throws Exception {
String classPath = new File(FastdfsUtil.class.getResource("/").getFile()).getCanonicalPath();
String configFilePath = classPath + File.separator + "fastdfs-client.properties";
logger.info("FastdfsUtils.init加载配置文件:" + configFilePath);
ClientGlobal.initByProperties(configFilePath);
}
private static TrackerClient getTrackerClient() throws Exception {
if (!isInit) {
init();
isInit = true;
}
TrackerClient trackerClient = new TrackerClient();
return trackerClient;
}
private static TrackerServer getTrackerServer() throws Exception {
return getTrackerClient().getConnection();
}
private static StorageClient getStorageClient() throws Exception {
TrackerServer trackerServer = getTrackerServer();
// StorageServer storageServer = null;
// StorageClient storageClient = new StorageClient(trackerServer,
// storageServer);
StorageClient storageClient = new StorageClient(trackerServer, null);
return storageClient;
}
/**
* 文件方式上传
*/
public static Map<String, Object> uploadFile(File file) {
String fileName = file.getName();
byte[] fileBuff = FileUtil.getBytes(file);
return uploadFile(fileBuff, fileName);
}
/**
* 是否是图片
*/
private static boolean isImage(String fileName) {
return FileTypeUtil.isImageByExtension(fileName);
}
/**
* 字节流方式上传
*/
public static Map<String, Object> uploadFile(byte[] fileBuff, String fileName) {
String originalFileName = FilenameUtils.getName(fileName);// 文件名
String fileExtName = FilenameUtils.getExtension(originalFileName);// 文件后缀名
long length = fileBuff.length;// 字节
boolean isImage = isImage(originalFileName);
String mimeType = FileUtil.getMimeType(fileName);
int width = 0;
int height = 0;
if (isImage) {
int[] imageInfo = getImageInfo(fileBuff);
if (imageInfo != null) {
width = imageInfo[0];
height = imageInfo[1];
}
}
NameValuePair[] metaList = new NameValuePair[] { new NameValuePair("fileName", fileName),
new NameValuePair("isImage", isImage + ""), new NameValuePair("mimeType", mimeType),
new NameValuePair("width", width + ""), new NameValuePair("height", height + ""),
new NameValuePair("author", "FastdfsUtils") };
boolean status = false;
String message = "文件上传失败!";
logger.info("startTIme:" + (new Date().getMinutes()));
String[] responseData = storeFile(fileBuff, fileExtName, metaList);
logger.info("startTIme:" + (new Date().getMinutes()));
Map<String, Object> uploadResult = new HashMap<String, Object>();
if (responseData != null) {
status = true;
message = "文件上传成功!";
uploadResult.put("isImage", isImage);
if (isImage) {
uploadResult.put("width", width);
uploadResult.put("height", height);
}
uploadResult.put("groupName", responseData[0]);
uploadResult.put("storageFileName", responseData[1]);
uploadResult.put("link", responseData[0] + "/" + responseData[1]);// 文件访问链接
}
uploadResult.put("status", status);
uploadResult.put("message", message);
uploadResult.put("fileName", fileName);
uploadResult.put("mimeType", mimeType);
uploadResult.put("length", length);
return uploadResult;
}
private static int[] getImageInfo(byte[] fileBuff) {
try {
// File转为BufferedImage
// BufferedImage buff = ImageIO.read(new
// FileImageInputStream(file));
// BufferedImage buff = ImageIO.read(file);
// byte[]转为BufferedImage
ByteArrayInputStream in = new ByteArrayInputStream(fileBuff);// 将byte[]作为输入流;
BufferedImage image = ImageIO.read(in);// 将in作为输入流,读取图片存入image中,而这里in可以为ByteArrayInputStream();
int width = image.getWidth();
int height = image.getHeight();
return new int[] { width, height };
} catch (Exception e) {
logger.error("FastdfsUtils.getImageInfo时发生异常:", e);
}
return new int[] { 0, 0 };
}
private static String[] storeFile(byte[] fileBuff, String fileExtName, NameValuePair[] metaList) {
String[] responseData = null;
try {
StorageClient storageClient = getStorageClient();
responseData = storageClient.upload_file(fileBuff, fileExtName.toLowerCase(), metaList);
} catch (Exception e) {
logger.error("FastdfsUtils.storeFile时发生异常:", e);
}
return responseData;
}
}
package cn.wisenergy.chnmuseum.party.common.dfs;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
public class FileTypeUtil {
private final static Map<String, String> FILE_TYPE_MAP = new HashMap<String, String>();
private final static List<String> imageAllowFiles = Arrays
.asList(new String[] { "png", "jpg", "jpeg", "gif", "bmp" });/* 允许上传的图片格式 */
static {
getAllFileType(); // 初始化文件类型信息
}
/**
* <p>
* Discription:[getAllFileType,常见文件头信息] 注:TXT文件没有文件头
* </p>
*/
private static void getAllFileType() {
FILE_TYPE_MAP.put("jpg", "FFD8FF"); // JPEG (jpg)
FILE_TYPE_MAP.put("png", "89504E47"); // PNG (png)
FILE_TYPE_MAP.put("gif", "47494638"); // GIF (gif)
FILE_TYPE_MAP.put("tif", "49492A00"); // TIFF (tif)
FILE_TYPE_MAP.put("bmp", "424D"); // Windows Bitmap (bmp)
FILE_TYPE_MAP.put("dwg", "41433130"); // CAD (dwg)
FILE_TYPE_MAP.put("html", "68746D6C3E"); // HTML (html)
FILE_TYPE_MAP.put("rtf", "7B5C727466"); // Rich Text Format (rtf)
FILE_TYPE_MAP.put("xml", "3C3F786D6C");
FILE_TYPE_MAP.put("zip", "504B0304");
FILE_TYPE_MAP.put("rar", "52617221");
FILE_TYPE_MAP.put("psd", "38425053"); // Photoshop (psd)
FILE_TYPE_MAP.put("eml", "44656C69766572792D646174653A"); // Email
// [thorough
// only]
// (eml)
FILE_TYPE_MAP.put("dbx", "CFAD12FEC5FD746F"); // Outlook Express (dbx)
FILE_TYPE_MAP.put("pst", "2142444E"); // Outlook (pst)
FILE_TYPE_MAP.put("xls", "D0CF11E0"); // MS Word
FILE_TYPE_MAP.put("doc", "D0CF11E0"); // MS Excel 注意:word 和 excel的文件头一样
FILE_TYPE_MAP.put("mdb", "5374616E64617264204A"); // MS Access (mdb)
FILE_TYPE_MAP.put("wpd", "FF575043"); // WordPerfect (wpd)
FILE_TYPE_MAP.put("eps", "252150532D41646F6265");
FILE_TYPE_MAP.put("ps", "252150532D41646F6265");
FILE_TYPE_MAP.put("pdf", "255044462D312E"); // Adobe Acrobat (pdf)
FILE_TYPE_MAP.put("qdf", "AC9EBD8F"); // Quicken (qdf)
FILE_TYPE_MAP.put("pwl", "E3828596"); // Windows Password (pwl)
FILE_TYPE_MAP.put("wav", "57415645"); // Wave (wav)
FILE_TYPE_MAP.put("avi", "41564920");
FILE_TYPE_MAP.put("ram", "2E7261FD"); // Real Audio (ram)
FILE_TYPE_MAP.put("rm", "2E524D46"); // Real Media (rm)
FILE_TYPE_MAP.put("mpg", "000001BA"); //
FILE_TYPE_MAP.put("mov", "6D6F6F76"); // Quicktime (mov)
FILE_TYPE_MAP.put("asf", "3026B2758E66CF11"); // Windows Media (asf)
FILE_TYPE_MAP.put("mid", "4D546864"); // MIDI (mid)
}
/**
* <p>
* Discription:[getFileTypeByStream]
* </p>
*/
public final static String getFileTypeByStream(byte[] b) {
String filetypeHex = String.valueOf(getFileHexString(b));
Iterator<Entry<String, String>> entryiterator = FILE_TYPE_MAP.entrySet().iterator();
while (entryiterator.hasNext()) {
Entry<String, String> entry = entryiterator.next();
String fileTypeHexValue = entry.getValue();
if (filetypeHex.toUpperCase().startsWith(fileTypeHexValue)) {
return entry.getKey();
}
}
return null;
}
/**
* <p>
* Discription:[getFileByFile,获取文件类型,包括图片,若格式不是已配置的,则返回null]
* </p>
*/
public final static String getFileTypeByFile(File file) {
String fileType = null;
byte[] b = new byte[50];
try {
InputStream is = new FileInputStream(file);
is.read(b);
fileType = getFileTypeByStream(b);
is.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return fileType;
}
/**
* <p>
* Discription:[getFileHexString]
* </p>
*/
public final static String getFileHexString(byte[] b) {
StringBuilder stringBuilder = new StringBuilder();
if (b == null || b.length <= 0) {
return null;
}
for (int i = 0; i < b.length; i++) {
int v = b[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString();
}
/**
* <p>
* Discription:[getImageFileType,获取图片文件实际类型,若不是图片则返回null]
* </p>
*/
public final static String getImageFileType(File f) {
if (isImage(f)) {
try {
ImageInputStream iis = ImageIO.createImageInputStream(f);
Iterator<ImageReader> iter = ImageIO.getImageReaders(iis);
if (!iter.hasNext()) {
return null;
}
ImageReader reader = iter.next();
iis.close();
return reader.getFormatName();
} catch (IOException e) {
e.printStackTrace();
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
return null;
}
/**
* 只根据后缀名判断是否为图片
*
* @param file
* @return
*/
public static final boolean isImage(File file) {
return isImage(file, true);
}
/**
* <p>
* Discription:[isImage,判断文件是否为图片]
* </p>
*
* @param file
* 源文件
* @param onlyByExtension
* 是否值验证后缀名
* @return true 是 | false 否
*/
public static final boolean isImage(File file, boolean onlyByExtension) {
boolean flag = false;
try {
boolean allowFile = isImageByExtension(file.getName());
if (onlyByExtension) {
flag = allowFile;
} else {
if (allowFile) {
BufferedImage bufreader = ImageIO.read(file);
int width = bufreader.getWidth();
int height = bufreader.getHeight();
if (width == 0 || height == 0) {
flag = false;
} else {
flag = true;
}
}
}
} catch (IOException e) {
flag = false;
e.printStackTrace();
} catch (Exception e) {
flag = false;
e.printStackTrace();
}
return flag;
}
/**
* 只通过后缀名判断是否为图片
*
* @param fileName
* @return
*/
public static final boolean isImageByExtension(String fileName) {
boolean flag = false;
String fileExtName = FilenameUtils.getExtension(fileName);
if (StringUtils.isNotBlank(fileExtName)) {
flag = imageAllowFiles.contains(fileExtName.toLowerCase());
}
return flag;
}
}
package cn.wisenergy.chnmuseum.party.common.dfs;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.FileNameMap;
import java.net.URLConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FileUtil {
private static final Logger logger = LoggerFactory.getLogger(FileUtil.class);
/**
* Get the Mime Type from a File
* <p>
* 参考:http://www.rgagnon.com/javadetails/java-0487.html,http://dada89007.
* iteye.com/blog/1392606
* </p>
*
* @param fileName
* @return
*/
public static String getMimeType(String fileName) {
FileNameMap fileNameMap = URLConnection.getFileNameMap();
String type = fileNameMap.getContentTypeFor(fileName);
logger.debug("type:" + type);
return type;
}
/**
* 获得指定文件的byte数组
*/
public static byte[] getBytes(String filePath) {
byte[] buffer = null;
File file = new File(filePath);
buffer = getBytes(file);
return buffer;
}
/**
* 获得指定文件的byte数组
*/
public static byte[] getBytes(File file) {
byte[] buffer = null;
try {
FileInputStream fis = new FileInputStream(file);
buffer = new byte[fis.available()];
long length = fis.read(buffer);
fis.close();
logger.debug("length:" + length);
} catch (FileNotFoundException e) {
logger.error("FileNotFoundException异常", e);
} catch (IOException e) {
logger.error("IOException异常", e);
}
return buffer;
}
}
package cn.wisenergy.chnmuseum.party.common.dfs;
import cn.wisenergy.chnmuseum.party.common.exception.FdfsUnsupportStorePathException;
import org.apache.commons.lang3.Validate;
/**
* 存储文件的路径信息
*
* @author yuqih
*
*/
public class StorePath {
private String group;
private String path;
/** 解析路径 */
private static final String SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR = "/";
/** group */
private static final String SPLIT_GROUP_NAME = "group";
/**
* 存储文件路径
*/
public StorePath() {
}
/**
* 存储文件路径
*
* @param group
* @param path
*/
public StorePath(String group, String path) {
super();
this.group = group;
this.path = path;
}
/**
* @return the group
*/
public String getGroup() {
return group;
}
/**
* @param group
* the group to set
*/
public void setGroup(String group) {
this.group = group;
}
/**
* @return the path
*/
public String getPath() {
return path;
}
/**
* @param path
* the path to set
*/
public void setPath(String path) {
this.path = path;
}
/**
* 获取文件全路径
*
* @return
*/
public String getFullPath() {
return this.group.concat(SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR).concat(this.path);
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "StorePath [group=" + group + ", path=" + path + "]";
}
/**
* 从Url当中解析存储路径对象
*
* @param filePath
* 有效的路径样式为(group/path) 或者 (http://ip/group/path),路径地址必须包含group
* @return
*/
public static StorePath praseFromUrl(String filePath) {
Validate.notNull(filePath, "解析文件路径不能为空");
// 获取group起始位置
int groupStartPos = getGroupStartPos(filePath);
String groupAndPath = filePath.substring(groupStartPos);
int pos = groupAndPath.indexOf(SPLIT_GROUP_NAME_AND_FILENAME_SEPERATOR);
if ((pos <= 0) || (pos == groupAndPath.length() - 1)) {
throw new FdfsUnsupportStorePathException("解析文件路径错误,有效的路径样式为(group/path) 而当前解析路径为".concat(filePath));
}
String group = groupAndPath.substring(0, pos);
String path = groupAndPath.substring(pos + 1);
return new StorePath(group, path);
}
/**
* 获得group起始位置
*
* @param filePath
*/
private static int getGroupStartPos(String filePath) {
int pos = filePath.indexOf(SPLIT_GROUP_NAME);
if ((pos == -1)) {
throw new FdfsUnsupportStorePathException("解析文件路径错误,被解析路径url没有group,当前解析路径为".concat(filePath));
}
return pos;
}
}
\ No newline at end of file
package cn.wisenergy.chnmuseum.party.common.exception;
/**
* 封装fastdfs的异常,使用运行时异常
*
* @author yuqih
* @author tobato
*
*/
public abstract class FdfsException extends RuntimeException {
/**
* serialVersionUID
*/
private static final long serialVersionUID = 1L;
protected FdfsException(String message) {
super(message);
}
/**
* @param message
* @param cause
*/
protected FdfsException(String message, Throwable cause) {
super(message, cause);
}
}
\ No newline at end of file
package cn.wisenergy.chnmuseum.party.common.exception;
/**
* 从Url解析StorePath文件路径对象错误
*
* @author wuyf
*
*/
public class FdfsUnsupportStorePathException extends FdfsException {
/**
* serialVersionUID
*/
private static final long serialVersionUID = 8116336411011152869L;
public FdfsUnsupportStorePathException(String message) {
super(message);
}
}
\ No newline at end of file
package cn.wisenergy.chnmuseum.party.common.multidatasource;
public enum DBTypeEnum {
datasource1("datasource1"), datasource2("datasource2");
private String value;
DBTypeEnum(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
package cn.wisenergy.chnmuseum.party.common.multidatasource;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 这是为了保证AOP在事务注解之前生效,Order的值越小,优先级越高
*/
//@Order(-100)
//@Component
//@Aspect
public class DataSourceSwitchAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceSwitchAspect.class);
@Pointcut("execution(* cn.gov.zunyi.business.hall.mapper.db1..*.*(..))")
private void db1Aspect() {
}
@Pointcut("execution(* cn.gov.zunyi.business.hall.mapper.db2..*.*(..))")
private void db2Aspect() {
}
@Before("db1Aspect()")
public void db1() {
LOGGER.info("切换到db1 数据源...");
DbContextHolder.setDbType(DBTypeEnum.datasource1);
}
@Before("db2Aspect()")
public void db2 () {
LOGGER.info("切换到db2 数据源...");
DbContextHolder.setDbType(DBTypeEnum.datasource2);
}
}
package cn.wisenergy.chnmuseum.party.common.multidatasource;
public class DbContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
/**
* 设置数据源
*
* @param dbTypeEnum
*/
public static void setDbType(DBTypeEnum dbTypeEnum) {
contextHolder.set(dbTypeEnum.getValue());
}
/**
* 取得当前数据源
*
* @return
*/
public static String getDbType() {
return contextHolder.get();
}
/**
* 清除上下文数据
*/
public static void clearDbType() {
contextHolder.remove();
}
}
package cn.wisenergy.chnmuseum.party.common.multidatasource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicMultipleDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
String lookupKey = DbContextHolder.getDbType();
if(lookupKey == null) {
lookupKey = DBTypeEnum.datasource2.toString();
}
DbContextHolder.clearDbType();
return lookupKey;
}
}
package cn.wisenergy.chnmuseum.party.common.mvc;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.convert.converter.Converter;
public class StringToDateConverter implements Converter<String, Date> {
private static final String dateFormat = "yyyy-MM-dd HH:mm:ss";
private static final String shortDateFormat = "yyyy-MM-dd";
/**
* @see Converter#convert(Object)
*/
@Override
public Date convert(String source) {
if (StringUtils.isBlank(source)) {
return null;
}
source = source.trim();
try {
if (source.contains("-")) {
SimpleDateFormat formatter;
if (source.contains(":")) {
formatter = new SimpleDateFormat(dateFormat);
} else {
formatter = new SimpleDateFormat(shortDateFormat);
}
Date dtDate = formatter.parse(source);
return dtDate;
} else if (source.matches("^\\d+$")) {
Long lDate = new Long(source);
return new Date(lDate);
}
} catch (Exception e) {
throw new RuntimeException(String.format("parser %s to Date fail", source));
}
throw new RuntimeException(String.format("parser %s to Date fail", source));
}
}
\ No newline at end of file
package cn.wisenergy.chnmuseum.party.common.mvc;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.convert.converter.Converter;
public class StringToIntegerConverter implements Converter<String, Integer> {
/**
* @see Converter#convert(Object)
*/
@Override
public Integer convert(String source) {
if (StringUtils.isBlank(source)) {
return null;
}
try {
source = source.trim();
return Integer.parseInt(source);
} catch (Exception e) {
throw new RuntimeException(String.format("parser %s to Date fail", source));
}
}
}
\ No newline at end of file
package cn.wisenergy.chnmuseum.party.common.mybatis;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;
import java.math.BigDecimal;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* MyBatisDecimal转换器
*/
/* 数据库中的数据类型 */
@MappedJdbcTypes(JdbcType.DECIMAL)
/* 转化后的数据类型 */
@MappedTypes(value = BigDecimal.class)
public class DecimalHandler implements TypeHandler<BigDecimal> {
@Override
public void setParameter(PreparedStatement preparedStatement, int i, BigDecimal bigDecimal, JdbcType jdbcType) throws SQLException {
preparedStatement.setBigDecimal(i, bigDecimal);
}
@Override
public BigDecimal getResult(ResultSet resultSet, String s) throws SQLException {
return transfer(resultSet.getString(s));
}
@Override
public BigDecimal getResult(ResultSet resultSet, int i) throws SQLException {
return transfer(resultSet.getString(i));
}
@Override
public BigDecimal getResult(CallableStatement callableStatement, int i) throws SQLException {
return transfer(callableStatement.getString(i));
}
private BigDecimal transfer(String val) {
if (val != null) {
val = val.replace(",", "");
return new BigDecimal(val);
}
return null;
}
}
package cn.wisenergy.chnmuseum.party.common.mybatis;
import java.io.File;
/**
* 生成器常量
**/
public interface GeneratorConstant {
/**
* 用户目录
*/
String USER_DIR = "user.dir";
/**
* java目录 src/main/java
*/
String JAVA_DIR = File.separator + "src" + File.separator + "main" + File.separator + "java";
/**
* resources目录 src/main/resources
*/
String RESOURCES_DIR = File.separator + "src" + File.separator + "main" + File.separator + "resources";
/**
* mapper目录 src/main/resources/mapper
*/
String MAPPER_DIR = RESOURCES_DIR + File.separator + "mapper";
/**
* 参数
*/
String PARAM = "param";
/**
* 分页参数
*/
String PAGE_PARAM = "PageParam";
/**
* VO
*/
String VO = "vo";
/**
* 查询VO
*/
String QUERY_VO = "QueryVo";
/**
* Service
*/
String SERVICE = "Service";
/**
* Mapper
*/
String MAPPER = "Mapper";
/**
* Mapper XML template路径
*/
String MAPPER_XML_TEMPLATE_PATH = File.separator + "templates" + File.separator + "mapper.xml.vm";
/**
* 分页参数 template路径
*/
String PAGE_PARAM_TEMPLATE_PATH = File.separator + "templates" + File.separator + "pageParam.java.vm";
/**
* 查询VO template路径
*/
String QUERY_VO_TEMPLATE_PATH = File.separator + "templates" + File.separator + "queryVo.java.vm";
/**
* 乐观锁属性名称
*/
String VERSION = "VERSION";
/**
* 逻辑删除属性名称
*/
String DELETED = "ENABLED_FLAG";
/**
* Service名称
*/
String SERVICE_NAME = "%sService";
/**
* 自定义继承的Entity类全称,带包名
*/
String SUPER_ENTITY_CLASS = "io.geekidea.springbootplus.framework.common.entity.BaseEntity";
/**
* 自定义继承的Controller类全称,带包名
*/
String SUPER_CONTROLLER_CLASS = "io.geekidea.springbootplus.framework.common.controller.BaseController";
/**
* 自定义继承的Service类全称,带包名
*/
String SUPER_SERVICE_CLASS = "io.geekidea.springbootplus.framework.common.service.BaseService";
/**
* 自定义继承的ServiceImpl类全称,带包名
*/
String SUPER_SERVICE_IMPL_CLASS = "io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl";
/**
* 分页参数父类全称,带包名
*/
String SUPER_PAGE_PARAM_CLASS = "io.geekidea.springbootplus.framework.core.pagination.BasePageParam";
/**
* 分页排序参数父类全称,带包名
*/
String SUPER_PAGE_ORDER_PARAM_CLASS = "io.geekidea.springbootplus.framework.core.pagination.BasePageOrderParam";
/**
* 公共id参数类全称,带包名
*/
String ID_PARAM_CLASS = "io.geekidea.springbootplus.framework.common.param.IdParam";
/**
* 分页对象类全称,带包名
*/
String PAGING_CLASS = "io.geekidea.springbootplus.framework.core.pagination.Paging";
/**
* 分页信息类全称,带包名
*/
String PAGE_INFO_CLASS = "io.geekidea.springbootplus.framework.core.pagination.PageInfo";
/**
* 公共结果类全称,带包名
*/
String API_RESULT_CLASS = "io.geekidea.springbootplus.framework.common.api.ApiResult";
/**
* 分组验证Add.class类路径
*/
String VALIDATOR_ADD_PACKAGE = "io.geekidea.springbootplus.framework.core.validator.groups.Add";
/**
* 分组验证Update.class类路径
*/
String VALIDATOR_UPDATE_PACKAGE = "io.geekidea.springbootplus.framework.core.validator.groups.Update";
}
package cn.wisenergy.chnmuseum.party.common.mybatis;
import cn.wisenergy.datastation.common.core.utils.mybatis.query.InsertBatch;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.extension.injector.methods.AlwaysUpdateSomeColumnById;
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
import com.baomidou.mybatisplus.extension.injector.methods.LogicDeleteByIdWithFill;
import java.util.List;
/**
* @author DannyLee
* @description 自定义sql注入器·
* @date Created in 2020/3/6 16:10
*/
public class MyLogicSqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass);
//增加自定义方法
methodList.add(new InsertBatch());
/**
* 以下 3 个为内置选装件
* 头 2 个支持字段筛选函数
*/
// 例: 不要指定了 update 填充的字段
methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
methodList.add(new AlwaysUpdateSomeColumnById(t -> !"name".equals(t.getColumn())));
methodList.add(new LogicDeleteByIdWithFill());
return methodList;
}
}
package cn.wisenergy.chnmuseum.party.common.mybatis;
import com.baomidou.mybatisplus.generator.config.querys.MySqlQuery;
/**
* MySQL代码生成查询是否为空的列
**/
public class MySQLQuery extends MySqlQuery {
@Override
public String[] fieldCustom() {
return new String[]{"null", "default", "privileges"};
}
}
package cn.wisenergy.chnmuseum.party.common.mybatis;
public class MysqlGenerator {
private static final String[] tableNames = new String[]{"M_QUALITY_JOB"};
private static final String projectPath = "/opt/ss";
public static void main(String[] args) {
CodeGenerator codeGenerator = new CodeGenerator();
for (String tableName : tableNames) {
codeGenerator.generator(projectPath, tableName);
}
}
}
package cn.wisenergy.chnmuseum.party.common.mybatis;
import com.github.pagehelper.Page;
import java.io.Serializable;
import java.util.List;
/**
* 对Page结果进行包装
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public class PageInfo<T> implements Serializable {
private static final long serialVersionUID = 8656597559014685635L;
/**
* 默认每页记录数
*/
private static final int DEFAULT_PAGE_SIZE = 10;
/**
* 最大每页记录数
*/
private static final int MAX_PAGE_SIZE = 1000;
private long total; //总记录数
private List<T> list; //结果集
private int pageNumber = 1; // 第几页
private int pageSize = DEFAULT_PAGE_SIZE; // 每页记录数
private int pages; // 总页数
private int size; // 当前页的数量 <= pageSize,该属性来自ArrayList的size属性
private int prevSize; // 上页页数
public PageInfo() {
}
public PageInfo(List<T> list) {
if (list instanceof Page) {
Page<T> page = (Page<T>) list;
this.pageNumber = page.getPageNum();
this.pageSize = page.getPageSize();
this.total = page.getTotal();
this.pages = page.getPages();
this.list = page;
this.size = page.size();
}
}
public PageInfo(Integer pageNumber, Integer pageSize) {
if (pageNumber != null && pageNumber >= 1) {
this.pageNumber = pageNumber;
}
if (pageSize != null && pageSize >= 1 && pageSize <= MAX_PAGE_SIZE) {
this.pageSize = pageSize;
}
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
reset(this.pageSize, total);
}
public List<T> getList() {
return list;
}
public void setList(List<T> list) {
this.list = list;
}
public int getPageNumber() {
return pageNumber;
}
public void setPageNumber(int pageNumber) {
reset(this.pageSize, this.total);
this.pageNumber = pageNumber;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
reset(pageSize, this.total);
}
public int getPages() {
return pages;
}
public void setPages(int pages) {
this.pages = pages;
}
public int getSize() {
return size;
}
public void setSize(int size) {
this.size = size;
}
public int getPrevSize() {
return prevSize;
}
/**
* 重新设置属性
*
* @param pageSize
* @param total
*/
private void reset(int pageSize, long total) {
this.total = total;
this.pageSize = pageSize;
this.pages = (int) (total % pageSize == 0 ? total / pageSize : total / pageSize + 1);
this.prevSize = (pageNumber - 1) * pageSize;
}
}
package cn.wisenergy.chnmuseum.party.common.mybatis.query;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
public class InsertBatch extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
final String sql = "<script>insert into %s %s values %s</script>";
final String fieldSql = prepareFieldSql(tableInfo);
final String valueSql = prepareValuesSqlForMysqlBatch(tableInfo);
final String sqlResult = String.format(sql, tableInfo.getTableName(), fieldSql, valueSql);
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass);
return this.addInsertMappedStatement(mapperClass, modelClass, "insertBatch", sqlSource, new NoKeyGenerator(), null, null);
}
private String prepareFieldSql(TableInfo tableInfo) {
StringBuilder fieldSql = new StringBuilder();
fieldSql.append(tableInfo.getKeyColumn()).append(",");
tableInfo.getFieldList().forEach(x -> {
fieldSql.append(x.getColumn()).append(",");
});
fieldSql.delete(fieldSql.length() - 1, fieldSql.length());
fieldSql.insert(0, "(");
fieldSql.append(")");
return fieldSql.toString();
}
private String prepareValuesSqlForMysqlBatch(TableInfo tableInfo) {
final StringBuilder valueSql = new StringBuilder();
valueSql.append("<foreach collection=\"list\" item=\"item\" index=\"index\" open=\"(\" separator=\"),(\" close=\")\">");
valueSql.append("#{item.").append(tableInfo.getKeyProperty()).append("},");
tableInfo.getFieldList().forEach(x -> valueSql.append("#{item.").append(x.getProperty()).append("},"));
valueSql.delete(valueSql.length() - 1, valueSql.length());
valueSql.append("</foreach>");
return valueSql.toString();
}
}
package cn.wisenergy.chnmuseum.party.common.mybatis.query;
import com.baomidou.mybatisplus.generator.config.querys.MySqlQuery;
/**
* MySQL代码生成查询是否为空的列
**/
public class MySQLQuery extends MySqlQuery {
@Override
public String[] fieldCustom() {
return new String[]{"null", "default", "privileges"};
}
}
package cn.wisenergy.chnmuseum.party.common.util;
import java.util.HashMap;
import java.util.Map;
/**
* 地域通用工具类
*
* @author lmh
*
*/
public class AreaUtil {
public static Map<String, String> areaMap() {
Map<String, String> map = new HashMap<String, String>();
map.put("110000", "北京市");
map.put("120000", "天津市");
map.put("130000", "河北省");
map.put("140000", "山西省");
map.put("150000", "内蒙古自治区");
map.put("210000", "辽宁省");
map.put("220000", "吉林省");
map.put("230000", "黑龙江省");
map.put("310000", "上海市");
map.put("320000", "江苏省");
map.put("330000", "浙江省");
map.put("340000", "安徽省");
map.put("350000", "福建省");
map.put("360000", "江西省");
map.put("370000", "山东省");
map.put("410000", "河南省");
map.put("420000", "湖北省");
map.put("430000", "湖南省");
map.put("440000", "广东省");
map.put("450000", "广西壮族自治区");
map.put("460000", "海南省");
map.put("500000", "重庆市");
map.put("510000", "四川省");
map.put("520000", "贵州省");
map.put("530000", "云南省");
map.put("540000", "西藏自治区");
map.put("610000", "陕西省");
map.put("620000", "甘肃省");
map.put("630000", "青海省");
map.put("640000", "宁夏回族自治区");
map.put("650000", "新疆维吾尔自治区");
map.put("710000", "台湾省");
map.put("810000", "香港特别行政区");
map.put("820000", "澳门特别行政区");
return map;
}
// 取国际key
public static String getAreaByKey(String key) {
Map<String, String> areaMap = areaMap();
return areaMap.get(key);
}
}
package cn.wisenergy.chnmuseum.party.common.util;
import java.util.Map;
import java.util.UUID;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.DateConverter;
public class CommonUtil {
/**
* 返回一个不重复的字符串
*
* @return
*/
public static String uuid() {
return UUID.randomUUID().toString().toLowerCase().replace("-","");
}
/**
* 把map转换成对象
*
* @param map
* @param clazz
* @return
*
* 把Map转换成指定类型
*/
public static <T> T toBean(Map<String, ? extends Object> map, Class<T> clazz) {
try {
/*
* 1. 通过参数clazz创建实例 2. 使用BeanUtils.populate把map的数据封装到bean中
*/
T bean = clazz.newInstance();
ConvertUtils.register(new DateConverter(), java.util.Date.class);
BeanUtils.populate(bean, map);
return bean;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
package cn.wisenergy.chnmuseum.party.common.util;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class DateUtil80 {
// 格式:年-月-日 小时:分钟:秒
public static final String FORMAT_ONE = "yyyy-MM-dd HH:mm:ss";
public static final String FORMAT_T = "yyyy-MM-ddTHH:mm:ss";
// 格式:年-月-日 小时:分钟
public static final String FORMAT_TWO = "yyyy-MM-dd HH:mm";
// 格式:年-月-日
public static final String LONG_DATE_FORMAT = "yyyy-MM-dd";
// 格式:月-日
public static final String SHORT_DATE_FORMAT = "MM-dd";
// 格式:小时:分钟:秒
public static final String LONG_TIME_FORMAT = "HH:mm:ss";
// 格式:年-月
public static final String MONTG_DATE_FORMAT = "yyyy-MM";
// 格式:年-月
public static final String Chinese_DATE_FORMAT = "yyyy年MM月dd日 HH:mm";
private static final ConcurrentMap<String, DateTimeFormatter> FORMATTER_CACHE = new ConcurrentHashMap<>();
private static final int PATTERN_CACHE_SIZE = 500;
/**
* Date转换为格式化时间
*
* @param date date
* @param pattern 格式
* @return
*/
public static String format(Date date, String pattern) {
return format(LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()), pattern);
}
/**
* localDateTime转换为格式化时间
*
* @param localDateTime localDateTime
* @param pattern 格式
* @return
*/
public static String format(LocalDateTime localDateTime, String pattern) {
DateTimeFormatter formatter = createCacheFormatter(pattern);
return localDateTime.format(formatter);
}
/**
* 格式化字符串转为Date
*
* @param time 格式化时间
* @param pattern 格式
* @return
*/
public static Date parseDate(String time, String pattern) {
return Date.from(parseLocalDateTime(time, pattern).atZone(ZoneId.systemDefault()).toInstant());
}
/**
* 格式化字符串转为Date
*
* @return
*/
public static Date getCurrDateTime() {
LocalDateTime localDateTime = LocalDateTime.now();
ZoneId zone = ZoneId.systemDefault();
Instant instant = localDateTime.atZone(zone).toInstant();
return Date.from(instant);
}
/**
* 格式化字符串转为Date
*
* @return
*/
public static Date getCurrDate() {
ZoneId zoneId = ZoneId.systemDefault();
LocalDate localDate = LocalDate.now();
ZonedDateTime zdt = localDate.atStartOfDay(zoneId);
return Date.from((zdt).toInstant());
}
//LocalDateTime -> Date
public static Date asDate(LocalDateTime localDateTime) {
return Date.from(localDateTime.atZone(ZoneId.of("Asia/Shanghai")).toInstant());
}
/**
* 格式化字符串转为LocalDateTime
*
* @param time 格式化时间
* @param pattern 格式
* @return
*/
public static LocalDateTime parseLocalDateTime(String time, String pattern) {
DateTimeFormatter formatter = createCacheFormatter(pattern);
return LocalDateTime.parse(time, formatter);
}
/**
* 将long类型的timestamp转为LocalDateTime
*
* @param timestamp
* @return
*/
public static LocalDateTime getDateTimeOfTimestamp(long timestamp) {
Instant instant = Instant.ofEpochMilli(timestamp);
ZoneId zone = ZoneId.systemDefault();
return LocalDateTime.ofInstant(instant, zone);
}
/**
* 在缓存中创建DateTimeFormatter
*
* @param pattern 格式
* @return
*/
private static DateTimeFormatter createCacheFormatter(String pattern) {
if (pattern == null || pattern.length() == 0) {
throw new IllegalArgumentException("Invalid pattern specification");
}
DateTimeFormatter formatter = FORMATTER_CACHE.get(pattern);
if (formatter == null) {
if (FORMATTER_CACHE.size() < PATTERN_CACHE_SIZE) {
formatter = DateTimeFormatter.ofPattern(pattern);
DateTimeFormatter oldFormatter = FORMATTER_CACHE.putIfAbsent(pattern, formatter);
if (oldFormatter != null) {
formatter = oldFormatter;
}
}
}
return formatter;
}
}
package cn.wisenergy.chnmuseum.party.common.util;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
/**
* 导出excel工具类
*
* @author lmh
*/
public class ExcelUtil {
public static HSSFWorkbook getHSSFWorkbook(String sheetName, String[] title, String[][] values, HSSFWorkbook wb) {
// 第一步,创建一个webbook,对应一个Excel文件
if (wb == null) {
wb = new HSSFWorkbook();
}
// 第二步,在webbook中添加一个sheet,对应Excel文件中的sheet
HSSFSheet sheet = wb.createSheet(sheetName);
// 第三步,在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制short
HSSFRow row = sheet.createRow(0);
// 第四步,创建单元格,并设置值表头 设置表头居中
HSSFCellStyle style = wb.createCellStyle();
// 创建一个居中格式
style.setAlignment(HorizontalAlignment.CENTER);
HSSFCell cell = null;
//创建标题
for (int i = 0; i < title.length; i++) {
cell = row.createCell(i);
cell.setCellValue(title[i]);
cell.setCellStyle(style);
sheet.setColumnWidth(i, 20 * 256 + 200);
}
HSSFCellStyle contentStyle = wb.createCellStyle();
// 设置单元格自动换行
contentStyle.setWrapText(true);
contentStyle.setAlignment(HorizontalAlignment.LEFT);
contentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
//创建内容
for (int i = 0; i < values.length; i++) {
row = sheet.createRow(i + 1);
for (int j = 0; j < values[i].length; j++) {
sheet.setDefaultColumnStyle(j, contentStyle);
sheet.setColumnWidth(j, 20 * 256 + 200);
row.createCell(j).setCellValue(values[i][j]);
}
}
return wb;
}
public static HSSFWorkbook getHSSFWorkbookImg(String sheetName, String[] title, String[][] values, HSSFWorkbook wb, ByteArrayOutputStream outStream) {
// 第一步,创建一个webbook,对应一个Excel文件
if (wb == null) {
wb = new HSSFWorkbook();
}
// 第二步,在webbook中添加一个sheet,对应Excel文件中的sheet
HSSFSheet sheet = wb.createSheet(sheetName);
// 第三步,在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制short
HSSFRow row = sheet.createRow(0);
// 第四步,创建单元格,并设置值表头 设置表头居中
HSSFCellStyle style = wb.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER); // 创建一个居中格式
HSSFCell cell = null;
//创建标题
for (int i = 0; i < title.length; i++) {
cell = row.createCell(i);
cell.setCellValue(title[i]);
cell.setCellStyle(style);
}
//创建内容
for (int i = 0; i < values.length; i++) {
row = sheet.createRow(i + 1);
for (int j = 0; j < values[i].length; j++) {
row.createCell(j).setCellValue(values[i][j]);
}
}
// 将图片写入流中
// 利用HSSFPatriarch将图片写入EXCEL
HSSFPatriarch patri = sheet.createDrawingPatriarch();
HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 0, 0,
(short) 0, 1, (short) 1, 3);
patri.createPicture(anchor, wb.addPicture(
outStream.toByteArray(), HSSFWorkbook.PICTURE_TYPE_PNG));
return wb;
}
public static void setResponseHeader(HttpServletResponse response, String fileName) {
try {
try {
fileName = new String(fileName.getBytes(), "ISO8859-1");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
response.setContentType("application/vnd.ms-excel;charset=utf-8");
// response.setContentType("application/octet-stream;charset=ISO8859-1");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
response.addHeader("Pargam", "no-cache");
response.addHeader("Cache-Control", "no-cache");
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static InputStream getInputStream(String path) {
InputStream inputStream = null;
HttpURLConnection httpURLConnection = null;
try {
URL url = new URL(path);
if (url != null) {
httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setConnectTimeout(3000);
httpURLConnection.setRequestMethod("GET");
int responseCode = httpURLConnection.getResponseCode();
if (responseCode == 200) {
inputStream = httpURLConnection.getInputStream();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return inputStream;
}
/**
* @param @param fileNames
* @param @param request
* @param @return 设定文件
* @return String 返回类型
* @throws
* @Title: encodeFileName
* @Description: 导出文件转换文件名称编码
*/
public static String encodeFileName(String fileNames, HttpServletRequest request) {
String codedFilename = fileNames;
try {
String agent = request.getHeader("USER-AGENT");
if ((null != agent && -1 != agent.indexOf("MSIE")) || (null != agent
&& -1 != agent.indexOf("Trident")) || (null != agent && -1 != agent.indexOf("Edge"))) {// ie浏览器及Edge浏览器
codedFilename = URLEncoder.encode(fileNames, "UTF-8");
}
} catch (Exception e) {
e.printStackTrace();
}
return codedFilename;
}
}
package cn.wisenergy.chnmuseum.party.common.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
public class FastJsonHttpMessageConverter extends AbstractHttpMessageConverter<Object> {
public final static Charset UTF8 = Charset.forName("UTF-8");
private Charset charset = UTF8;
private SerializerFeature[] serializerFeature;
@Override
protected boolean supports(Class<?> clazz) {
return true;
}
@Override
protected Object readInternal(Class<? extends Object> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream in = inputMessage.getBody();
byte[] buf = new byte[1024];
for (;;) {
int len = in.read(buf);
if (len == -1) {
break;
}
if (len > 0) {
baos.write(buf, 0, len);
}
}
byte[] bytes = baos.toByteArray();
if (charset == UTF8) {
return JSON.parseObject(bytes, clazz);
} else {
return JSON.parseObject(bytes, 0, bytes.length, charset.newDecoder(), clazz);
}
}
@Override
protected void writeInternal(Object obj, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
OutputStream out = outputMessage.getBody();
byte[] bytes;
if (charset == UTF8) {
if (serializerFeature != null) {
bytes = JSON.toJSONBytes(obj, serializerFeature);
} else {
bytes = JSON.toJSONBytes(obj, SerializerFeature.WriteDateUseDateFormat);
}
} else {
String text;
if (serializerFeature != null) {
text = JSON.toJSONString(obj, serializerFeature);
} else {
text = JSON.toJSONString(obj, SerializerFeature.WriteDateUseDateFormat);
}
bytes = text.getBytes(charset);
}
out.write(bytes);
}
}
package cn.wisenergy.chnmuseum.party.common.util;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
public class ResponseUtil {
public static void write(HttpServletResponse response,Object o)throws Exception{
response.setContentType("text/html;charset=utf-8");
PrintWriter out=response.getWriter();
out.println(o.toString());
out.flush();
out.close();
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment