healthCode

项目整体结构

配置文件:web.xml, spring.xml, springmvc.xml, mybatis.xml

包:controller, dto, service, dao, domain

 

web.xml

<!-- 注册ServletContextListener监听器。当ServletContext被创建时,该监听器会根据spring.xml创建出root ioc容器 -->
<listener>   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring.xml</param-value>
</context-param>
<!-- 将所有请求交给DispatcherServlet处理。在类中会根据springmvc.xml创建出servlet ioc容器(该容器是root ioc容器的子容器。寻找bean时会先在该容器中寻找,若没找到则委托root容器寻找。) -->
<servlet>
    <servlet-name>app-servlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>app-servlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

spring.xml

<!-- 将数据库连接池交给容器管理 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="com.mysql.jdbc.Driver" />
    <property name="jdbcUrl" value="..." />
    <property name="user" value="root" />
    <property name="password" value="xiemingrui" />
</bean>
<!-- 将mybatis的SqlSessionFactory交给容器管理 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="mapperLocations" value="classpath:com/xmr/dao/*Mapper.xml"/>
    <property name="configLocation" value="classpath:mybatis.xml" />
</bean>
<!-- 将mybatis创建的代理类(即DAO)交给容器管理(dao包中放的只是接口而不是DAO,MapperScannerConfigurer则是将mybatis通过动态代理创建的DAO交给容器) -->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.xmr.dao" />
</bean>

 

springmvc.xml

<!-- 将controller, service类交给容器管理 -->
<context:component-scan base-package="com.xmr.controller"/>
<context:component-scan base-package="com.xmr.service"/>
<!-- 配置静态资源,使得这些url不会被mapping到DispatcherServlet中处理 -->

<!-- <mvc:annotation-driven/> -->

<!-- <mvc:resources mapping="/res/**"  location="/res/"/> -->

 

mybatis.xml

<!-- 配置延迟加载 -->
<configuration>
    <settings>
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>
</configuration>

 

controller:

--将从request中获取的参数封装成DTO(Data Transfer Object)

--将DTO作为参数,调用service层的方法,进行业务处理,获取service层返回的DTO

--将service层返回的DTO,放进request的attribute中,forward给jsp去展示

 

service:

--将从controller层接收到的DTO封装成DO(Domain Object)

--将DO作为参数,调用dao层的方法,操作数据库,获取dao层返回的DO

--将dao层返回的DO,封装为DTO,返回给controller层

 

dao:

--接收DO作为参数,操作数据库,返回DO

 

String管理各个类的过程:

1. 当Context被创建时,触发org.springframework.web.context.ContextLoaderListener监听器中相应方法的执行。该方法会根据spring.xml配置文件创建出一个ioc容器(ApplicationContext),容器中包含了dataSource、sqlSessionFactory、

mapperScannerConfigurer这三个bean,而mapperScannerConfigurer

2. 当Tomcat启动时,会创建org.springframework.web.servlet.DispatcherServlet类的单例,并执行该Servlet的init方法(因为配置了load-on-startup)。init方法中会根据springmvc.xml配置文件创建出一个ioc容器(ApplicationContext),该容器中包含了com.xmr.controller/service包下的加了注解的相应Controller bean和Service bean。

3. 每个bean默认的scope为singleton,所以在创建ApplicationContext时,就会触发这些bean单例的创建。在创建mapperScannerConfigurer bean的单例时,其会扫描com.xmr.dao包下的所有DAO接口,并生成这些接口的代理对象,将这些对象放入容器中。在创建Controller bean时,因为Controller bean中依赖了一系列的Service bean,spring会去容器中寻找这些Service bean注入,而Service bean中又依赖了一系列的DAO bean,spring会去容器中找到这些DAO bean注入,最终完成Controller单例的创建。

4. 当接收到请求时,Tomacat调用DispatcherServlet的service方法。其service方法中会根据请求的url,从容器中取出相应的Controller实例,调用其相应方法处理请求。

 

项目前台功能:

1. 获取申报入口查询表单

controller:

--无接收参数

--调用service层的方法,获取仅包含了国家名的CountryDTO数组;调用service层的方法,获取仅包含了省份名的ProvinceDTO数组

--将service层返回的两个DTO数组,放进request的attribute中,forward给jsp,供用户从中选择相应出发中转国家和到达省份。

 

service:

--无接收参数

--调用countries的dao方法,获取全部的CountryDO;调用provinces的dao方法,获取全部的ProvinceDO

--将dao层返回的DO,封装为仅包含国家名的CountryDTO、仅包含省份名的ProvinceDTO,返回给controller层

 

