基于javaweb+mysql的ssm车牌识别停车场管理系统(java+ssm+mysql+jsp+ocr)
运行环境
Java≥8、MySQL≥5.7、Tomcat≥8
开发工具
eclipse/idea/myeclipse/sts等均可配置运行
适用
课程设计,大作业,毕业设计,项目练习,学习演示等
功能说明
基于javaweb+mysql的SSM车牌识别停车场管理系统(java+ssm+mysql+jsp+OCR)
登录:
admin 123456
功能:车牌监控识别(进场)、车辆管理、停车管理、缴费管理等
本项目使用的是腾讯云的文字识别(OCR)服务
<!-- 车辆出场 -->
<update id="carOut">
<![CDATA[
update car set outTime=#{outTime},outPic=#{outPic},carFee=#{carFee},financeType=#{financeType},status=#{status},userName=#{userName},remark=#{remark} where carId=#{carId}
]]>
</update>
<!-- 列表-->
<select id="findAll" parameterType="carVo" resultType="carVo">
<![CDATA[
select * from car
]]>
<if test="cardNo!=null and cardNo!=''">
where cardNo=#{cardNo}
</if>
<if test="status>=0">
status = #{status}
</if>
order by inTime desc
</select>
<select id="count" parameterType="carVo" resultType="int">
<![CDATA[
select count(*) from car
]]>
<where>
<if test="car.cardNo!=null and car.cardNo!=''">
cardNo=#{car.cardNo}
</if>
<if test="car.inTime!=null and car.inTime !='' and car.outTime!=null and car.outTime!=''">
and inTime between '${car.inTime} 00:00:00' and '${car.outTime} 23:59:59'
</if>
</where>
</select>
<select id="findByCarNo" parameterType="carVo" resultType="carVo">
<![CDATA[
select * from car
]]>
<where>
<if test="car.cardNo!=null and car.cardNo!=''">
cardNo=#{car.cardNo}
</if>
<if test="car.inTime!=null and car.inTime !='' and car.outTime!=null and car.outTime!=''">
and inTime between '${car.inTime} 00:00:00' and '${car.outTime} 23:59:59'
</if>
</where>
order by inTime desc limit #{pager.startRow},#{pager.pageRow}
</select>
<!-- 按状态查找 -->
<select id="findByStatus" parameterType="carVo" resultType="carVo">
public class CarApi {
private Logger logger = Logger.getLogger(CarApi.class);
//车牌识别
public RootResp carVerify(String image) {
RootResp result = new RootResp();
try{
Credential cred = new Credential(WeChatConfig.SECRETID, WeChatConfig.SECRETKEY);
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint(WeChatConfig.SERVERIP);
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
//车牌识别
OcrClient ocrclient = new OcrClient(cred,WeChatConfig.AREA,clientProfile);
LicensePlateOCRRequest req = new LicensePlateOCRRequest();
req.setImageBase64(image);
LicensePlateOCRResponse resp = ocrclient.LicensePlateOCR(req);
System.out.println(LicensePlateOCRResponse.toJsonString(resp));
result.setData(LicensePlateOCRResponse.toJsonString(resp));
} catch (TencentCloudSDKException e) {
result.setRet(-1);
result.setMsg(e.toString());
logger.error(e.toString());
}
logger.info(result);
return result;
}
}
}
//注册
@Transactional
public void reg(UserVo user){
userDAO.reg(user);
}
//修改密码
@Transactional
public void pwd(UserVo user){
userDAO.pwd(user);
}
//用户列表
@Transactional
public List<UserVo> userList(){
return userDAO.userList();
}
//修改用户状态
@Transactional
public void updStatus(UserVo user){
userDAO.updStatus(user);
}
//登录
@Transactional
public UserVo login(UserVo user){
return userDAO.login(user);
}
//按用户id查找
@Transactional
public boolean findById(UserVo user){
UserVo u = userDAO.findById(user);
if(u==null){
return true;
}else{
return false;
}
}
//获取参数
@Transactional
public SysSetVo getSet(){
return sysDAO.getSet();
}
//修改参数
return "financeAdd";
}
//缴费
@RequestMapping(value="/financeAdd",method=RequestMethod.POST)
public String financeCar(HttpServletRequest request, CarInfoVo carInfo,FinanceVo finance,ModelMap model) {
CarInfoVo cInfo = dbService.getCarById(carInfo.getCarInfoId());
cInfo.setExpireDate(carInfo.getExpireDate());
dbService.carUpdate(cInfo);
finance.setFinanceType(1);//1:包月收费
finance.setOprTime(new Date());
//从session中获取当前登录的用户信息(车辆管理员)
UserVo user = (UserVo)request.getSession().getAttribute("userinfo");
finance.setUserName(user.getUserName());
finance.setRemark("缴费("+finance.getTotalMoney()+"元)");
dbService.financeAdd(finance);
//更新车辆账户余额
cInfo.setRemainMoney(finance.getTotalMoney());
dbService.updateMoney(cInfo);
List<CarInfoVo> carInfoList = dbService.findCar("");
model.addAttribute("carInfoList", carInfoList);
return "car";
}
}
/**
* 错误码列表
* */
public class ErrorCode {
public static Map<Integer, String> errorMap = new HashMap<Integer, String>();
static{
errorMap.put(9,"qps超过限制,建议处理方式:用户认证升级或者降低调用频率");
errorMap.put(4096,"参数非法,建议处理方式:请检查请求参数是否符合要求");
errorMap.put(12289,"应用不存在,建议处理方式:请检查app_id是否有效的应用标识(AppId)");
errorMap.put(12801,"素材不存在,建议处理方式:请检查app_id对应的素材模版id");
errorMap.put(12802,"素材ID与应用ID不匹配,建议处理方式:请检查app_id对应的素材模版id");
errorMap.put(16385,"缺少app_id参数,建议处理方式:请检查请求中是否包含有效的app_id参数");
errorMap.put(16386,"缺少time_stamp参数,建议处理方式:请检查请求中是否包含有效的time_stamp参数");
errorMap.put(16387,"缺少nonce_str参数,建议处理方式:请检查请求中是否包含有效的nonce_str参数");
errorMap.put(16388,"请求签名无效,建议处理方式:请检查请求中的签名信息(sign)是否有效");
errorMap.put(16389,"缺失API权限,建议处理方式:请检查应用是否勾选当前API所属接口的权限");
finance.setUserName(user.getUserName());
finance.setRemark("【"+carNo+"】:出场,扣款:"+carFee+"元" );
finance.setTotalMoney(carFee);
dbService.financeAdd(finance);
//------更新账户余额----------
carInfo.setRemainMoney(-finance.getTotalMoney());
dbService.updateMoney(carInfo);
}
json.put("msg","【"+carNo+"】:出场,扣款:"+carFee+"元" );
}
}else{//包月停车
remark="包月停车";
car.setFinanceType(1);//1包月
if(c==null){//入库
car.setCarFee(0);
car.setInPic(inPic);
car.setInTime(sdf.format(new Date()));
car.setRemark(remark);
car.setStatus(0);//0未收费
dbService.carIn(car);
json.put("msg","包月车【"+carNo+"】:入场" );
}else{//出库
car.setCarFee(0);
car.setStatus(2);//2包月
car.setOutPic(inPic);
car.setOutTime(sdf.format(new Date()));
car.setRemark(remark);
car.setCarId(c.getCarId());
dbService.carOut(car);
if(carInfo.getDiffDate()>0){
json.put("msg","包月车【"+carNo+"】:出场,还剩"+carInfo.getDiffDate()+"天" );
}else{
json.put("msg","包月车【"+carNo+"】:出场,请及时缴费" );
}
}
}
}else{
json.put("errorCode", resp.getRet());
json.put("msg", "车牌识别失败");
}
/*
* 处理整个系统中日期类型的转换
* 1.实现Converter接口
* 2.实现抽象方法convert,进行处理
* 3.要在spring-web.xml文件里面配置该类,为整个系统服务
* <bean id="dateUtil" class="org.springframework.format.support.FormattingConversionServiceFactoryBean" >
<property name="converters" >
<list>
<bean class="com.ht.base.DateUtil"></bean>
</list>
</property>
</bean>
4.在spring-web.xml里面配置如下代码
<mvc:annotation-driven conversion-service="dateUtil"></mvc:annotation-driven>
* */
public class DateUtil implements Converter<String, Date> {
@Override
public Date convert(String source) {
System.out.println("source="+source);
//实现将字符串转成日期类型(格式是yyyy-MM-dd HH:mm:ss)
SimpleDateFormat dateFormat = null;
if(!StringUtils.isEmpty(source)){
//判断日期字符串是否包含了时间部分
int pos1 = source.indexOf(":");//从左往右查找字符串中第一个冒号的位置
int pos2 = source.lastIndexOf(":");//从右往左查找字符串中第一个冒号的位置
source = source.replace("T", " ");//把字符串中的T替换为空格
if(pos1>0 && pos1 != pos2){
dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}else if(pos1>0 && pos1==pos2){
source = source +":00";
dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}else{
dateFormat = new SimpleDateFormat("yyyy-MM-dd");
}
}
try {
return dateFormat.parse(source);
} catch (Exception e) {
e.printStackTrace();
}
//如果参数绑定失败返回null
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
}
@Controller
@RequestMapping("/user")
public class UserController {
@Resource
DbService dbService;
//首页
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String login() {
return "login";
}
//登录
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String login(HttpServletRequest request, Model model) {
String msg = "";
car.setRemark(remark);
car.setStatus(0);//0未收费
dbService.carIn(car);
json.put("msg","包月车【"+carNo+"】:入场" );
}else{//出库
car.setCarFee(0);
car.setStatus(2);//2包月
car.setOutPic(inPic);
car.setOutTime(sdf.format(new Date()));
car.setRemark(remark);
car.setCarId(c.getCarId());
dbService.carOut(car);
if(carInfo.getDiffDate()>0){
json.put("msg","包月车【"+carNo+"】:出场,还剩"+carInfo.getDiffDate()+"天" );
}else{
json.put("msg","包月车【"+carNo+"】:出场,请及时缴费" );
}
}
}
}else{
json.put("errorCode", resp.getRet());
json.put("msg", "车牌识别失败");
}
}
return json;
}
//显示车辆列表界面
@RequestMapping("/carInfo")
public String carInfo(String carNo,ModelMap model) throws Exception{
if(carNo==null){
carNo="";
}
List<CarInfoVo> carInfoList = dbService.findCar(carNo);
model.addAttribute("carInfoList", carInfoList);
return "car";
}
//显示新增车辆界面
@RequestMapping(value="/carAdd",method=RequestMethod.GET)
public String carAdd(ModelMap model) throws Exception{
CarInfoVo carInfo = new CarInfoVo();
model.addAttribute("carInfo",carInfo);
return "carInfo";
}
//保存车辆信息
@RequestMapping(value="/carAdd",method=RequestMethod.POST)
public String carAdd(CarInfoVo carInfo,ModelMap model) {
try{
if(carInfo.getCarInfoId()==0){
carInfo.setRemainMoney(0);
dbService.carAdd(carInfo);
}else{
<li><span>手机号码:</span><input type="text" name="mobile" id="mobile" class="iptxs"></li>
<li><span>登录密码:</span><input type="password" name="password" id="password" class="iptxs"></li>
<li><span>确认密码:</span><input type="password" name="confirmPwd" id="confirmPwd" class="iptxs"></li>
<li><span> </span><a class="kaoshi_btn" href="javascript:void(0);" onclick="check();">保存</a></li>
</ul>
</div>
</div>
</div>
</body>
</html>
<?xml version="1.0" encoding="UTF-8" ?>
<!-- mybatis的dtd文件 -->
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace属性: 用于指定指向那个接口 -->
<mapper namespace="com.ht.mapper.CarDAO">
<!-- 车辆入场 -->
<insert id="carIn" parameterType="carVo">
<![CDATA[
insert into car(cardNo,inTime,inPic,carFee,status,userName) values(#{cardNo},#{inTime},#{inPic},#{carFee},#{status},#{userName})
]]>
</insert>
<!-- 车辆出场 -->
<update id="carOut">
<![CDATA[
update car set outTime=#{outTime},outPic=#{outPic},carFee=#{carFee},financeType=#{financeType},status=#{status},userName=#{userName},remark=#{remark} where carId=#{carId}
]]>
</update>
<!-- 列表-->
<select id="findAll" parameterType="carVo" resultType="carVo">
<![CDATA[
select * from car
]]>
<if test="cardNo!=null and cardNo!=''">
where cardNo=#{cardNo}
</if>
<if test="status>=0">
status = #{status}
</if>
order by inTime desc
</select>
<select id="count" parameterType="carVo" resultType="int">
<![CDATA[
select count(*) from car
]]>
<where>
<if test="car.cardNo!=null and car.cardNo!=''">
cardNo=#{car.cardNo}
</if>
<if test="car.inTime!=null and car.inTime !='' and car.outTime!=null and car.outTime!=''">
and inTime between '${car.inTime} 00:00:00' and '${car.outTime} 23:59:59'
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
/**
* 解密
*
* @param content
* 待解密内容
* @param password
* 解密密钥
* @return
*/
public static byte[] decryptAES(byte[] content, String password) {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128, new SecureRandom(password.getBytes()));
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Cipher cipher = Cipher.getInstance("AES");// 创建密码器
cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
byte[] result = cipher.doFinal(content);
return result; // 加密
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
}
public void setCarNo(String carNo) {
this.carNo = carNo;
}
public int getFinanceType() {
return financeType;
}
public void setFinanceType(int financeType) {
this.financeType = financeType;
}
public float getTotalMoney() {
return totalMoney;
}
public void setTotalMoney(float totalMoney) {
this.totalMoney = totalMoney;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Date getOprTime() {
return oprTime;
}
public void setOprTime(Date oprTime) {
this.oprTime = oprTime;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
}
public class PageObject {
//当前页
private int cur_page=1;
//每页显示的记录数
public static int pageRow=30;
//记录总数
private int totalRows;
//开始位置
private int startRow;
//数据
private List datas;
System.out.println(LicensePlateOCRResponse.toJsonString(resp));
result.setData(LicensePlateOCRResponse.toJsonString(resp));
} catch (TencentCloudSDKException e) {
result.setRet(-1);
result.setMsg(e.toString());
logger.error(e.toString());
}
logger.info(result);
return result;
}
}
public class CarInfoVo implements Serializable {
private int carInfoId;
private String carNo;
private String userName;
private String mobile;
private String startDate;
private String expireDate;
private String remark;
private float remainMoney;
public float getRemainMoney() {
return remainMoney;
}
public void setRemainMoney(float remainMoney) {
this.remainMoney = remainMoney;
}
private int diffDate;
public int getDiffDate() {
return diffDate;
}
public void setDiffDate(int diffDate) {
this.diffDate = diffDate;
}
public int getCarInfoId() {
return carInfoId;
}
/**
* 信任管理器
*
*/
public class MyX509TrustManager implements X509TrustManager {
// 检查客户端证书
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
// 检查服务器端证书
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
// 返回受信任的X509证书数组
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
public interface CarDAO {
//入库
public void carIn(CarVo car);
//出库
public void carOut(CarVo car);
//查询列表
public List<CarVo> findAll(CarVo car);
public int count(@Param("car") CarVo car,@Param("pager") PageObject pager);
String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
if (shaHex.length() < 2) {
hexString.append(0);
}
hexString.append(shaHex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
public static String MD5(String input) {
try {
// 获得MD5摘要算法的 MessageDigest 对象
MessageDigest mdInst = MessageDigest.getInstance("MD5");
// 使用指定的字节更新摘要
mdInst.update(input.getBytes());
// 获得密文
byte[] md = mdInst.digest();
// 把密文转换成十六进制的字符串形式
StringBuffer hexString = new StringBuffer();
// 字节数组转换为 十六进制 数
for (int i = 0; i < md.length; i++) {
String shaHex = Integer.toHexString(md[i] & 0xFF);
if (shaHex.length() < 2) {
hexString.append(0);
}
hexString.append(shaHex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return "";
}
/**
* 加密
*
* @param content
* 需要加密的内容
* @param password
* 加密密码
* @return
*/
public static byte[] encryptAES(String content, String password) {
try {
public String getCardNo() {
return cardNo;
}
public void setCardNo(String cardNo) {
this.cardNo = cardNo;
}
public String getInTime() {
return inTime;
}
public void setInTime(String inTime) {
this.inTime = inTime;
}
public String getOutTime() {
return outTime;
}
public void setOutTime(String outTime) {
this.outTime = outTime;
}
public String getInPic() {
return inPic;
}
public void setInPic(String inPic) {
this.inPic = inPic;
}
public String getOutPic() {
return outPic;
}
public void setOutPic(String outPic) {
this.outPic = outPic;
}
public float getCarFee() {
return carFee;
}
public void setCarFee(float carFee) {
this.carFee = carFee;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!doctype html>
<html>
<head>
<base href="<%=basePath%>">
<title>车牌识别停车场管理系统</title>
<jsp:include page="/IncludeJS.jsp"></jsp:include>
<script type="text/javascript">
var isSuccess=false;
function toLogin(){
var code = $("#loginName").val();
var pwd = $("#password").val();
var randCode = $("#randCode").val();
if(code==""||pwd==""||randCode=="") {
alert("请填写完整用户名,密码和验证码");
return false;
}
$("#loginForm").submit();
return true;
}
function refresh(){
document.getElementById("codes").src= '${pageContext.request.contextPath }/enimg.jsp?'+Math.random();
}
if("${msg}"!=null&&"${msg}".length>0){
alert("${msg}");
}
</script>
</head>
<body>
<div class="login_b">
<div class="header"><!--<div class="header_logo"><img src="images/logo.png" width="140" height="47"></div> -->
<p class="header_con">车牌识别停车场管理系统</p>
</div>
<div class="lgn_bx">
<div class="login_con">
<div class="lgn_con">
<div class="login_con_bx">
<div class="login_tit">用户登录</div>
<div class="login_con_bx_t"><span>账号登录</span></div>
<div>
<ul class="login_con_bx_bl">
<form action="${pageContext.request.contextPath}/user/login" id="loginForm" method="post">
<li style="cursor: hand">
<span style="cursor: hand"><img src="${pageContext.request.contextPath}/images/login_icon02.png" /></span>
<div class="lgtel">
<input type="text" name="loginName" id="loginName" placeholder="请输入您的账号" class="telbt" onfocus="clearvalue(this);"/>
</div>
</li>
return "financeAdd";
}
//缴费
@RequestMapping(value="/financeAdd",method=RequestMethod.POST)
public String financeCar(HttpServletRequest request, CarInfoVo carInfo,FinanceVo finance,ModelMap model) {
CarInfoVo cInfo = dbService.getCarById(carInfo.getCarInfoId());
cInfo.setExpireDate(carInfo.getExpireDate());
dbService.carUpdate(cInfo);
finance.setFinanceType(1);//1:包月收费
finance.setOprTime(new Date());
//从session中获取当前登录的用户信息(车辆管理员)
UserVo user = (UserVo)request.getSession().getAttribute("userinfo");
finance.setUserName(user.getUserName());
finance.setRemark("缴费("+finance.getTotalMoney()+"元)");
dbService.financeAdd(finance);
//更新车辆账户余额
cInfo.setRemainMoney(finance.getTotalMoney());
dbService.updateMoney(cInfo);
List<CarInfoVo> carInfoList = dbService.findCar("");
model.addAttribute("carInfoList", carInfoList);
return "car";
}
}
/**
* 错误码列表
* */
public class ErrorCode {
public static Map<Integer, String> errorMap = new HashMap<Integer, String>();
static{
errorMap.put(9,"qps超过限制,建议处理方式:用户认证升级或者降低调用频率");
errorMap.put(4096,"参数非法,建议处理方式:请检查请求参数是否符合要求");
errorMap.put(12289,"应用不存在,建议处理方式:请检查app_id是否有效的应用标识(AppId)");
errorMap.put(12801,"素材不存在,建议处理方式:请检查app_id对应的素材模版id");
errorMap.put(12802,"素材ID与应用ID不匹配,建议处理方式:请检查app_id对应的素材模版id");
errorMap.put(16385,"缺少app_id参数,建议处理方式:请检查请求中是否包含有效的app_id参数");
errorMap.put(16386,"缺少time_stamp参数,建议处理方式:请检查请求中是否包含有效的time_stamp参数");
errorMap.put(16387,"缺少nonce_str参数,建议处理方式:请检查请求中是否包含有效的nonce_str参数");