作者:五洋顽石_449 | 来源:互联网 | 2023-10-12 16:34
1. 移动端开发
1.1 移动端开发方式
随着移动互联网的兴起和手机的普及,目前移动端应用变得愈发重要,成为各个商家的必争之地。例如,我们可以使用手机购物、支付、打车、玩游戏、订酒店、购票等。以前只能通过PC端完成的事情,现在通过手机就能完成,而且更加方便,而这些都需要移动端开发进行支持,那如何进行移动端开发呢?
移动端开发主要有三种方式:
1. 基于手机API开发(原生APP)
2. 基于手机浏览器开发(移动web)
3. 混合开发(混合APP)
1.1.1 基于手机API开发
手机端使用手机API,例如使用Andriod、ios进行开发,服务端只是一个数据提供者,手机端请求服务端获取数据(json、xml格式)并在页面展示,这种方式相当于传统的C/S模式。
1.1.2 基于手机浏览器开发
生存在浏览器中的应用,基本可以是触屏版的应用,这种开发方式相当于传统开发开发中的B/S模式手机上不需要额外安装软件,直接基于手机的的浏览器进行访问,这就需要我们编写的html页面需要根据不同手机尺寸进行自适应调节,目前比较流行的是html5开发,除了直接通过手机浏览器被访问,还可以将页面内嵌到一些应用程序中,例如通过微信公众号访问html5页面。
这种方式需要针对不同手机系统分别进行开发,只需要开发一个版本,就可以在不同的手机上访问。本项目通将我们开发的html5页面内嵌到微信公众号进行的。
1.1.3 混合开发
半原生半web混合类APP,需要下载安装,看上去类似原生APP,访问的内容是web网页,其实就是把html5页面嵌入到一个原生容器容器里面
1.2 微信公众号开发
1.2.1 账号分类
要进行微信公众号,首先访问微信公众平台。官网
本项目选择订阅号方式进行公众号开发。
1.2.2 注册账号
要开发微信微信公众号,首先要注册成为会员,然后就可以登录微信公众平台进行自定义菜单设置。
注册页面
1.2.3 自定义菜单
在自定义菜单页面可以根据需求创建一级菜单和二级菜单,其中一级菜单最多可以创建3个,每一个一级菜单下面最多可以创建5个二级菜单,每一个菜单由菜单名称和菜单内容组成,其中菜单内容有3种形式:发送消息、跳转网页、跳转小程序。
1.2.4 上线要求
如果是个人用户身份注册的订阅号,则自定义菜单的菜单内容不能进行跳转网页,因为个人用户目前不支持微信认证,而跳转网页需要微信认证后才有权限。
如果是企业用户,首先需要进行微信认证,通过后就可以进行跳转网页,跳转网页的地址要求必须有域名并且域名需要备案通过。
2. 需求分析和环境搭建
2.1 需求分析
用户体检之前需要进行预约,可以通过电话方式进行预约,此时由体检中心客服人员通过后台系统录入预约信息。用户也可以通过手机端自助预约。本章节开发的功能为用户通过手机自助预约。
预约流程如下:
1. 访问移动端首页
2. 点击体检预约进入体检套餐列表页面
3. 在体检套餐列表页面点击具体套餐进入套餐详情页面
4. 在套餐详情页面点击立即预约进入预约页面
5. 在预约页面录入体检人相关信息点击提交预约
2.2 搭建移动端工程
本项目是基于SOA架构进行开发,前面我们已经完成了后台系统的部分功能开发,在后台系统中都是通过Dubbo调用服务层发布的服务进行相关操作,本章节我们开发移动端工程也是同样模式,所以我们要在移动端工程通过Dubbo调用服务层发布的服务,如下图:
2.2.1 导入maven坐标
在health_common工程的pom.xml文件中导入阿里短信发送的maven坐标
com.aliyunaliyun-java-sdk-core3.3.1com.aliyunaliyun-java-sdk-dysmsapi1.0.0
2.2.2 导入通用组件
短信工具类:
随机生成验证码工具类ValidateCodeUtils
package com.itheima.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);//生成随机数,最大为9999if(code <1000){code = code + 1000;//保证随机数为4位数字}}else if(length == 6){code = new Random().nextInt(999999);//生成随机数,最大为999999if(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;}
}
短信发送工具类SMSUtils
package com.itheima.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产品域名(接口地址固定,无需修改)// 替换成你的AKfinal String accessKeyId = "accessKeyId";// 你的accessKeyId,参考本文档步骤2final 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);if (sendSmsResponse.getCode() != null && sendSmsResponse.getCode().equals("OK")) {// 请求成功System.out.println("请求成功");}}
}
RedisMessageConstant常量类:
package com.itheima.constant;public class RedisMessageConstant {public static final String SENDTYPE_ORDER = "001";//用于缓存体检预约时发送的验证码public static final String SENDTYPE_LOGIN = "002";//用于缓存手机号快速登录时发送的验证码public static final String SENDTYPE_GETPWD = "003";//用于缓存找回密码时发送的验证码
}
2.2.3 health_mobile
创建移动端工程health_mobile,打包方式为war,用于存放Controller,在Controller中通过Dubbo可以远程访问服务层相关服务,所以需要依赖health_interface接口工程。
pom.xml:
health_parentcom.itheima1.0-SNAPSHOT4.0.0health_mobile
warhealthmobile_web Maven Webapphttp://www.example.com
UTF-81.81.8com.itheimahealth_interface1.0-SNAPSHOTorg.apache.tomcat.maventomcat7-maven-plugin80
/
静态资源:
web.xml:
Archetype Created Web ApplicationCharacterEncodingFilterorg.springframework.web.filter.CharacterEncodingFilterencoding
utf-8
forceEncoding
true
CharacterEncodingFilter/*springmvcorg.springframework.web.servlet.DispatcherServletcontextConfigLocation
classpath:springmvc.xml
1springmvc*.do/pages/index.html
spring-mvc.xml:
WriteMapNullValueWriteDateUseDateFormat
spring-redis.xml:
${redis.pool.maxActive}
${redis.pool.maxIdle}
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://:12345@127.0.0.1:6379/0redis.host = 127.0.0.1
redis.port = 6379
redis.timeout = 30000
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 &#39;info&#39; to &#39;debug&#39; ###log4j.rootLogger=info, stdout