兰州工程建设信息网站,手机html网站开发工具,残联网站建设概况,做网站需要学会写代码吗1、浏览器请求web服务器
2、服务器渲染页面#xff0c;渲染的过程就是向jsp页面(模板)内填充数据(模型)。
3、服务器将渲染生成的页面返回给浏览器。
所以模板引擎就是#xff1a;模板数据输出#xff0c;Jsp页面就是模板#xff0c;页面中嵌入的jsp标签就是数据#x… 1、浏览器请求web服务器
2、服务器渲染页面渲染的过程就是向jsp页面(模板)内填充数据(模型)。
3、服务器将渲染生成的页面返回给浏览器。
所以模板引擎就是模板数据输出Jsp页面就是模板页面中嵌入的jsp标签就是数据两者相结合输出html网页。
Freemarker 添加依赖
!-- Spring Boot 对结果视图 Freemarker 集成 --
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-freemarker/artifactId
/dependency
配置文件
YAML
spring:freemarker:enabled: truecache: false #关闭模板缓存方便测试settings:template_update_delay: 0suffix: .ftl #页面模板后缀名charset: UTF-8template-loader-path: classpath:/templates/ #页面模板位置(默认为 classpath:/templates/)resources:add-mappings: false #关闭项目中的静态资源映射(static、resources文件夹下的资源)
Html页面
HTML
!DOCTYPE html
html
headmeta charsetutf-8titleHello World!/title
/head
body
Hello ${name}!
/body
/html
接口实现
Controller
public class FreemarkerController {GetMapping(/testfreemarker)public ModelAndView test(){ModelAndView modelAndView new ModelAndView();//设置模型数据modelAndView.addObject(name,小明);//设置模板名称modelAndView.setViewName(test);return modelAndView;} public void testGenerateHtmlByTemplate() throws IOException, TemplateException {//配置freemarkerConfiguration configuration new Configuration(Configuration.getVersion());//加载模板//选指定模板路径,classpath下templates下//得到classpath路径String classpath this.getClass().getResource(/).getPath();configuration.setDirectoryForTemplateLoading(new File(classpath /templates/));//设置字符编码configuration.setDefaultEncoding(utf-8);//指定模板文件名称Template template configuration.getTemplate(course_template.ftl);//准备数据CoursePreviewDto coursePreviewInfo coursePublishService.getCoursePreviewInfo(2L);MapString, Object map new HashMap();map.put(model, coursePreviewInfo);//静态化//参数1模板参数2数据模型String content FreeMarkerTemplateUtils.processTemplateIntoString(template, map);System.out.println(content);//将静态化内容输出到文件中InputStream inputStream IOUtils.toInputStream(content);//输出流FileOutputStream outputStream new FileOutputStream(D:\\develop\\test.html);IOUtils.copy(inputStream, outputStream);}} course_template.html是一个静态html页面里边还没有添加freemarker标签如果要预览该页面需要借助Nginx进行预览因为页面需要加载一些css样式表、图片等内容。
在进行课程预览时需要展示课程的图片在线插放课程视频课程图片、视频这些都在MinIO文件系统存储下边统一由Nginx代理通过文件服务域名统一访问。
进入课程详情页面点击马上学习或课程目录下的小节的名称将打开视频播放页面。首先在nginx.conf中配置视频播放页面的地址。 开发流程
1、请求参数
传入课程id表示要预览哪一门课程。
2、响应结果
输出课程详情页面到浏览器。 响应页面到浏览器使用freemarker模板引擎技术实现首先从课程资料目录下获取课程预览页面course_template.html拷贝至内容管理的接口工程的resources/templates下并将其在本目录复制一份命名为course_template.ftl GetMapping(/coursepreview/{courseId})public ModelAndView preview(PathVariable(courseId) Long courseId) {ModelAndView modelAndView new ModelAndView();//查询课程的信息作为模型数据CoursePreviewDto coursePreviewInfo coursePublishService.getCoursePreviewInfo(courseId);//指定模型modelAndView.addObject(model, coursePreviewInfo);//指定模板modelAndView.setViewName(course_template);//根据视图名称加.ftl找到模板return modelAndView;} 课程审核 说明如下
1、一门课程新增后它的审核状为”未提交“发布状态为”未发布“。
2、课程信息编辑完成教学机构人员执行”提交审核“操作。此时课程的审核状态为”已提交“。
3、当课程状态为已提交时运营平台人员对课程进行审核。
4、运营平台人员审核课程结果有两个审核通过、审核不通过。
5、课程审核过后不管状态是通过还是不通过教学机构可以再次修改课程并提交审核此时课程状态为”已提交“。此时运营平台人员再次审核课程。
6、课程审核通过教学机构人员可以发布课程发布成功后课程的发布状态为”已发布“。
7、课程发布后通过”下架“操作可以更改课程发布状态为”下架“
8、课程下架后通过”上架“操作可以再次发布课程上架后课程发布状态为“发布”。 提交课程审核将课程信息汇总后写入课程预发布表课程预发布表记录了教学机构在某个时间点要发布的课程信息。
课程审核人员从预发布表查询信息进行审核。
课程审核的同时可以对课程进行修改修改的内容不会写入课程预发布表。
课程审核通过执行课程发布将课程预发布表的信息写入课程发布表。
提交审核课程后必须等到课程审核完成才可以再次提交课程。
课程发布 1、向内容管理数据库的课程发布表存储课程发布信息更新课程基本信息表中发布状态为已发布。
2、向Redis存储课程缓存信息。
3、向Elasticsearch存储课程索引信息。
4、请求分布文件系统存储课程静态化页面(即html页面)实现快速浏览课程详情页面。 redis中的课程缓存信息是将课程发布表中的数据转为json进行存储。
elasticsearch中的课程索引信息是根据搜索需要将课程名称、课程介绍等信息进行索引存储。
MinIO中存储了课程的静态化页面文件html网页查看课程详情是通过文件系统去浏览课程详情页面。 分布式事务控制
满足CP
如果要满足CP就表示课程发布操作后向数据库、redis、elasticsearch、MinIO写四份数据只要有一份写失败其它的全部回滚。
满足AP
课程发布操作后先更新数据库中的课程发布状态更新后向redis、elasticsearch、MinIO写课程信息只要在一定时间内最终向redis、elasticsearch、MinIO写数据成功即可。
目前我们已经有了任务调度的技术积累这里选用任务调度的方案去实现分布式事务控制课程发布满足AP即可。 1、在内容管理服务的数据库中添加一个消息表消息表和课程发布表在同一个数据库。
2、点击课程发布通过本地事务向课程发布表写入课程发布信息同时向消息表写课程发布的消息。通过数据库进行控制只要课程发布表插入成功消息表也插入成功消息表的数据就记录了某门课程发布的任务。
3、启动任务调度系统定时调度内容管理服务去定时扫描消息表的记录。
4、当扫描到课程发布的消息时即开始完成向redis、elasticsearch、MinIO同步数据的操作。
5、同步数据的任务完成后删除消息表记录。 时序图如下
下图是课程发布操作的流程 1、执行发布操作内容管理服务存储课程发布表的同时向消息表添加一条“课程发布任务”。这里使用本地事务保证课程发布信息保存成功同时消息表也保存成功。
2、任务调度服务定时调度内容管理服务扫描消息表由于课程发布操作后向消息表插入一条课程发布任务此时扫描到一条任务。
3、拿到任务开始执行任务分别向redis、elasticsearch及文件系统存储数据。
4、任务完成后删除消息表记录。 下边对消息SDK的设计内容进行说明
sdk需要提供执行任务的逻辑吗
拿课程发布任务举例执行课程发布任务是要向redis、索引库等同步数据其它任务的执行逻辑是不同的所以执行任务在sdk中不用实现任务逻辑只需要提供一个抽象方法由具体的执行任务方去实现。
如何保证任务的幂等性
在视频处理章节介绍的视频处理的幂等性方案这里可以采用类似方案任务执行完成后会从消息表删除如果消息的状态是完成或不存在消息表中则不用执行。
如何保证任务不重复执行
采用和视频处理章节一致方案除了保证任务的幂等性外任务调度采用分片广播根据分片参数去获取任务另外阻塞调度策略为丢弃任务。
注意这里是信息同步类任务即使任务重复执行也没有关系不再使用抢占任务的方式保证任务不重复执行。
还有一个问题根据消息表记录是否存在或消息表中的任务状态去保证任务的幂等性如果一个任务有好几个小任务比如课程发布任务需要执行三个同步操作存储课程到redis、存储课程到索引库存储课程页面到文件系统。如果其中一个小任务已经完成也不应该去重复执行。这里该如何设计 将小任务作为任务的不同的阶段在消息表中设计阶段状态。 每完成一个阶段在相应的阶段状态字段打上完成标记即使这个大任务没有完成再重新执行时如果小阶段任务完成了也不会重复执行某个小阶段的任务。 远程调用
!-- Spring Cloud 微服务远程调用 --
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId
/dependency
dependencygroupIdio.github.openfeign/groupIdartifactIdfeign-httpclient/artifactId
/dependency
!--feign支持Multipart格式传参--
dependencygroupIdio.github.openfeign.form/groupIdartifactIdfeign-form/artifactIdversion3.8.0/version
/dependency
dependencygroupIdio.github.openfeign.form/groupIdartifactIdfeign-form-spring/artifactIdversion3.8.0/version
/dependency
feign:hystrix:enabled: truecircuitbreaker:enabled: true
hystrix:command:default:execution:isolation:thread:timeoutInMilliseconds: 30000 #熔断超时时间
ribbon:ConnectTimeout: 60000 #连接超时时间ReadTimeout: 60000 #读超时时间MaxAutoRetries: 0 #重试次数MaxAutoRetriesNextServer: 1 #切换实例的重试次数 //在启动类上
EnableFeignClients(basePackages{com.xuecheng.content.feignclient})FeignClient(value search,fallbackFactory SearchServiceClientFallbackFactory.class)
public interface SearchServiceClient {PostMapping(/search/index/course)public Boolean add(RequestBody CourseIndex courseIndex);
}降级处理
FeignClient(value media-api,configuration
MultipartSupportConfig.class,fallback MediaServiceClientFallback.class)
RequestMapping(/media)
public interface MediaServiceClient{
Java
FeignClient(value media-api,configuration MultipartSupportConfig.class,
fallbackFactory MediaServiceClientFallbackFactory.class)
Slf4j
Component
public class MediaServiceClientFallbackFactory implements FallbackFactoryMediaServiceClient {Overridepublic MediaServiceClient create(Throwable throwable) {return new MediaServiceClient(){Overridepublic String uploadFile(MultipartFile upload, String objectName) {//降级方法log.debug(调用媒资管理服务上传文件时发生熔断异常信息:{},throwable.toString(),throwable);return null;}};}
}
elasticsearch