1>.
项目前言
1.项目介绍
①. 甲方:**健康管理机构
②.专业化,流程化,数据化,可视化,集成化
2.原型展示
3.技术架构
前端:HTML5,bootstrpt,vue,elementUI,ajax
后台:
1.zk+dubbo(服务注册与调用)
2.Spring+SpringMVC+Mybatis(主框架)
3.Spring security安全框架(登录认证)
4.Mysql+Redis(数据库)
5.Apache POI(office操作 api)
6.七牛云文件存储(OSS)
7.阿里云短信服务(SMS)
8.微信开发平台(公众号-订阅号)
9.Git(分布式版本管理),echarts(百度统计API)
瀑布与敏捷的区别
1.瀑布稳定团队或者需求,侧重文档
2.敏捷需求变动比较频繁,侧重沟通
1.
项目结构
各模块职责定位:
1.health_parent:父工程,打包方式为pom,统一锁定依赖的版本,同时聚合其他子模块 便于统一
执行maven命令
2.health_common:通用模块,打包方式为jar,存放项目中使用到的一些工具类、实体 类、返回结果
和常量类
3.health_interface:打包方式为jar,存放服务接口
4.health_service_provider:Dubbo服务模块,打包方式为war,存放服务实现类、Dao接 口、
Mapper映射文件等,作为服务提供方,需要部署到tomcat运行
5.health_backend:传智健康管理后台,打包方式为war,作为Dubbo服务消费方,存放 Controller、
HTML页面、js、css、spring配置文件等,需要部署到tomcat运行
6.health_mobile:移动端前台,打包方式为war,作为Dubbo服务消费方,存放 Controller、HTML
页面、js、css、spring配置文件等,需要部署到tomcat运行
2.
health_parent
创建一个空目录
创建health_parent,父工程,打包方式为pom,用于统一管理依赖版本 pom.xml
<packaging>pompackaging>
<properties>
<junit.version>4.12junit.version>
<spring.version>5.0.5.RELEASEspring.version>
<pagehelper.version>4.1.4pagehelper.version>
<servlet-api.version>2.5servlet-api.version>
<dubbo.version>2.6.0dubbo.version>
<zookeeper.version>3.4.7zookeeper.version>
<zkclient.version>0.1zkclient.version>
<mybatis.version>3.4.5mybatis.version>
<mybatis.spring.version>1.3.1mybatis.spring.version>
<mybatis.paginator.version>1.2.15mybatis.paginator.version>
<mysql.version>5.1.32mysql.version>
<druid.version>1.0.9druid.version>
<commons-fileupload.version>1.3.1commons-fileupload.version>
<spring.security.version>5.0.5.RELEASEspring.security.version>
<poi.version>3.14poi.version>
<jedis.version>2.9.0jedis.version>
<quartz.version>2.2.1quartz.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-beansartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aspectsartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jmsartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-context-supportartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>${spring.version}version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>dubboartifactId>
<version>${dubbo.version}version>
dependency>
<dependency>
<groupId>org.apache.zookeepergroupId>
<artifactId>zookeeperartifactId>
<version>${zookeeper.version}version>
dependency>
<dependency>
<groupId>com.github.sgroschupfgroupId>
<artifactId>zkclientartifactId>
<version>${zkclient.version}version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.47version>
dependency>
<dependency>
<groupId>javassistgroupId>
<artifactId>javassistartifactId>
<version>3.12.1.GAversion>
dependency>
<dependency>
<groupId>commons-codecgroupId>
<artifactId>commons-codecartifactId>
<version>1.10version>
dependency>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
<version>${pagehelper.version}version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>${mybatis.version}version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>${mybatis.spring.version}version>
dependency>
<dependency>
<groupId>com.github.miemiedevgroupId>
<artifactId>mybatis-paginatorartifactId>
<version>${mybatis.paginator.version}version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>${mysql.version}version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>${druid.version}version>
dependency>
<dependency>
<groupId>commons-fileuploadgroupId>
<artifactId>commons-fileuploadartifactId>
<version>${commons-fileupload.version}version>
dependency>
<dependency>
<groupId>org.quartz-schedulergroupId>
<artifactId>quartzartifactId>
<version>${quartz.version}version>
dependency>
<dependency>
<groupId>org.quartz-schedulergroupId>
<artifactId>quartz-jobsartifactId>
<version>${quartz.version}version>
dependency>
<dependency>
<groupId>com.sun.jerseygroupId>
<artifactId>jersey-clientartifactId>
<version>1.18.1version>
dependency>
<dependency>
<groupId>com.qiniugroupId>
<artifactId>qiniu-java-sdkartifactId>
<version>7.2.0version>
dependency>
<dependency>
<groupId>org.apache.poigroupId>
<artifactId>poiartifactId>
<version>${poi.version}version>
dependency>
<dependency>
<groupId>org.apache.poigroupId>
<artifactId>poi-ooxmlartifactId>
<version>${poi.version}version>
dependency>
<dependency>
<groupId>redis.clientsgroupId>
<artifactId>jedisartifactId>
<version>${jedis.version}version>
dependency>
<dependency>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-webartifactId>
<version>${spring.security.version}version>
dependency>
<dependency>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-configartifactId>
<version>${spring.security.version}version>
dependency>
<dependency>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-taglibsartifactId>
<version>${spring.security.version}version>
dependency>
<dependency>
<groupId>com.github.pengglegroupId>
<artifactId>kaptchaartifactId>
<version>2.3.2version>
<exclusions>
<exclusion>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>dom4jgroupId>
<artifactId>dom4jartifactId>
<version>1.6.1version>
dependency>
<dependency>
<groupId>xml-apisgroupId>
<artifactId>xml-apisartifactId>
<version>1.4.01version>
dependency>
dependencies>
dependencyManagement>
<dependencies>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>servlet-apiartifactId>
<version>${servlet-api.version}version>
<scope>providedscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>3.2version>
<configuration>
<source>1.8source>
<target>1.8target>
<encoding>UTF-8encoding>
configuration>
plugin>
plugins>
build>
2.
health_common
<dependencies>
<dependency>
<groupId>com.github.pagehelpergroupId>
<artifactId>pagehelperartifactId>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
dependency>
<dependency>
<groupId>com.github.miemiedevgroupId>
<artifactId>mybatis-paginatorartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
dependency>
<dependency>
<groupId>commons-fileuploadgroupId>
<artifactId>commons-fileuploadartifactId>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-beansartifactId>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webartifactId>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aspectsartifactId>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jmsartifactId>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-context-supportartifactId>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>dubboartifactId>
dependency>
<dependency>
<groupId>org.apache.zookeepergroupId>
<artifactId>zookeeperartifactId>
dependency>
<dependency>
<groupId>com.github.sgroschupfgroupId>
<artifactId>zkclientartifactId>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
dependency>
<dependency>
<groupId>javassistgroupId>
<artifactId>javassistartifactId>
dependency>
<dependency>
<groupId>commons-codecgroupId>
<artifactId>commons-codecartifactId>
dependency>
<dependency>
<groupId>org.apache.poigroupId>
<artifactId>poiartifactId>
dependency>
<dependency>
<groupId>redis.clientsgroupId>
<artifactId>jedisartifactId>
dependency>
<dependency>
<groupId>com.qiniugroupId>
<artifactId>qiniu-java-sdkartifactId>
dependency>
<dependency>
<groupId>com.sun.jerseygroupId>
<artifactId>jersey-clientartifactId>
dependency>
<dependency>
<groupId>org.apache.poigroupId>
<artifactId>poi-ooxmlartifactId>
dependency>
<dependency>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-configartifactId>
dependency>
<dependency>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-taglibsartifactId>
dependency>
dependencies>
3.
health_interface
<dependencies>
<dependency>
<groupId>com.itheima</groupId>
<artifactId>health_common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
4.
health_service_provider
<dependencies>
<dependency>
<groupId>com.itheimagroupId>
<artifactId>health_interfaceartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<configuration>
<port>81port>
<uriEncoding>UTF-8uriEncoding>
<path>/path>
configuration>
plugin>
plugins>
build>
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:\\mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=debug, stdout
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="dataSource"
class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/health" />
<property name="username" value="root" />
<property name="password" value="root" />
bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:SqlMapConfig.xml" />
bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.itheima.dao" />
bean>
beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<dubbo:application name="health_service_provider"/>
<dubbo:protocol name="dubbo" port="20887"/>
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:annotation package="com.itheima.service"/>
beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
bean>
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true"/>
beans>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<plugins>
<!-- com.github.pagehelper 为 PageHelper 类所在包名 -->
<plugin interceptor="com.github.pagehelper.PageHelper">
<!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL 六种数据库-->
<property name="dialect" value="mysql"/>
</plugin>
</plugins>
</configuration>
<web-app>
<display-name>Archetype Created Web Applicationdisplay-name>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath*:spring*.xmlparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
web-app>
5.
health_backend
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes" value="application/json"/>
<property name="features">
<list>
<value>WriteMapNullValuevalue>
<value>WriteDateUseDateFormatvalue>
list>
property>
bean>
mvc:message-converters>
mvc:annotation-driven>
<dubbo:application name="health_backend" />
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:annotation package="com.itheima.controller" />
<dubbo:consumer timeout="600000" check="false"/>
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="104857600" />
<property name="maxInMemorySize" value="4096" />
<property name="defaultEncoding" value="UTF-8"/>
bean>
beans>
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:\\mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=debug, stdout
<web-app>
<display-name>Archetype Created Web Applicationdisplay-name>
<filter>
<filter-name>CharacterEncodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>utf-8param-value>
init-param>
<init-param>
<param-name>forceEncodingparam-name>
<param-value>trueparam-value>
init-param>
filter>
<filter-mapping>
<filter-name>CharacterEncodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<init-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:springmvc.xmlparam-value>
init-param>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>*.dourl-pattern>
servlet-mapping>
web-app>
1>.
检查项列表显示
前台:[触发时机 -> 钩子函数、查询按钮、当页码改变时触发]
1.定义分页相关模型数据
2.页面加载时,在钩子函数中调用findPage()方法
3.定义findPage()方法。
3.1 发送ajax请求,param[currentPage、pageSize、queryString]作为参数传递到后台
3.2 响应后,对每页显示的数据dataList和总记录数total进行赋值
后台:
1.controller
将前台输入的参数param封装到一个QueryPageBean中返回一个PageResult[row
、 total]
2.service
2.1 将封装到的QueryPageBean对象三个参数取出
2.2 利用mybatis进行分业 PageHelper.startPage(currentPage,pageSize)
2.3 调用dao层对数据库进行查询
2.4 将page对象中的total和result设置到PageResult中去
3.dao
select * from t_checkitem
<if test="value!=null and value.length>0">
where code=#{code} and name = #{value}
</if>
前台步骤:
1.定义分页相关模型数据
2.页面加载时,在钩子函数中调用findPage()方法
3.定义findPage()方法
2>.
新增
前台:
1.点击新建按钮,触发事件。将模态框设置为可见,要注意重置表单数据
2.当点击新增按钮触发事件
2.1 对表格中的数据进行校验
2.2 如果校验通过
1>.关闭模态框
2>.发送ajax请求,将表单中的参数传入后台
3>.对响应回的结果进行判断;
如果正确,给出提示,新增成功
如果不正确,给出提示,新增失败
2.3 如果校验不通过:给出提示
3. .finally(()=>{ this.findPage(); })
后台:
1.controller:调用service
2.service 调用dao
3.dao 对数据库进行查询
3>.
删除
前台:
1.点击删除按钮,给出相对应的提示信息。是否进行删除
2.如果进行删除
2.1 发送ajax请求,将id作为参数传递进去
2.2 返回响应结果
1>.如果删除成功!给出成功提示
2>.如果删除失败!给出错误提示
3.如果取消删除:给出提示
4.调用findPage()方法
后台:
1.controller
2.service[要查询检查项和检查组有关联没]
2.1 如果有关联则抛出异常,删除失败
2.2 如果没有关联则删除
3.dao
3.1 通过检查项id查询是否和检查项有关联
3.2 对检查项id进行删除
后台步骤:
1.controller
2.service:
注意:不能直接删除,需要判断当前检查项是否和检查组关联,如果已经和检查组进行了关联则不允许删除
3.dao
4>.
修改
1.
数据回写
[通过id查询CheckItem对象]
前台:
1.点击编辑按钮,触发事件。打开模态框
2.发送ajax请求,将id作为参数传递到后台
3.如果通过id查找对象成功
4.如果查找对象失败,则给出提示
后台:
1.controller
2.service
3.dao
2.
修改
前台:
1.点击修改按钮,对表单进行校验
2.如果校验成功!
2.1 关闭模态框
2.2 发送ajax将表单中的参数传递到后台
2.3 返回响应结果。给出对应的提示
3.校验失败,给出提示信息
⑤. mybatis怎么拿到当前主键 [ selectKey ]?
1.selectKey : 通过mybatis框架提供的selectKey来获得自增产生的id值
2.order:insert 与 selectKey的执行顺序
3.keyProperty:这个属性不能乱写,要对应CheckGroup实体类中的id
<insert id="add" parameterType="com.itheima.pojo.CheckGroup">
/*
通过mybatis框架提供的selectKey来获得自增产生的id值
order:insert 与 selectKey的执行顺序
keyProperty:这个属性不能乱写,要对应CheckGroup实体类中的id
*/
<selectKey resultType="int" order="AFTER" keyProperty="id">
select LAST_INSERT_ID()
selectKey>
insert into t_checkgroup(code,name,helpCode,sex,remark,attention)
values
(#{code},#{name},#{helpCode},#{sex},#{remark},#{attention})
insert>
<insert id="setCheckGroupAndCheckItem" parameterType="map">
insert into t_checkgroup_checkitem(checkgroup_id,checkitem_id)
values(#{checkGroupId},#{checkitemId})
insert>
1>.
检查组添加
2>.
修改
前台:
点击编辑按钮,触发事件。发送三个ajax
[
通过检查组id获得当前编辑对象
获取检查项列表信息
根据检查组id回写被选中的检查项ids集合
]
后台:
1.controller
2.service
2.1 检查组:通过当前id对数据库中检查组进行修改
2.2 检查项:将检查组id和被选中的检查项ids作为参数,传递给dao.返回一个List<Integer>
3.dao
前台代码实现
1.需要为编辑按钮绑定单击事件,并且将当前行数据作为参数传递给处理函数
2.弹出编辑窗口回显数据
后台代码实现
1.controller
2.service
3.dao
前台:
1.点击修改按钮[对数据进行校验],发送ajax请求,将检查组表单数据和检查项数据
作为参数传递到后台
2.在响应中,将模态框进行关闭。看修改是否成功!
2.1 如果修改成功,给出相对应的提示
2.2 如果修改失败,给出相对应的提示
3.在finally中调用findPage()
后台:
1.controller:将检查组的表单数据和检查项被选中的ids传递给service
2.service
检查组: 根据id进行修改
检查项:
根据当前检查组id删除中间表数据
根据当前检查组的id和被选中的检查项ids 进行中间表添加
前台:
在编辑窗口中修改完成后,点击确定按钮需要提交请求,所以需要为确定按钮绑定事件并提供处理函数
后台:
1.controller:
2.service
3.dao
UUID 的十六个八位字节被表示为 32个十六进制数字,以连字号分隔的五组来显示,形式为
8-4-4-4-12,总共有 36个字符(即三十二个英数字母和四个连字号)。例如:
123e4567-e89b-12d3-a456-426655440000
UUID.randomUUID().toString()+extention;[extention为后缀名]
(注意:这里的toString()是转成字符串类型)
1.
新增
前台:
1.点击新建按钮,显示模态框,将套餐数据 | 图片url | 检查组中的数据清空 | 选项卡选中套餐,
发送ajax查询到检查组所有的数据,将查询出来的数据赋值给检查组中表单数据,并显示在页面
2.点击新建按钮[表单进行验证],将套餐表单数据和检查组中复选框的id作为参数传递到后台.返回
结果[如果为true,则给出成功提示;否则给出失败提示],在返回结果中,要将模态框关闭
3.调用findPage方法重新查询页面数据
后台:
1.controller: 将套餐表单数据和检查组复选框ids作为参数传递给service
2.service:
2.1 将套餐数据作为参数传递给dao,进行数据库新增
注意:这里要拿到当前新增的id,要在insert中使用selectKey标签
2.2 将套餐新增的id和复选框ids传入到dao,进行中间表数据的添加[重点掌握]
3.dao Setmeal 和 中间表的新增
上传图片并预览
1.点击 + 号上传图片,action路径会访问controller
2.将图片传入到七里云中[传入的参数是UUID后缀名]
UUID:UUID.randomUUID().toString()+extention;
extention:[
String originalFilename = imgFile.getOriginalFilename();//原始文件名
String extention=originalFilename.substring
(originalFilename.lastIndexOf("."));
]
3.要将传入七牛云的图片传入到redis中
4.在返回时,要将上传到七牛云图片的名称返回给前台[在新增套餐时,有img这个属性]
<packaging>warpackaging>
<dependencies>
<dependency>
<groupId>com.itheimagroupId>
<artifactId>health_interfaceartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
<dependency>
<groupId>org.quartz-schedulergroupId>
<artifactId>quartzartifactId>
dependency>
<dependency>
<groupId>org.quartz-schedulergroupId>
<artifactId>quartz-jobsartifactId>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.mavengroupId>
<artifactId>tomcat7-maven-pluginartifactId>
<configuration>
<port>83port>
<path>/path>
configuration>
plugin>
plugins>
build>
<web-app>
<display-name>Archetype Created Web Applicationdisplay-name>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath*:applicationContext*.xmlparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
web-app>
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=c:\\mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=debug, stdout
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal">
<value>200value>
property>
<property name="maxIdle">
<value>50value>
property>
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="true"/>
bean>
<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg name="poolConfig" ref="jedisPoolConfig" />
<constructor-arg name="host" value="127.0.0.1" />
<constructor-arg name="port" value="6379" type="int" />
<constructor-arg name="timeout" value="30000" type="int" />
bean>
beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config>context:annotation-config>
<bean id="clearImgJob" class="com.itheima.jobs.ClearImgJob">bean>
<bean id="jobDetail"
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="clearImgJob"/>
<property name="targetMethod" value="clearImg"/>
bean>
<bean id="myTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="jobDetail"/>
<property name="cronExpression">
<value>0/10 * * * * ?value>
property>
bean>
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="myTrigger"/>
list>
property>
bean>
beans>
package com.itheima.jobs;
import com.itheima.constant.RedisConstant;
import com.itheima.utils.QiniuUtils;
import org.springframework.beans.factory.annotation.Autowired;
import redis.clients.jedis.JedisPool;
import java.util.Set;
/*
* 自定义Job,实现定时清理垃圾图片
* */
public class ClearImgJob {
@Autowired
private JedisPool jedisPool;
public void clearImg(){
//根据redis中保存的两个set集合进行差值计算,获取垃圾图片名称集合
Set<String> set = jedisPool.getResource().sdiff
(RedisConstant.SETMEAL_PIC_RESOURCES, RedisConstant.SETMEAL_PIC_DB_RESOURCES);
if(set!=null){
for (String picName : set) {
//删除七牛云服务器上的图片
QiniuUtils.deleteFileFromQiniu(picName);
//从redis集合中删除集合名称
jedisPool.getResource().srem(RedisConstant.SETMEAL_PIC_RESOURCES,picName);
}
}
}
}
如果我们导入两个一样的数据,如果不进行判断,相同的数据会插入两次
思路:
1.点击模板下载按钮下载Excel模板文件
2.将预约设置信息录入到模板文件中
3.点击上传文件按钮将录入完信息的模板文件上传到服务器
4.通过POI读取上传文件的数据并保存到数据库
后台:
1.controller
1.1 利用POI将文件导入,返回一个List<String[]>
1.2 创建一个List<OrderSetting>
1.3 将List<String[]>数据存入List<OrderSetting>集合中
1.4 将List<OrderSetting>传入service
2.service
2.1 对List<OrderSetting> 集合进行判断并循环
2.2 通过日期查询数据库是否有这条记录
如果有,则进行修改操作
如果没有,则进行新增操作
3.dao
后台:前台需要传入一个data=2019-6
1.controller:将data数据传入service中,返回一个List<Map>
2.service:
2.1 将传入参数data 分别加上 begin="-01" | end="-31" 将bengin|end 封装到map传入dao
2.2 返回一个List<对象>
2.3 拿到前台想要的数据类型List<Map>
3.dao
前台:需要传入orderDate和num(预约人数)
1.controller: 将OrderSetting对象作为参数传入service
2.service:(根据日期查看数据库中是否有这条记录)
如果有,进行修改操作
如果没有,进行新增操作
//获取指定的URL参数值 http://localhost/pages/setmeal_detail.html?id=3&name=jack
function getUrlParam(paraName) {
var url = document.location.toString();
alert(url);//http://localhost/pages/setmeal_detail.html?id=3&name=jack
var arrObj = url.split("?");//id=3&name=jack
if (arrObj.length > 1) {
var arrPara = arrObj[1].split("&");
var arr;
for (var i = 0; i < arrPara.length; i++) {
arr = arrPara[i].split("=");
if (arr != null && arr[0] == paraName) {
return arr[1];
}
}
return "";
}
else {
return "";
}
}
思路:查询所有的套餐列表
<resultMap id="baseResultMap" type="com.itheima.pojo.Setmeal">
<id column="id" property="id"/> <result column="name" property="name"/>
<result column="code" property="code"/>
<result column="helpCode" property="helpCode"/>
<result column="sex" property="sex"/>
<result column="age" property="age"/>
<result column="price" property="price"/>
<result column="remark" property="remark"/>
<result column="attention" property="attention"/>
<result column="img" property="img"/>
</resultMap>
<resultMap id="findByIdResultMap"
type="com.itheima.pojo.Setmeal"
extends="baseResultMap">
<!--套餐和检查组之间多对多-->
<!-- select * from t_setmeal where id=#{id}
column="id" 这个id就是select*from t...查询出来的id字段名-->
<collection property="checkGroups"
ofType="com.itheima.pojo.CheckGroup"
select="com.itheima.dao.CheckGroupDao.findCheckGroupById"
column="id">
</collection>
</resultMap>
<!--根据套餐id查询套餐详情、检查组、检查项信息-->
<select id="findById" resultMap="findByIdResultMap" parameterType="int">
select * from t_setmeal where id=#{id}
</select>
<!--关联查询
根据套餐id查询关联的检查组详情
-->
<select id="findCheckGroupById" parameterType="int" resultMap="findByIdResultMap">
select * from t_checkgroup
where id in (
select checkgroup_id from t_setmeal_checkgroup
where setmeal_id=#{id})
</select>
<resultMap type="com.itheima.pojo.CheckGroup" id="baseResultMap">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="code" property="code"/>
<result column="helpCode" property="helpCode"/>
<result column="sex" property="sex"/>
<result column="remark" property="remark"/>
<result column="attention" property="attention"/>
</resultMap>
<resultMap type="com.itheima.pojo.CheckGroup"
id="findByIdResultMap"
extends="baseResultMap">
<!--检查组和检查项关联查询-->
<collection property="checkItems"
ofType="com.itheima.pojo.CheckItem"
column="id"
select="com.itheima.dao.CheckItemDao.findCheckItemById">
</collection>
</resultMap>
<!--关联查询
根据检查组id来查询关联的检查项
-->
<select id="findCheckItemById" parameterType="int"
resultType="com.itheima.pojo.CheckItem">
select * from t_checkitem where id in (select checkitem_id from
t_checkgroup_checkitem where checkgroup_id=#{id})
</select>
重点
知识点小结:
集合: CollectionUtils.isNotEmpty()
字符串:StringUtils.equals(validateCodeInRedis,validateCode)
1>.
手机号校验
1.检查手机号是否合法
2.倒计时30s倒计时
3.发送ajax请求,为用发送手机验证码
//发送验证码
sendValidateCode(){
//获取用户输入的手机号this.orderInfo.telephone
//1.调用checkTelephone()看手机号是否合法
/**
* 手机号校验
1--以1为开头;
2--第二位可为3,4,5,7,8,中的任意一位;
3--最后以0-9的9个整数结尾。
*/
var reg=/^[1][3,4,5,7,8][0-9]{9}$/;
if (!reg.test(this.orderInfo.telephone)) {
return false;
}
//2.倒计时
var num1=30;
var clock1;//定时器变量
var validateCodeButton1=document.getElementById("validateCodeButton");
function doLoop1(){
num1--;
if(num1>0){
validateCodeButton1.disabled=true;
validateCodeButton1.value=num1+"秒后重新获取";
}else{
validateCodeButton1.disabled=false;
validateCodeButton1.value="重新获取验证码";
window.clearInterval(clock1);
num1=30;
}
}
//校验通过,30s倒计时
clock1= window.setInterval(doLoop1,1000);//定时器方法,每隔指定时间,调用指定方法
//3.发送ajax请求,为用发送手机验证码
axios.post("/validateCode/send4Order.do?telephone="+this.orderInfo.telephone)
.then((res)=>{
if(!res.data.flag){
//短信验证码发送失败
this.$message.error(res.data.message);
}
});
},
思想:
1.通过阿里短信服务发送短信
2.如果失败,则给出相对应的错误信息
3.如果成功,则将短信存入redis
//用户在线体检预约发送验证码
@RequestMapping("/send4Order")
public Result send4Order(String telephone){
//随机生成4位数字验证码
Integer validateCode = ValidateCodeUtils.generateValidateCode(4);
try {
//给我们用户发送验证码
SMSUtils.sendShortMessage(SMSUtils.VALIDATE_CODE,telephone,validateCode+"");
} catch (ClientException e) {
e.printStackTrace();
return new Result(false, MessageConstant.SEND_VALIDATECODE_FAIL);
}
//将验证码保存到redis(5分钟) 18774149736001
jedisPool.getResource().setex(telephone+ RedisMessageConstant.SENDTYPE_ORDER,300,validateCode.toString());
return new Result(true, MessageConstant.SEND_VALIDATECODE_SUCCESS);
}
2>.
预约
controller:
1.将用户输入的验证码和redis中保存的验证码进行比对
2.如果校验成功,将map参数传入service;根据service返回的结果来进行判断
3.如果校验失败,返回错误信息结果给页面
service:
1.检查用户所选择的预约日期是否已经提前进行了预约设置,如果没有设置则无法进行 预约
2.检查用户所选择的预约日期是否已经约满,如果已经约满则无法预约
3.检查用户是否重复预约(同一个用户在同一天预约了同一个套餐),如果是重复预约 则无法完成
再次预约
4.检查当前用户是否为会员,如果是会员则直接完成预约,如果不是会员则自动完成注 册并进行
预约
5.预约成功,更新当日的已预约人数
//在线体检预约
@RequestMapping("/submit")
/*
controller:
1.将redis缓存的验证码和前台输入框中的验证码进行比对
2.如果比对成功!
2.1 设置预约类型
2.2 调用service
2.3 如果result.isFlag==true 发送成功验证码
3.如果比对不成功
* */
public Result submit(@RequestBody Map map){
//要知道手机号
String telephone = (String) map.get("telephone");
//思路: 先从redis获取保存的验证码
String validateCodeInRedis=jedisPool.getResource().
get(telephone+ RedisMessageConstant.SENDTYPE_ORDER);
//将用户输入的验证码和redis中保存的验证码进行比对
String validateCode = (String) map.get("validateCode");
/* if(StringUtils.equals(validateCodeInRedis,validateCode)){
}*/
if(validateCodeInRedis!=null&&validateCode!=null&&validateCode.equals(validateCodeInRedis)){
//如果比对成功!调用服务完成预约业务进行处理
//设置预约的类型,分为: 微信预约 | 电话预约
map.put("orderType", Order.ORDERTYPE_WEIXIN);
//通过dubbo来远程调用服务,来实现在线预约业务处理
Result result=null;
try {
result= orderService.order(map);
}catch (Exception e){
e.getStackTrace();
return result;
}
if(result.isFlag()){
//预约成功!可以为用户发送短信
try {
SMSUtils.sendShortMessage(SMSUtils.ORDER_NOTICE,telephone,(String)map.get("orderDate"));
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}else{
//如果比对失败,返回结果给页面
return new Result(false, MessageConstant.VALIDATECODE_ERROR);
}
}
//体检预约
@Override
public Result order(Map map) throws Exception{
//1、检查用户所选择的预约日期是否已经提前进行了预约设置,如果没有设置则无法进行预约
//1.1 获取前台的日期
String orderDate = (String) map.get("orderDate");
Date date = DateUtils.parseString2Date(orderDate);
OrderSetting orderSetting=orderSettingDao.findByOrderDate(date);
if(orderSetting==null){
//指定日期没有进行预约设置,则无法完成预约
return new Result(false, MessageConstant.SELECTED_DATE_CANNOT_ORDER);
}
//2、检查用户所选择的预约日期是否已经约满,如果已经约满则无法预约
//2.1 可预约的人数
int number = orderSetting.getNumber();
//2.2 已预约的人数
int reservations=orderSetting.getReservations();
if(reservations>=number){
//预约已满,不能预约
return new Result(false,MessageConstant.ORDER_FULL);
}
//3、检查用户是否重复预约(同一个用户在同一天预约了同一个套餐),如果是重复预约则无法完成再次预约
String telephone = (String) map.get("telephone");//获取用户页面输入的手机号
Member member = memberDao.findByTelephone(telephone);
if(member!=null){
//判断是否在重复预约
Integer numberId = member.getId();//会员id
String setmealId = (String) map.get("setmealId");//套餐id
//同一个用户同一天预约了同一个套餐
Order order = new Order(numberId, date, Integer.parseInt(setmealId));
//根据条件进行查询
List<Order> list = orderDao.findByCondition(order);
if(list!=null&&list.size()>0){
//说明用户在重复预约,无法完成再次预约
return new Result(false,MessageConstant.HAS_ORDERED);
}
}else{
//4、检查当前用户是否为会员,如果是会员则直接完成预约,如果不是会员则自动完成注 册并进行预约
member=new Member();
member.setName((String) map.get("name"));
member.setPhoneNumber(telephone);
member.setIdCard((String) map.get("idCard"));
member.setSex((String) map.get("sex"));
member.setRegTime(new Date());
memberDao.add(member);//自动完成会员注册
}
//5、预约成功,更新当日的已预约人数
Order order = new Order();
order.setMemberId(member.getId());//设置会员ID
order.setOrderDate(date);//预约日期
order.setOrderType((String) map.get("orderType"));//预约类型
order.setOrderStatus(Order.ORDERSTATUS_NO);//到诊状态
order.setSetmealId(Integer.parseInt((String) map.get("setmealId")));//套餐ID
orderDao.add(order);
//设置已预约人数+1
orderSetting.setReservations(orderSetting.getReservations()+1);
orderSettingDao.editReservationsByOrderDate(orderSetting);
return new Result(true,MessageConstant.ORDER_SUCCESS,order.getId());
}
1>.
通过手机进行验证
1.需求分析:
2.
发送验证码
思路
前台:
1.验证手机号是否正确
2.如果手机号正确,通过定时器来完成倒计时30s
3.发送ajax发送验证码[将电话号码作为参数传入后台]
后台:[controller]
1.调用阿里接口短信发送[验证码是工具类生成的]
2.如果发送成功,将验证码保持到redis中
注意:因为验证码是一次性的,在Redis中保持要用sete(key,time,value)
步骤:
1.前台代码
2.后台代码
[在ValidateCodeController中提供send4Login方法,调用短信服务发送验证码并将验证 码保存到redis]
3.
登录
思路
前台:
1.验证手机号是否正确[防止有人直接点击登录]
2.如果手机号正确,通过定时器来完成倒计时30s
3.发送ajax发送验证码[表单信息作为参数传入后台]
后台:[controller]
1.校验用户输入的短信验证码是否正确,如果验证码错误则登录失败
2.如果验证码正确,则判断当前用户是否为会员,如果不是会员则自动完成会员注册
3.向客户端写入Cookie,内容为用户手机号
4.将会员信息保存到Redis,使用手机号作为key,保存时长为30分钟
//后台代码实现
@Autowired
private JedisPool jedisPool;
@Reference
private MemberService memberService;
//手机号快速登录
@RequestMapping("/login")
public Result login(@RequestBody Map map, HttpServletResponse response){
// 获取页面的手机号码
String telephone= (String) map.get("telephone");
// 获取redis中的验证码
String redisCode = jedisPool.getResource().get(telephone + RedisMessageConstant.SENDTYPE_LOGIN);
// 获取页面的验证码
String validateCode= (String) map.get("validateCode");
//1.比对redis中的验证码和输入的验证码是否相同
if(redisCode!=null&&validateCode!=null&&redisCode.equals(validateCode)){
//验证码正确
//2.判断当前用户是否是会员(查询会员表示确定)
Member member = memberService.findByTelephone(telephone);
if(member==null){
//不是会员,自动完成注册(自动将用户信息保持会员表)
member=new Member();
member.setRegTime(new Date());
member.setPhoneNumber(telephone);
memberService.add(member);
}
//3、向客户端写入Cookie,内容为用户手机号
Cookie cookie=new Cookie("login_member_telephone",telephone);
cookie.setPath("/");//路径
cookie.setMaxAge(60*60*24*30);//有效期30天
response.addCookie(cookie);
//4、将会员信息保存到Redis,使用手机号作为key,保存时长为30分钟
String json=JSON.toJSON(member).toString();
jedisPool.getResource().setex(telephone,60*30,json);
return new Result(true,MessageConstant.LOGIN_SUCCESS);
}else{
//验证码输入错误
return new Result(false, MessageConstant.VALIDATECODE_ERROR);
}
}