欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SSM秒杀系统(七)

程序员文章站 2022-04-22 08:19:01
...

该部分对秒杀主页进行了优化,秒杀活动开始前,其实就有很多用户访问该页面了。如果这个页面的一些资源,比如 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数据库,和数据库配置
SSM秒杀系统(七)
数据库配置:
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更新一次,也会自动修改

相关标签: SSM秒杀系统