countries的dao:

--返回全部的CountryDO

provinces的dao

--返回全部的ProvinceDO

 

2. 申报入口查询

===============================================================================

插:ReportTypeQueryDTO

ArrayList<String> countries;

String queryResult;

===============================================================================

 

controller:

--从request中获得始发地和中转地国家,封装进reportTypeQueryDTO的countries中。

--将DTO作为参数,调用service层的方法,获取含有queryResult的DTO。

--将从service层获取的DTO,放进request的attribute中,forward给jsp去展示

 

service:

--将从controller层接收到的DTO中的国家名封装成country DO数组。

--将每个country DO作为参数,调用countries表的dao方法,获取到完整的country DO。

统计所有country DO的type字段。若包含>0个type 1国家,则在queryResult中设置为核酸检测入口;若包含0个type 1国家,>0个type 2国家,则在queryResult中设置为健康申报入口;若包含0个type 1国家和0个type 2国家,则在queryResult中设置为可无需任何申报。

--将DTO返回给controller层

 

dao:

--接收country DO作为参数,查询countries表,返回完整的country DO。

3. 获取日常健康申报表单

controller:查看HttpSession中key为user的键值对,值是否为空。

若为空,则forward到登录界面jsp;若不为空,则forward到日常健康申报表单jsp。

 

4. 日常健康申报

===============================================================================

插:DailyReportDO

UserDO userDO;

int state;

Date date;

 

插:DailyReportDTO

HashMap<String, String> report;

boolean hint;

===============================================================================

 

controller:

--将从request中获取的参数封装进DailyReportDTO

--将DTO作为参数,调用service层的方法,对健康申报进行记录,获取到返回的DTO

--若返回的DTO中的hint为空,则申报成功重定向到申报成功页面;否则,将DTO放进request的attribute中,forward给申报表单jsp展示错误信息。

 

service:

--检查DTO中的数据正确性。若有问题,则在hint中设置相关提示并返回;若无问题,则根据DTO中的report,判断出健康状态state;从HttpSession中取出userDO;获取当前时间。封装dailyReportDO。

--将dailyReportDO作为参数,调用daily_report的dao方法,存储健康申报记录。

--将DTO返回给controller层。

dao:

--接收dailyReportDO,将其存储进数据库

 

 

 

 

 

 

 

 

 

 

 

 

 

 

5. 出示健康申报二维码

===============================================================================

插:QRCodeDTO  String path; String hint;

 

插:QRCodeManager

public class QRCodeManager {
   private static Map<String, QRCodeInfo>

qrCodeMap = new ConcurrentHashMap<>();
   static {
      ScheduledThreadPoolExecutor pool = new

     ScheduledThreadPoolExecutor(1);
      scheduledThreadPoolExecutor.scheduleAtFixedRate(

new Runnable() {
         @Override
         public void run() {
            checkOutDateQRCode();
         }
      }, 1, 1, TimeUnit.HOURS);
   }

   private static void startQRCodeOutdateCheckThread(){..}

}

qrCodeMap中key为随机生成的字符串,value为QRCodeInfo类,该类包含二维码颜色信息、UserInfoDO对象、二维码图片路径、创建时间、最大存活时间、二维码类别信息(健康申报类型二维码)。

使用ScheduledThreadPoolExecutor定时执行重复任务。每小时执行一次checkOutDateSession方法,该方法会对qrCodeMap进行遍历,用系统的当前时间减去每个QRCodeInfo中记录的创建时间,若差值超过了最大存活时间,则从qrCodeMap中删除该二维码记录,并去到相应路径下删除二维码图片。

===============================================================================

 

controller:

--无接收参数

--调用service层的方法,获取service层返回的QRCodeDTO

--将DTO放进request的attribute中。若DTO中的hint为空,则forward到二维码展示页面进行二维码展示;否则,forward到错误提示页面展示错误信息。

 

service:

--无接收参数

--将从HttpSession中获取的UserDO作为参数(为空则在hint中设置相关提示并返回),调用daily_report的dao方法,获取到该用户的所有健康申报记录(DailyReportDO数组)。从DailyReportDO数组中获取到过去14天的记录。若无法获取到14天前的记录,则判定为红码;若14天记录中有出现不健康状态,则判定为红码;若14天记中有相邻两条记录间隔超过24小时,判定为红码;其余为绿码。

获取UserInfoDO:以UserDO作为参数调用user_info表的dao,获取到UserInfoDO。若获取到的UserInfoDO为空,则在hint中设置相关提示并返回。

