基于springboot+mysql+Shiro实现的宠物医院管理系统
1.项目介绍
系统主要为用户提供了管理员权限的用户,实现了前台查看客户信息、在线添加预约等;后台管理医生坐诊信息、管理就诊信息、修改密码,管理公告、管理宠物分类、管理就诊、管理用户、修改密码等。在设计方面,本系统采用MVC模式,同时使用JSP技术进行动态页面的设计,使用Ajax进行页面异步交互。后台数据库选用mysql数据库。
前台显示医院文化信息,可在线挂号,在线预约,在线查看专家信息和宠物常见病治疗方法,可充值享受专家1v1在线服务后台显示会诊宠物信息,医院人员信息,医生信息,医院人员排班,人员调休,打卡情况,工资奖金,手术安排等。
1.1 软件架构
1.2 使用技术
SpringBoot(2.2.7) + MySQL + Thymeleaf + Shiro + WebSocket + BootStrap4 + Log4J
本文以实现一个宠物医院管理系统-宠物看病预约网为目标,从环境搭建到编码实现全过程讲述:
-
使用javaweb、J2EE来构建宠物医院管理系统-宠物看病预约网,环境使用最新版jdk和tomcat,配合mysql数据库
-
开发工具使用idea(也可以使用eclipse),数据库管理工具使用Navicat Premium
-
开发框架使用JavaBean Servlet MVC结构
-
在项中会引入My97DatePicker作为前端日期时间选择工具,使用fckeditor作为富媒体编辑器(也可以使用百度的ueditor)
-
使用DWR(Direct Web Remoting)用于改善web页面与Java类交互,实现远程服务器端AJAX读取登录数据
-
使用JSTL(Java server pages standarded tag library,即JSP标准标签库),此库是由JCP(Java community Proces)所制定的标准规范,它主要提供给Java Web开发人员一个标准通用的标签库,并由Apache的Jakarta小组来维护。开发人员可以利用这些标签取代JSP页面上的Java代码,从而提高程序的可读性,降低程序的维护难度
2.数据库设计
2.1 表结构
医生表
信息表
排班表
手术排班表
权限用户表
宠物表
2.2 E-R图
3.项目实现
3.1 工具类
阿里云短信接口
```java public class AliyunMsg { public static void main(String[] args) { } public static String aliThree(String phone ,String code){
String host = "https://smslong.shumaidata.com";
String path = "/sms/sendLong";
String method = "POST";
String appcode = "24db86ba9d994cdba1a6aae0dabb5912";
Map<String, String> headers = new HashMap<String, String>();
//最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
headers.put("Authorization", "APPCODE " + appcode);
Map<String, String> querys = new HashMap<String, String>();
querys.put("receive", phone);
querys.put("tag", code);
querys.put("templateId", "M09DD535F4");
Map<String, String> bodys = new HashMap<String, String>();
try {
/**
* 重要提示如下:
* HttpUtils请从
* https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
* 下载
*
* 相应的依赖请参照
* https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
*/
HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
System.out.println(response.toString());
//获取response的body
//System.out.println(EntityUtils.toString(response.getEntity()));
} catch (Exception e) {
e.printStackTrace();
return "fail";
}
return code;
}
} ```
邮件发送功能
java
@Component
@EnableAsync//开启异步注解
public class EmailUtils {
@Autowired
JavaMailSenderImpl mailSender;
@Async
public String sendEmail(String email,String code) {
MimeMessage mimeMessage = mailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true,"utf-8");
//主题
helper.setSubject("来自煮鱼宠物医院的一封邮件");
//正文
helper.setText("【煮鱼宠物医院】您的验证码为["+code+"]您正进行身份验证,打死不告诉别人!",true);
//附件
// helper.addAttachment("test.jpg",new File("C:\\Users\\Administrator\\Desktop\\1.jpg"));
// helper.addAttachment("test2.jpg",new File("C:\\Users\\Administrator\\Desktop\\1.jpg"));
//收件人
helper.setTo(email);
helper.setFrom("wzy990506@qq.com");
mailSender.send(mimeMessage);
} catch (MessagingException e) {
e.printStackTrace();
return "fail";
}
return "success";
}
public String remindEmail(String email,String name,String date,String msg) {
MimeMessage mimeMessage = mailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true,"utf-8");
//主题
helper.setSubject("来自煮鱼宠物医院的一封邮件");
//正文
helper.setText("【煮鱼宠物医院】 您好"+name+"医生,今天"+date+"有您的手术,是"+msg+"的一台手术,不要迟到了呀 -----由【煮鱼宠物医院】手动提醒",true);
//附件
// helper.addAttachment("test.jpg",new File("C:\\Users\\Administrator\\Desktop\\1.jpg"));
// helper.addAttachment("test2.jpg",new File("C:\\Users\\Administrator\\Desktop\\1.jpg"));
//收件人
helper.setTo(email);
helper.setFrom("wzy990506@qq.com");
mailSender.send(mimeMessage);
} catch (MessagingException e) {
e.printStackTrace();
return "fail";
}
return "success";
}
}
HTTP请求工具类
java
private static String buildUrl(String host, String path, Map<String, String> querys) throws UnsupportedEncodingException {
StringBuilder sbUrl = new StringBuilder();
sbUrl.append(host);
if (!StringUtils.isBlank(path)) {
sbUrl.append(path);
}
if (null != querys) {
StringBuilder sbQuery = new StringBuilder();
for (Map.Entry<String, String> query : querys.entrySet()) {
if (0 < sbQuery.length()) {
sbQuery.append("&");
}
if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) {
sbQuery.append(query.getValue());
}
if (!StringUtils.isBlank(query.getKey())) {
sbQuery.append(query.getKey());
if (!StringUtils.isBlank(query.getValue())) {
sbQuery.append("=");
sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8"));
}
}
}
if (0 < sbQuery.length()) {
sbUrl.append("?").append(sbQuery);
}
}
return sbUrl.toString();
}
private static HttpClient wrapClient(String host) {
HttpClient httpClient = new DefaultHttpClient();
if (host.startsWith("https://")) {
sslClient(httpClient);
}
return httpClient;
}
private static void sslClient(HttpClient httpClient) {
try {
SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] xcs, String str) {}
public void checkServerTrusted(X509Certificate[] xcs, String str) {}
};
ctx.init(null, new TrustManager[] { tm }, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx);
ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager ccm = httpClient.getConnectionManager();
SchemeRegistry registry = ccm.getSchemeRegistry();
registry.register(new Scheme("https", 443, ssf));
} catch (KeyManagementException ex) {
throw new RuntimeException(ex);
} catch (NoSuchAlgorithmException ex) {
throw new RuntimeException(ex);
}
}
3.2 WebSocket通信实现
java
@ServerEndpoint("/websocket/${sid}")
@Component
public class WebSocketServer {
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static int onlineCount = 0;
//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
//与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session;
//接收sid
private String sid = "";
@OnOpen
public void onOpen(Session session, @PathParam("sid") String sid) {
this.session = session;
webSocketSet.add(this); //加入set中
addOnlineCount(); //在线数加1
System.out.println(("有新窗口开始监听:" + sid + ",当前在线人数为" + getOnlineCount()));
this.sid = sid;
try {
sendMessage("连接成功");
} catch (IOException e) {
System.out.println(("websocket IO异常"));
}
}
// 连接关闭调用的方法
@OnClose
public void onClose() {
webSocketSet.remove(this); //从set中删除
subOnlineCount(); //在线数减1
System.out.println(("有一连接关闭!当前在线人数为" + getOnlineCount()));
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message, Session session) {
System.out.println(("收到来自窗口" + sid + "的信息:" + message));
//群发消息
for (WebSocketServer item : webSocketSet) {
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
System.out.println(("发生错误"));
error.printStackTrace();
}
/**
* 实现服务器主动推送
*/
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
/**
* 群发自定义消息
*/
public static void sendInfo(String message, @PathParam("sid") String sid) throws IOException {
System.out.println(("推送消息到窗口" + sid + ",推送内容:" + message));
for (WebSocketServer item : webSocketSet) {
try {
//这里可以设定只推送给这个sid的,为null则全部推送
if (sid == null) {
item.sendMessage(message);
} else if (item.sid.equals(sid)) {
item.sendMessage(message);
}
} catch (IOException e) {
continue;
}
}
}
java
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
//表示定义一个前缀为”/chat“的endPoint 并开启withSockJS支持 SockJS可以解决浏览器对WebSocket兼容的问题,客户端可以
//通过这里配置的URL来建立WebSocket连接
registry.addEndpoint("/chat").withSockJS();
// registry.addEndpoint("/p2p").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
//表示设置消息代理的前缀 即如果消息的前缀是“/topic”,就会把消息转发给消息代理人(broker),再有消息代理人将信息广播给当前连接的客户端
registry.enableSimpleBroker("/topic","/queue");
//表示配置一个或多个前缀 通过这些前缀过滤出需要被注解方法处理的消息。例如前缀“/app”的destination可以通过@MessageMapping注解的使用方法
//处理,而其他的destination(例如”/topic“ ”/queue“)将直接交给broker处理
registry.setApplicationDestinationPrefixes("/app");
}
3.3 主要功能代码
java
@RequestMapping("/toDoctorInfo")
public String toDoctorInfo(String name, Model model){
System.out.println(name);
List<MessagePojo> messagePojos = messageService.selectMessage();
//根据名字获取一个医生信息
List<DoctorPojo> doctor = doctorService.selectDoctorByName(name);
//获取未读消息 messageStatusSize的个数
int messageStatusSize = 0;
for (MessagePojo messagePojo : messagePojos) {
int message_status = messagePojo.getMessage_status();
if (message_status == 0) {
messageStatusSize++;
}
}
String messageStatusSizes = messageStatusSize + "条未读消息";
model.addAttribute("doctor",doctor);
model.addAttribute("messageStatusSize", messageStatusSizes);
model.addAttribute("msgs", messagePojos);
return "home/doctorInfo";
}
@RequestMapping("/toDoctors")
public String toDoctors(Model model) {
List<OperationPlusPojo> operationPlusPojos = operationPlusService.selectOperationPlus();
List<MessagePojo> messagePojos = messageService.selectMessage();
//根据名字获取一个医生信息
List<DoctorPojo> doctor = doctorService.selectDoctor();
//获取未读消息 messageStatusSize的个数
int messageStatusSize = 0;
for (MessagePojo messagePojo : messagePojos) {
int message_status = messagePojo.getMessage_status();
if (message_status == 0) {
messageStatusSize++;
}
}
String messageStatusSizes = messageStatusSize + "条未读消息";
model.addAttribute("operationPlusPojos",operationPlusPojos);
model.addAttribute("doctor",doctor);
model.addAttribute("messageStatusSize", messageStatusSizes);
model.addAttribute("msgs", messagePojos);
return "home/doctors";
}
@PostMapping("/sendEmailAndPhone")
@ResponseBody
public String sendEmailAndPhone(String phoneOrEmail) throws ParseException {
String name = doctorService.selectNameByEmailOrPhone(phoneOrEmail);
List<OperationPlusPojo> list = operationPlusService.selectDateAndMsgByName(name);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date parse = simpleDateFormat.parse("2000-01-01");
String msg = null;
for (OperationPlusPojo operationPlusPojo : list) {
if(parse.before(operationPlusPojo.getOperationplus_date())){
parse=operationPlusPojo.getOperationplus_date();
msg=operationPlusPojo.getOperationplus_msg();
}
}
String format = simpleDateFormat.format(parse);
System.out.println(phoneOrEmail);
emailUtils.remindEmail(phoneOrEmail,name,format,msg);
return "success";
}
@RequestMapping("/toAddDoctor")
public String toAddDoctor(){
return "home/addDoctor";
}
@RequestMapping("/addDoctor")
public String addDoctor(String number,String doctor,String post,String email,String phone,int age,int gender,String level,String msg){
System.out.println(number+doctor+post+email+phone+age+level+gender+msg);
return "redirect:/toDoctors";
}
}
4.项目展示
登录页
国际化
主页
添加问诊信息
消息提醒
查看医生信息
排班
添加手术
404异常页面
参考文献
- 宠物领养Web App的设计与实现(华中科技大学·杨芹)
- 医院管理系统的设计与实现(南昌大学·程进)
- 宠物交易系统的设计与实现(华中科技大学·胡鼎)
- 基于J2EE技术的城市宠物管理系统的设计与实现(电子科技大学·史骏)
- 医院管理系统的设计与实现(南昌大学·程进)
- 基于Java Web的种猪管理系统设计与实现(南京农业大学·张志川)
- 医疗电子商务平台的设计与实现(电子科技大学·唐章琨)
- 基于JavaEE的工厂文档管理系统(武汉科技大学·朱永强)
- 基于SSH的医疗单位事务管理系统的设计与实现(江西农业大学·邱石)
- 宠物领养Web App的设计与实现(华中科技大学·杨芹)
- 基于Java EE平台的个人健康信息管理系统设计与实现(南京邮电大学·贾顺贺)
- 基于SSH的医疗单位事务管理系统的设计与实现(江西农业大学·邱石)
- 基于SSH的医疗单位事务管理系统的设计与实现(江西农业大学·邱石)
- 基于OAuth2.0协议的企业分布式授权系统设计与实现(华中科技大学·支猛)
- 基于SSH的医疗单位事务管理系统的设计与实现(江西农业大学·邱石)
本文内容包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主题。发布者:源码驿站 ,原文地址:https://bishedaima.com/yuanma/35508.html