学习目标:
-
掌握移动端套餐列表页动态展示实现过程
-
掌握移动端套餐详情页
-
掌握Freemarker页面静态化技术
-
能够使用Freemarker生成html静态页面
1. 移动端需求分析和环境搭建
1.1. 需求分析
【目标】
-
能够搭建移动端开发环境
【路径】
-
开发需求
-
环境搭建
【讲解】
1.1.1 移动端开发需求分析
用户在体检之前需要进行预约,可以通过电话方式进行预约,此时会由体检中心客服人员通过后台系统录入预约信息。用户也可以通过手机端自助预约。本章节开发的功能为用户通过手机自助预约。
预约流程如下:
1、访问移动端首页
2、点击体检预约进入体检套餐列表页面
3、在体检套餐列表页面点击具体套餐进入套餐详情页面
4、在套餐详情页面点击立即预约进入预约页面
5、在预约页面录入体检人相关信息点击提交预约
效果如下图:
【小结】
体检预约-->套餐列表-->套餐详情-->立即预约(发送手机验证码+Redis)
1.2. 搭建移动端工程
【目标】
移动端工程搭建
【路径】
-
创建healthmobile_web工程, 导入坐标(依赖health_interface)
-
导入页面
-
配置web.xml(springmvc的核心控制器+post请求乱码过滤器)
-
创建springmvc.xml(配置dubbo, 驱动注解)
-
导入通用组件
【讲解】
本项目是基于SOA架构进行开发,前面我们已经完成了后台系统的部分功能开发,在后台系统中都是通过Dubbo调用服务层发布的服务进行相关的操作。本章节我们开发移动端工程也是同样的模式,所以我们也需要在移动端工程中通过Dubbo调用服务层发布的服务,如下图:
1.2.1. 导入maven坐标
在health_parent工程的pom.xml文件中导入阿里短信发送的maven坐标
<!--阿里云服务器短信平台-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>1.0.0</version>
</dependency>
在health_common工程中添加引入的依赖
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
</dependency>
1.2.2. healthmobile_web
【路径】
1:pom.xml
2:静态资源(CSS、html、img等)
3:web.xml
4:springmvc.xml
5:spring-jedis.xml
6:redis.properties
7:log4j.properties
移动端工程,打包方式为war,用于存放Controller,在Controller中通过Dubbo可以远程访问服务层相关服务,所以需要依赖health_interface接口工程。
1.2.2.1.pom.xml:
1.2.2.2.静态资源(CSS、html、img等,详见资料):
1.2.2.3.web.xml:
1.2.2.4.springmvc.xml:
1.2.2.5.spring-jedis.xml:
1.2.2.6.redis.properties:
#最大分配的对象数
redis.pool.maxActive=200
#最大能够保持idel状态的对象数
redis.pool.maxIdle=50
redis.pool.minIdle=10
redis.pool.maxWaitMillis=20000
#当池内没有返回对象时,最大等待时间
redis.pool.maxWait=300
#格式:redis://:[密码]@[服务器地址]:[端口]/[db index]
#redis.uri = redis://:[email protected]:6379/0
redis.host = 127.0.0.1
redis.port = 6379
redis.timeout = 30000
1.2.2.7.log4j.properties:
### 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=info, stdout
1.2.3. 导入通用组件
【路径】
1:ValidateCodeUtils工具类:(产生验证码)
2:SMSUtils工具类:(短信服务,用于发送短消息服务(SMS))
3:RedisMessageConstant常量类:
【讲解】
在health_common工程中导入如下通用组件
1:ValidateCodeUtils工具类:(产生验证码)
package com.itheima.health.utils; import java.util.Random; /** * 随机生成验证码工具类 */ public class ValidateCodeUtils { /** * 随机生成验证码 * @param length 长度为4位或者6位 * @return */ public static Integer generateValidateCode(int length){ Integer code =null; if(length 4){ code = new Random().nextInt(9999);//生成随机数,最大为9999 if(code < 1000){ code = code + 1000;//保证随机数为4位数字 } }else if(length 6){ code = new Random().nextInt(999999);//生成随机数,最大为999999 if(code < 100000){ code = code + 100000;//保证随机数为6位数字 } }else{ throw new RuntimeException("只能生成4位或6位数字验证码"); } return code; } /** * 随机生成指定长度字符串验证码 * @param length 长度 * @return */ public static String generateValidateCode4String(int length){ Random rdm = new Random(); String hash1 = Integer.toHexString(rdm.nextInt()); String capstr = hash1.substring(0, length); return capstr; } }
2:SMSUtils工具类:(短信服务,用于发送短消息服务(SMS))
package com.itheima.health.utils;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
/**
* 短信发送工具类
*/
public class SMSUtils {
public static final String VALIDATE_CODE = "SMS_159620392";//发送短信验证码
public static final String ORDER_NOTICE = "SMS_159771588";//体检预约成功通知
/**
* 发送短信
* @param phoneNumbers
* @param param
* @throws ClientException
*/
public static void sendShortMessage(String templateCode,String phoneNumbers,String param) throws ClientException{
// 设置超时时间-可自行调整
System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
System.setProperty("sun.net.client.defaultReadTimeout", "10000");
// 初始化ascClient需要的几个参数
final String product = "Dysmsapi";// 短信API产品名称(短信产品名固定,无需修改)
final String domain = "dysmsapi.aliyuncs.com";// 短信API产品域名(接口地址固定,无需修改)
// 替换成你的AK
final String accessKeyId = "accessKeyId";// 你的accessKeyId,参考本文档步骤2
final String accessKeySecret = "accessKeySecret";// 你的accessKeySecret,参考本文档步骤2
// 初始化ascClient,暂时不支持多region(请勿修改)
IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
IAcsClient acsClient = new DefaultAcsClient(profile);
// 组装请求对象
SendSmsRequest request = new SendSmsRequest();
// 使用post提交
request.setMethod(MethodType.POST);
// 必填:待发送手机号。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式
request.setPhoneNumbers(phoneNumbers);
// 必填:短信签名-可在短信控制台中找到
request.setSignName("传智健康");
// 必填:短信模板-可在短信控制台中找到
request.setTemplateCode(templateCode);
// 可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
// 友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
request.setTemplateParam("{\"code\":\""+param+"\"}");
// 可选-上行短信扩展码(扩展码字段控制在7位或以下,无特殊需求用户请忽略此字段)
// request.setSmsUpExtendCode("90997");
// 可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
// request.setOutId("yourOutId");
// 请求失败这里会抛ClientException异常
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);