使用‘url?qrCode=随机字符串'这串字符串生成二维码图片存储在相应路径中(文件名为那串随机字符串)。

向QRCodeManager中插入一条key为随机字符串,value为QRCodeInfo对象的键值对。

--将二维码图片的路径封装进QRCodeDTO,返回给controller。

 

dao:

--接收UserDO作为参数,查询该用户的所有健康申报记录,返回DailyReportDO数组。

user_info表的dao:

--接收UserDO作为参数,查询该用户的实名认证信息,返回UserInfoDO。

 

6. 获取注册表单

直接forward到注册表单jsp

 

7. 注册

===============================================================================
插:RegisterDTO

String userName;

String password;

String hint;

===============================================================================

controller:

--将从request中获取到的账号、密码封装进RegisterDTO

--将RegisterDTO作为参数,调用service层的方法,将信息存进user表中,并获取service层返回的RegisterDTO

--若service层返回的RegisterDTO中的hint为空,则注册成功重定向到注册成功页面;否则,将RegisterDTO放进request的attribute中,forward给注册表单jsp展示错误信息。

 

service:

--检查从controller层接收到的RegisterDTO。若用户名重复,则在RegisterDTO中设置相应hint返回;若无问题,则封装成UserDO

--以UserDO作为参数,调用user表的dao方法,将数据存入数据库中

--将DTO返回给controller层

 

dao:

--接收UserDO作为参数,将相应数据存储进数据库

 

8. 获取登录表单

直接forward到登录表单jsp

 

 

 

 

9. 登录

===============================================================================
插:LoginDTO

String userName;

String password;

String hint;
===============================================================================

controller:

--将从request中获取到的账号、密码封装进LoginDTO

--将LoginDTO作为参数,调用service层的方法,获取service层返回的LoginDTO

--若service层返回的LoginDTO中的hint为空,则登录成功重定向到主页;否则,将LoginDTO放进request的attribute中,forward给登录表单jsp展示错误信息。

 

service:

--将从controller层接收到的LoginDTO中的userName封装成UserDO

--以该UserDO为参数,调用user表的dao,查找用户,获取到完整的UserDO。若获取到的UserDO为空或UserDO中的密码和LoginDTO中的密码不一致,则在LoginDTO的hint中设置相应提示信息;

--将LoginDTO返回给controller层

 

user表的dao:

--接收UserDO作为参数,查询数据库,返回完整的UserDO

 

10. 获取实名认证表单

controller:查看HttpSession中key为user的键值对,值是否为空。

若为空,则forward到登录表单jsp;若不为空,则forward到实名认证表单jsp。

 

11. 实名认证

===============================================================================
插:UserInfoDTO

...some personal information...

String hint;
===============================================================================

controller:

--将从request中获取到的实名认证信息封装成UserInfoDTO。为获取到的图片生成独一无二的id字符串作为图片的文件名,存储在以该用户userName命名的文件夹下(userName从HttpSession中的UserDO中获得)。DTO中对应记录的则是图片的路径。

--将DTO作为参数,调用service层的方法,获取service层返回的DTO

--若service层返回的UserInfoDTO中的hint为空,则提交成功重定向到提交成功页面;否则,将UserInfoDTO放进request的attribute中,forward给实名认证表单jsp展示错误信息。

 

 

service:

--检查从controller层接收到的UserInfoDTO。如有问题,则设置相应hint返回;若无问题,则加上checked=0和user_id后封装成UserInfoDO

--从HttpSessin中获取到UserDO,以UserDO为参数调用user_info的dao获取到UserInfoDO。若UserInfoDO不为空,表示该用户之前提交过实名认证数据,则调用相应dao将原有数据改为当前的UserInfoDO中的数据(checked字段设为0,需重新审核);若UserInfoDO为空,则表示该用户并未提交过实名认证数据,则调用相应dao添加该UserInfoDO进数据库。

--将UserInfoDTO返回给controller层

 

dao:

--接收UserInfoDO作为参数,操作数据库,将数据存进数据库中或修改原有数据

 

12. 获取核酸检测申报表单

controller:查看HttpSession中key为user的键值对,值是否为空。

若为空,则forward到登录界面jsp;若不为空,则forward到核酸检测申报表单jsp。

 

13. 核酸检测申报

controller:

--从request处获取到核酸检测图片和检测日期信息。为检测图片生成独一无二的id字符串作为图片的文件名,存储在以该用户userName命名的文件夹下(userName从HttpSession中的UserDO中获得)。将图片路径和检测日期封装成DTO

--将DTO作为参数,调用service层的方法,存储申报信息,获取service层返回的DTO

