SSM秒杀系统(七)
程序员文章站
2022-04-22 08:19:01
...
SSM秒杀系统(七)
该部分对秒杀主页进行了优化,秒杀活动开始前,其实就有很多用户访问该页面了。如果这个页面的一些资源,比如 CSS、JS、图片、商品详情等,都访问后端服务器提供,甚至操作数据库,服务肯定会出现不可用的情况。所以一般我们会把这个页面整体进行静态化,降低服务器的压力
十一、频道列表静态化
1.频道列表静态化
由于我们每次访问频道页,也就是主页的时候就会从数据库读取数据进行加载,这样会非常耗时,我们将其静态化为html。这对于哪些修改不频繁的页面非常有用,采用httpclient生成html页面
@RequestMapping("producehtml")
public void producehtml(HttpServletRequest req){
String htmlPath=req.getRealPath("/WEB-INF/html/");
String contextpath = req.getScheme() +"://" + req.getServerName() + ":" +req.getServerPort() +req.getContextPath();
contextpath = contextpath + "/pagehomeAction/tohome";
CloseableHttpClient client = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(contextpath);
CloseableHttpResponse response = null;
try {
//3.执行请求,获取响应
response = client.execute(httpGet);
//看请求是否成功,这儿打印的是http状态码
System.out.println(response.getStatusLine().getStatusCode());
//4.获取响应的实体内容,就是我们所要抓取得网页内容
HttpEntity entity = response.getEntity();
//5.将其打印到控制台上面
//方法一:使用EntityUtils
if (entity != null) {
String html = EntityUtils.toString(entity);
File file = new File(htmlPath+"/index.html");//存到应用的htmlPath目录下
Writer writer = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(file), "utf-8"));
writer.write(html);
writer.flush();
writer.close();
}
EntityUtils.consume(entity);
}catch (Exception e) {
e.printStackTrace();
}
}
这会直接在/WEB-INF/html/目录下生成一个与/pagehomeAction/tohome访问的页面相同的一个html页面
由于静态页面没有用户信息,所以通过js添加:
@RequestMapping("getUser")
@ResponseBody
public String getuser(HttpServletRequest req) {
Msuser msuser = (Msuser)req.getSession().getAttribute("msuser");
//获取用户名
String account = "";
if(msuser!=null) {
account = msuser.getUseraccount();
}
return account;
}
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
欢迎:<span id="useraccount"></span>
<a href="/YF_MS_WEB/userregiterloginAction/toregiter">注册</a></br>
<a href="/YF_MS_WEB/userregiterloginAction/tologin">登录</a>
<a href="/YF_MS_WEB/userregiterloginAction/exit">退出登录</a>
<a href="/YF_MS_WEB/orderAction/queryorderbyuserid">订单查询</a>
<table border="2">
<c:forEach items="${list}" var="item">
<tr>
<td>${item.producttitle}</td>
<td>${item.productpicture}</td>
<td>${item.miaoshaprice}</td>
<td>${item.originalprice}</td>
<td>${item.starttime}</td>
<td>${item.endtime}</td>
<td><a href="viewproductdetail?id=${item.id}">查看</a></td>
</tr>
</c:forEach>
</table>
<script src="/YF_MS_WEB/js/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$.ajax({
type:"get",
url:"/YF_MS_WEB/pagehomeAction/getUser",
success:function(msg){
$("#useraccount").html(msg);
}
});
</script>
</body>
</html>
2.分布式定时任务
如果商品更新后如何更新到静态页面呢:我们采用分布式定时任务自动生成html页面,并定时进行更新。我们采用分布式定时任务quartz来实现:
2.1 引入quartz相关的包
<!-- 定时任务引入相关依赖 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.2</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
2.2 导入quartz数据库,和数据库配置
数据库配置:
quartz.properties
#============================================================================
# Configure JobStore
# Using Spring datasource in quartzJobsConfig.xml
# Spring uses LocalDataSourceJobStore extension of JobStoreCMT
#============================================================================
org.quartz.jobStore.useProperties=true
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 5000
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.txIsolationLevelReadCommitted = true
# Change this to match your DB vendor
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#============================================================================
# Configure Main Scheduler Properties
# Needed to manage cluster instances
#============================================================================
org.quartz.scheduler.instanceId=AUTO
org.quartz.scheduler.instanceName=MY_CLUSTERED_JOB_SCHEDULER
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
#============================================================================
# Configure ThreadPool
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
分布式定时任务spring配置:
<!-- 自动扫描 -->
<context:component-scan base-package="com.youfan.*"/>
<bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/test2"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<!-- 配置线程池-->
<bean name="executor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="15"/>
<property name="maxPoolSize" value="25"/>
<property name="queueCapacity" value="100"/>
</bean>
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource1"/>
</bean>
<!-- 配置调度任务-->
<bean name="quartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="configLocation" value="classpath:quartz.properties"/>
<property name="dataSource" ref="dataSource1"/>
<property name="transactionManager" ref="transactionManager"/>
<!-- 任务唯一的名称,将会持久化到数据库-->
<property name="schedulerName" value="baseScheduler"/>
<!-- 每台集群机器部署应用的时候会更新触发器-->
<property name="overwriteExistingJobs" value="true"/>
<property name="applicationContextSchedulerContextKey" value="appli22"/>
<property name="jobFactory">
<bean class="com.youfan.task.AutowiringSpringBeanJobFactory"/>
</property>
<property name="triggers">
<list>
<ref bean="printCurrentTimeScheduler"/>
</list>
</property>
<property name="jobDetails">
<list>
<ref bean="printCurrentTimeJobs"/>
</list>
</property>
<property name="taskExecutor" ref="executor"/>
</bean>
<!-- 配置Job详情 -->
<bean name="printCurrentTimeJobs" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.youfan.task.PrintCurrentTimeJobs"/>
<!--<property name="jobDataAsMap">
<map>
<entry key="clusterQuartz" value="com.aaron.framework.clusterquartz.job.ClusterQuartz"/>
</map>
</property>-->
<property name="durability" value="true"/>
<property name="requestsRecovery" value="false"/>
</bean>
<!-- 配置触发时间 -->
<bean name="printCurrentTimeScheduler" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="printCurrentTimeJobs"/>
<property name="cronExpression">
<value>0/10 * * * * ?</value>
</property>
<property name="timeZone">
<value>GMT+8:00</value>
</property>
</bean>
<!-- 分布式事务配置 end -->
2.3 自动生成和更新html
还是调用pagehomeAction/producehtml来生成
@Controller
public class ProducehtmlTask
{
public void producehtml(){
String url = "http://127.0.0.1:8080/YF_MS_WEB/pagehomeAction/producehtml";
CloseableHttpClient client = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response = null;
try {
//3.执行请求,获取响应
response = client.execute(httpGet);
//看请求是否成功,这儿打印的是http状态码
System.out.println("ProducehtmlTask=="+response.getStatusLine().getStatusCode());
}catch (Exception e) {
e.printStackTrace();
}
}
}
2.4 这样服务器启动成功后,如果数据库数据被修改,我们访问的html/index.html页面每隔10s更新一次,也会自动修改