--若service层返回的DTO中的hint为空,则提交成功重定向到提交成功页面;否则,将DTO放进request的attribute中,forward给实名认证表单jsp展示错误信息。

 

service:

--检查从controller层接收到的DTO。若有问题,则在hint中设置相关提示返回。若无问题,则加上checked=0和user_id后将其封装成DO

--将UserDO作为参数,调用nat_report表的dao方法,查询是否存在该用户的核酸检测申报记录。若有,则对其进行修改;若无,则将DO插入。

--将DTO返回给controller层

 

dao:

--将接收到的DO存储进数据库或对已存数据进行修改

 

14. 出示核酸检测二维码

controller:

--无接收参数

--调用service层的方法,获取service层返回的QRCodeDTO

--将DTO放进request的attribute中。若DTO中的hint为空,则forward到二维码展示页面进行二维码展示;否则,forward到错误提示页面展示错误信息。

 

 

service:

--无接收参数

--将从HttpSession中获取的UserDO作为参数(为空则在hint中设置相关提示并返回),调用nat_report的dao方法,获取到对应该用户的唯一一条核酸检测申报记录。若查询不到对应记录,则为红码;若查询到的记录的checked=0,则为红码;若checked=1但记录的日期与当前时间的差大于5天,则为红码;若checked=1且记录的日期与当前时间的差小于5天,则为绿码。

获取UserInfoDO:以UserDO作为参数调用user_info表的dao,获取到UserInfoDO。若获取到的UserInfoDO为空,则在hint中设置相关提示并返回。

使用‘url?qrCode=随机字符串'这串字符串生成二维码图片存储在相应路径中(文件名为那串随机字符串)。

向QRCodeManager中插入一条key为随机字符串,value为QRCodeInfo对象的键值对。

--将二维码图片的路径封装进QRCodeDTO,返回给controller。

 

dao:

--接收UserDO作为参数,查询该用户的所有健康申报记录,返回NATReportDO。

user_info表的dao:

--接收UserDO作为参数,查询该用户的实名认证信息,返回UserInfoDO。

 

项目后台功能:

1. 查询二维码

微信扫描二维码后,将会从二维码图片中解析出‘url?qrCode=字符串'并访问。

服务端处从request中获取到qrCode参数中的字符串。在QRCodeManager中查找是否存在以该字符串为key的二维码。若存在,则获取该key对应的QRCodeInfo对象,将里面的信息封装成DTO,forward给jsp显示。展示的信息有,二维码颜色信息、二维码类型信息、实名认证信息,其中实名认证信息中包含了其实名是否通过审核的信息;若不存在,则返回相应提示。

 

2. 发送提醒邮件

使用ScheduledThreadPoolExecutor去定时重复执行任务。每隔一段时间就去数据库中查找出每个用户的最后一次申报记录,用当前时间减去该用户最后一次申报的时间,若超过20小时,则发送提醒邮件给该用户。

因为提交的Runnable类需要执行连接数据库进行查询的操作,其需要依赖Service bean。因此,我们将该Runnable类交给spring管理,让spring去注入相关依赖。具体做法即,将该类注解为Component,并配置springmvc.xml去扫描到该类,使得该类得以被放进容器中。当容器(即AppliationContext)被创建时,将会去创建该类的单例对象,并将其依赖的Service bean注入。

为了启动该定时重复执行的任务,我们创建了一个Context监听器,并将其在配置文件中进行注册。当Context创建时,将会触发监听器中的相应方法。该方法会创建一个ScheduledThreadPoolExecutor对象,并调用其scheduleAtFixedRate(myRunnable, t1, t2)方法。其中,myRunnable对象由applicationContext.getBean("myRunnable")方法从容器中取出。

Runnable的run方法将会调用相应的Service层方法(不需参数),以获取到每个用户的最后一次申报记录的DailyReportDTO,并找出超过20小时未进行新的申报的用户,对他们发邮件进行提醒。对于被调用的service层方法,其会调用daily_report表的相应dao方法(无需参数),以获取到每隔用户的最后一次申报记录的DailyReportDO,并将其封装为DailyReportDTO返回给run方法。对于被调用的dao方法,其会对数据库进行查询,返回相应的DailyReportDO。

 

3. 对实名认证、核酸检测证明进行审核

获取到user_info表和nat_report表中所有checked=0的记录。审核好后提交,改变对应记录的checked字段。

 

4. 对需进行申报的国家及其所需的申报类型进行更新

获取到countries表中所有的记录。修改好后提交,改变对应国家的type字段。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值