SSH开发框架中,实现系统启动加载类,读取数据库常用数据进入内存,利用Spring托管,并完成reload功能

别再复制粘贴了!手把手教你用腾讯云CentOS 7.5部署Spring Boot项目(含MySQL 5.7避坑指南) 本文详细介绍了在腾讯云CentOS 7.5服务器上部署Spring Boot项目的全流程,包括环境配置、MySQL 5.7安装避坑指南及性能优化技巧。特别针对腾讯云服务器配置环境中的常见问题提供解决方案,帮助开发者高效完成项目部署。 阅读详情

各位看官,请做好心理准备,这个帖子会很长,因为小弟已经做好写很长的准备。

现在说一下需求,这次的项目是做一个水产养殖相关的项目,系统开启以后很多地方要用到数据库里的字典数据,比如部门表,养殖对象表,这些数据是可变的,但是变化频率很小,所有每次用到的时候都去数据库取数据很明显的是对资源的浪费,所以想按照以前的方法把数据从数据库里读取出来,放到内存,每次用到的时候直接去内存找就可以了。想法应该是正确的,可是用到了SSH框架,做起来就有点小困难了,研究了一下午,总是是搞定。思路和代码写出来,有错误的地方请大家指正。

正式开始!中间的调错过程省去,直接如何实现。

         另配一个listener,和spring同时启动,不可取。因为listener的启动机制貌似是线程,并不是按顺序一个一个启动,所有想到直接在spring的配置文件里,注册bean文件,让bean文件来执行取数据的工作,但是这个bean显然是不能使用DAO的类,因为DAO层的东西无法注入进来,所以要有个替代的东西,这个东西好难找啊,就是BeanPostProcessor接口,用类PBSTrackManagerPostProcessor实现它其中的一个方法postProcessAfterInitialization,这个方法里可以引入一个类GetDictionaryInfo,实现类的方法getAllInfo(),当getAllInfo去调用DAO层的数据时就可以了。

不说了,直接上源码:

PBSTrackManagerPostProcessor.java

view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
import org.springframework.beans.BeansException;  
import org.springframework.beans.factory.config.BeanPostProcessor;  
 
/** 
 * @author ROC 
 * @2010年4月5日18:24:58 
 * 实现BeanPostProcessor接口,可以实现在Spring加载时,调取一个的对象的方法,使其能够取得实例化以后的DAO. 
 *  
 *  
 *  
 * */ 
 
public class PBSTrackManagerPostProcessor implements BeanPostProcessor   
{  
 
    public Object postProcessAfterInitialization(Object obj, String s)  
            throws BeansException  
    {  
        if(obj instanceof GetDictionaryInfo)//GetDictionaryInfo为类名  
        {  
            ((GetDictionaryInfo) obj).getAllInfo();//getAllInfo为GetDictionaryInfo的方法  
        }  
        return obj;  
    }  
 
    public Object postProcessBeforeInitialization(Object obj, String s)  
            throws BeansException  
    {  
        return obj;  
    }  
 
} 
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * @author ROC
 * @2010年4月5日18:24:58
 * 实现BeanPostProcessor接口,可以实现在Spring加载时,调取一个的对象的方法,使其能够取得实例化以后的DAO.
 *
 *
 *
 * */

public class PBSTrackManagerPostProcessor implements BeanPostProcessor
{

    public Object postProcessAfterInitialization(Object obj, String s)
            throws BeansException
    {
        if(obj instanceof GetDictionaryInfo)//GetDictionaryInfo为类名
        {
            ((GetDictionaryInfo) obj).getAllInfo();//getAllInfo为GetDictionaryInfo的方法
        }
        return obj;
    }

    public Object postProcessBeforeInitialization(Object obj, String s)
            throws BeansException
    {
        return obj;
    }

}

 

GetDictionaryInfo.java

view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
import java.util.HashMap;  
import javax.annotation.Resource;  
import javax.servlet.ServletContext;  
 
import org.springframework.web.context.WebApplicationContext;  
import org.springframework.web.context.support.WebApplicationContextUtils;  
 
import java.util.ArrayList;  
import edu.ldu.system.preferences.feeding.DAO.TdFeedingRatesDAO;  
import edu.ldu.system.preferences.product.DAO.TdProductFishDAO;  
/** 
 * @author ROC 
 * 2010年4月5日18:26:55 
 * 实现getAllInfo方法,取得所有常用字典表里的数据 
 *  
 * */ 
 
 
public class GetDictionaryInfo {  
 
    @Resource 
    private TdFeedingRatesDAO tdFeedingRatesDAO ;  
    @Resource 
    private TdProductFishDAO tdProductFishDAO;  
      
    public GetDictionaryInfo(){  
        super();  
    }  
    private static WebApplicationContext springContext;  
    public static ServletContext _servletContext;//这个是为了取servletContext  
    private static GetDictionaryInfo _instance;   
    public static GetDictionaryInfo getInstance()  
    {  
        springContext = WebApplicationContextUtils  
        .getWebApplicationContext(_servletContext);  
        if(null == _instance)  
            _instance = (GetDictionaryInfo)springContext.getBean("getDictionaryInfo");  
        return _instance;  
          
    }  
    public static HashMap<String,ArrayList> dictionaryInfoMap = new HashMap<String, ArrayList>();  
      
    public  void getAllInfo() {  
        System.out.println("%%%%%%%%%%系统启动加载......");  
        System.out.println("@@@@@@@@@@开始从数据库中取数据!");  
        ArrayList tdFeedingRatesList =  (ArrayList)tdFeedingRatesDAO.findAll();  
        System.out.println("数据LIST - 1 的大小 "+tdFeedingRatesList.size());  
        ArrayList tdProductFishList  = (ArrayList)tdProductFishDAO.findAll();     
        System.out.println("数据LIST - 2 的大小 "+tdProductFishList.size());  
        System.out.println("@@@@@@@@@@数据从数据库中全部取出!");  
        dictionaryInfoMap.put("tdFeedingRatesList", tdFeedingRatesList);  
        dictionaryInfoMap.put("tdProductFishList", tdProductFishList);  
        System.out.println("@@@@@@@@@@数据打包完毕,全部放进了dictionaryInfoMap!");  
    }  
      
    /** 
     * 重新加载字典表数据! 
     * */ 
    public   void reloadDictionaryInfoMap()  
    {  
        System.out.println("==========~~~~~~~~~~系统开始重新加载字典表");  
        dictionaryInfoMap.clear();  
        System.out.println("==========~~~~~~~~~~字典表MAP,清空成功!");  
        getAllInfo();  
        System.out.println("==========~~~~~~~~~~重新加载字典表成功");  
    }  
      
    public HashMap<String, ArrayList> getDictionaryInfoMap() {  
        return dictionaryInfoMap;  
    }  
 
    public void setDictionaryInfoMap(HashMap<String, ArrayList> dictionaryInfoMap) {  
        this.dictionaryInfoMap = dictionaryInfoMap;  
    }  
 
} 
import java.util.HashMap;
import javax.annotation.Resource;
import javax.servlet.ServletContext;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import java.util.ArrayList;
import edu.ldu.system.preferences.feeding.DAO.TdFeedingRatesDAO;
import edu.ldu.system.preferences.product.DAO.TdProductFishDAO;
/**
 * @author ROC
 * 2010年4月5日18:26:55
 * 实现getAllInfo方法,取得所有常用字典表里的数据
 *
 * */


public class GetDictionaryInfo {

 @Resource
 private TdFeedingRatesDAO tdFeedingRatesDAO ;
 @Resource
 private TdProductFishDAO tdProductFishDAO;
 
 public GetDictionaryInfo(){
  super();
 }
 private static WebApplicationContext springContext;
 public static ServletContext _servletContext;//这个是为了取servletContext
 private static GetDictionaryInfo _instance; 
 public static GetDictionaryInfo getInstance()
 {
  springContext = WebApplicationContextUtils
  .getWebApplicationContext(_servletContext);
  if(null == _instance)
   _instance = (GetDictionaryInfo)springContext.getBean("getDictionaryInfo");
  return _instance;
  
 }
 public static HashMap<String,ArrayList> dictionaryInfoMap = new HashMap<String, ArrayList>();
 
 public  void getAllInfo() {
  System.out.println("%%%%%%%%%%系统启动加载......");
  System.out.println("@@@@@@@@@@开始从数据库中取数据!");
  ArrayList tdFeedingRatesList =  (ArrayList)tdFeedingRatesDAO.findAll();
  System.out.println("数据LIST - 1 的大小 "+tdFeedingRatesList.size());
  ArrayList tdProductFishList  = (ArrayList)tdProductFishDAO.findAll(); 
  System.out.println("数据LIST - 2 的大小 "+tdProductFishList.size());
  System.out.println("@@@@@@@@@@数据从数据库中全部取出!");
  dictionaryInfoMap.put("tdFeedingRatesList", tdFeedingRatesList);
  dictionaryInfoMap.put("tdProductFishList", tdProductFishList);
  System.out.println("@@@@@@@@@@数据打包完毕,全部放进了dictionaryInfoMap!");
 }
 
 /**
  * 重新加载字典表数据!
  * */
 public   void reloadDictionaryInfoMap()
 {
  System.out.println("==========~~~~~~~~~~系统开始重新加载字典表");
  dictionaryInfoMap.clear();
  System.out.println("==========~~~~~~~~~~字典表MAP,清空成功!");
  getAllInfo();
  System.out.println("==========~~~~~~~~~~重新加载字典表成功");
 }
 
 public HashMap<String, ArrayList> getDictionaryInfoMap() {
  return dictionaryInfoMap;
 }

 public void setDictionaryInfoMap(HashMap<String, ArrayList> dictionaryInfoMap) {
  this.dictionaryInfoMap = dictionaryInfoMap;
 }

}

 

然后这个GetDictionaryInfo.java是个普通的类,所有要有一个servlet启动并且把取得HaspMap放到context里去

MainServlet.java

view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
import java.io.IOException;  
import java.io.PrintWriter;  
import java.util.HashMap;  
import java.util.ArrayList;  
 
import javax.servlet.ServletContext;  
import javax.servlet.ServletException;  
import javax.servlet.http.HttpServlet;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
 
import org.springframework.web.context.WebApplicationContext;  
import org.springframework.web.context.support.WebApplicationContextUtils;  
 
public class MainServlet extends HttpServlet {  
 
    /** 
     * Initialization of the servlet. <br> 
     *  
     * @throws ServletException 
     *             if an error occurs 
     */ 
    private static final long serialVersionUID = 1L;  
    // private SystemParamServicesImpl sysParamService;  
    private static WebApplicationContext springContext;  
    private ServletContext context;  
 
    public void init() throws ServletException {  
        // Put your code here  
          
        springContext = WebApplicationContextUtils  
                .getWebApplicationContext(this.getServletContext());  
        GetDictionaryInfo._servletContext=this.getServletContext();  
          
        context = this.getServletContext();  
        // GetDictionaryInfo getDictionaryInfo = new GetDictionaryInfo();  
        HashMap<String, ArrayList> dictionaryInfoMap = (HashMap<String, ArrayList>) GetDictionaryInfo.dictionaryInfoMap;  
        System.out.println("字典MAP里的数据长度为" + dictionaryInfoMap.size() + "个");  
        context.setAttribute("dictionaryInfoMap", dictionaryInfoMap);  
        System.out.println("@@@@@@@@@@系统字典表数据加载成功!");  
    }  
 
    /** 
     * Constructor of the object. 
     */ 
    public MainServlet() {  
        super();  
    }  
 
    /** 
     * Destruction of the servlet. <br> 
     */ 
    public void destroy() {  
        super.destroy(); // Just puts "destroy" string in log  
        // Put your code here  
    }  
 
    /** 
     * The doGet method of the servlet. <br> 
     *  
     * This method is called when a form has its tag value method equals to get. 
     *  
     * @param request 
     *            the request send by the client to the server 
     * @param response 
     *            the response send by the server to the client 
     * @throws ServletException 
     *             if an error occurred 
     * @throws IOException 
     *             if an error occurred 
     */ 
    public void doGet(HttpServletRequest request, HttpServletResponse response)  
            throws ServletException, IOException {  
 
        response.setContentType("text/html");  
        PrintWriter out = response.getWriter();  
        out  
                .println("<!DOCTYPE HTML PUBLIC /"-//W3C//DTD HTML 4.01 Transitional//EN/">");  
        out.println("<HTML>");  
        out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");  
        out.println("  <BODY>");  
        out.print("    This is ");  
        out.print(this.getClass());  
        out.println(", using the GET method");  
        out.println("  </BODY>");  
        out.println("</HTML>");  
        out.flush();  
        out.close();  
    }  
 
    /** 
     * The doPost method of the servlet. <br> 
     *  
     * This method is called when a form has its tag value method equals to 
     * post. 
     *  
     * @param request 
     *            the request send by the client to the server 
     * @param response 
     *            the response send by the server to the client 
     * @throws ServletException 
     *             if an error occurred 
     * @throws IOException 
     *             if an error occurred 
     */ 
    public void doPost(HttpServletRequest request, HttpServletResponse response)  
            throws ServletException, IOException {  
 
        response.setContentType("text/html");  
        PrintWriter out = response.getWriter();  
        out  
                .println("<!DOCTYPE HTML PUBLIC /"-//W3C//DTD HTML 4.01 Transitional//EN/">");  
        out.println("<HTML>");  
        out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");  
        out.println("  <BODY>");  
        out.print("    This is ");  
        out.print(this.getClass());  
        out.println(", using the POST method");  
        out.println("  </BODY>");  
        out.println("</HTML>");  
        out.flush();  
        out.close();  
    }  
 
} 
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.ArrayList;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

public class MainServlet extends HttpServlet {

 /**
  * Initialization of the servlet. <br>
  *
  * @throws ServletException
  *             if an error occurs
  */
 private static final long serialVersionUID = 1L;
 // private SystemParamServicesImpl sysParamService;
 private static WebApplicationContext springContext;
 private ServletContext context;

 public void init() throws ServletException {
  // Put your code here
  
  springContext = WebApplicationContextUtils
    .getWebApplicationContext(this.getServletContext());
  GetDictionaryInfo._servletContext=this.getServletContext();
  
  context = this.getServletContext();
  // GetDictionaryInfo getDictionaryInfo = new GetDictionaryInfo();
  HashMap<String, ArrayList> dictionaryInfoMap = (HashMap<String, ArrayList>) GetDictionaryInfo.dictionaryInfoMap;
  System.out.println("字典MAP里的数据长度为" + dictionaryInfoMap.size() + "个");
  context.setAttribute("dictionaryInfoMap", dictionaryInfoMap);
  System.out.println("@@@@@@@@@@系统字典表数据加载成功!");
 }

 /**
  * Constructor of the object.
  */
 public MainServlet() {
  super();
 }

 /**
  * Destruction of the servlet. <br>
  */
 public void destroy() {
  super.destroy(); // Just puts "destroy" string in log
  // Put your code here
 }

 /**
  * The doGet method of the servlet. <br>
  *
  * This method is called when a form has its tag value method equals to get.
  *
  * @param request
  *            the request send by the client to the server
  * @param response
  *            the response send by the server to the client
  * @throws ServletException
  *             if an error occurred
  * @throws IOException
  *             if an error occurred
  */
 public void doGet(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {

  response.setContentType("text/html");
  PrintWriter out = response.getWriter();
  out
    .println("<!DOCTYPE HTML PUBLIC /"-//W3C//DTD HTML 4.01 Transitional//EN/">");
  out.println("<HTML>");
  out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
  out.println("  <BODY>");
  out.print("    This is ");
  out.print(this.getClass());
  out.println(", using the GET method");
  out.println("  </BODY>");
  out.println("</HTML>");
  out.flush();
  out.close();
 }

 /**
  * The doPost method of the servlet. <br>
  *
  * This method is called when a form has its tag value method equals to
  * post.
  *
  * @param request
  *            the request send by the client to the server
  * @param response
  *            the response send by the server to the client
  * @throws ServletException
  *             if an error occurred
  * @throws IOException
  *             if an error occurred
  */
 public void doPost(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {

  response.setContentType("text/html");
  PrintWriter out = response.getWriter();
  out
    .println("<!DOCTYPE HTML PUBLIC /"-//W3C//DTD HTML 4.01 Transitional//EN/">");
  out.println("<HTML>");
  out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
  out.println("  <BODY>");
  out.print("    This is ");
  out.print(this.getClass());
  out.println(", using the POST method");
  out.println("  </BODY>");
  out.println("</HTML>");
  out.flush();
  out.close();
 }

}
 

然后完成注册功能

applicationContext.XML

view plaincopy to clipboardprint?
<!-- 调用GetDictionaryInfo 读的 --> 
<bean id="pbsTrackManagerPostProcess" class="edu.ldu.utils.PBSTrackManagerPostProcessor" /> 
<bean id="getDictionaryInfo" class="edu.ldu.utils.GetDictionaryInfo" /> 
 <!-- 调用GetDictionaryInfo 读的 -->
 <bean id="pbsTrackManagerPostProcess" class="edu.ldu.utils.PBSTrackManagerPostProcessor" />
 <bean id="getDictionaryInfo" class="edu.ldu.utils.GetDictionaryInfo" />
 

配置web.xml让MainServlet.java自启动

view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
<servlet> 
        <servlet-name>MainServlet</servlet-name> 
        <servlet-class>edu.ldu.utils.MainServlet</servlet-class> 
        <load-on-startup>1</load-on-startup> 
    </servlet> 
<servlet>
  <servlet-name>MainServlet</servlet-name>
  <servlet-class>edu.ldu.utils.MainServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>

然后就是如何在Action里取到数据了:

view plaincopy to clipboardprint?
ServletContext context = ServletActionContext.getServletContext();  
        HashMap dictionaryInfoMap = (HashMap)context.getAttribute("dictionaryInfoMap"); 
ServletContext context = ServletActionContext.getServletContext();
  HashMap dictionaryInfoMap = (HashMap)context.getAttribute("dictionaryInfoMap");

又一个问题就是解决触发一个函数,让这些东西重新加载。

view plaincopy to clipboardprint?
GetDictionaryInfo.getInstance().reloadDictionaryInfoMap(); 
GetDictionaryInfo.getInstance().reloadDictionaryInfoMap();

reloadDictionaryInfoMap();实现起来时比较困难的,要在GetDictionaryInfo 取到ServletContext,而且要必须取到第一次实例的GetDictionaryInfo ,所有有一个东西很好用,就是Spring的context,取到他的方式

view plaincopy to clipboardprint?
private static WebApplicationContext springContext;  
springContext = WebApplicationContextUtils  
        .getWebApplicationContext(_servletContext); 
private static WebApplicationContext springContext;
springContext = WebApplicationContextUtils
  .getWebApplicationContext(_servletContext);

这样就大功告成,跑起来以后的结果,列出控制台的输出数据:

view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
%%%%%%%%%%系统启动加载......  
@@@@@@@@@@开始从数据库中取数据!  
Hibernate: select tdfeedingr0_.pk_id as pk1_0_, tdfeedingr0_.fishTypeId as fishTypeId0_, tdfeedingr0_.waterTemperature as waterTem3_0_, tdfeedingr0_.growthStageId as growthSt4_0_, tdfeedingr0_.baitId as baitId0_, tdfeedingr0_.feedingRate as feedingR6_0_, tdfeedingr0_.state as state0_ from LDU_Aquaculture.dbo.td_feeding_rates tdfeedingr0_  
数据LIST - 1 的大小 12  
Hibernate: select tdproductf0_.pk_fishid as pk1_7_, tdproductf0_.fishname as fishname7_, tdproductf0_.fish_store as fish3_7_, tdproductf0_.state as state7_, tdproductf0_.creationDate as creation5_7_, tdproductf0_.lastModifiedDate as lastModi6_7_ from LDU_Aquaculture.dbo.td_product_fish tdproductf0_  
数据LIST - 2 的大小 2  
@@@@@@@@@@数据从数据库中全部取出!  
@@@@@@@@@@数据打包完毕,全部放进了dictionaryInfoMap!  
字典MAP里的数据长度为2个  
@@@@@@@@@@系统字典表数据加载成功!  
系统启动,开始装载日志文件……  
DEBUG日志文件路径为:E:/Program Files/Tomcat 6.0/webapps/Aquaculture/WEB-INF/logs/app-debug.log   
INFO日志文件路径为:E:/Program Files/Tomcat 6.0/webapps/Aquaculture/WEB-INF/logs/app-info.log   
WARN日志文件路径为:E:/Program Files/Tomcat 6.0/webapps/Aquaculture/WEB-INF/logs/app-warn.log   
ERROR日志文件路径为:E:/Program Files/Tomcat 6.0/webapps/Aquaculture/WEB-INF/logs/app-error.log   
2010-4-6 9:35:38 org.apache.coyote.http11.Http11Protocol start  
信息: Starting Coyote HTTP/1.1 on http-8080  
2010-4-6 9:35:38 org.apache.jk.common.ChannelSocket init  
信息: JK: ajp13 listening on /0.0.0.0:8009  
2010-4-6 9:35:38 org.apache.jk.server.JkMain start  
信息: Jk running ID=0 time=0/31  config=null 
2010-4-6 9:35:38 org.apache.catalina.startup.Catalina start  
信息: Server startup in 10921 ms 
==========~~~~~~~~~~系统开始重新加载字典表  
==========~~~~~~~~~~字典表MAP,清空成功!  
%%%%%%%%%%系统启动加载......  
@@@@@@@@@@开始从数据库中取数据!  
Hibernate: select tdfeedingr0_.pk_id as pk1_0_, tdfeedingr0_.fishTypeId as fishTypeId0_, tdfeedingr0_.waterTemperature as waterTem3_0_, tdfeedingr0_.growthStageId as growthSt4_0_, tdfeedingr0_.baitId as baitId0_, tdfeedingr0_.feedingRate as feedingR6_0_, tdfeedingr0_.state as state0_ from LDU_Aquaculture.dbo.td_feeding_rates tdfeedingr0_  
数据LIST - 1 的大小 12  
Hibernate: select tdproductf0_.pk_fishid as pk1_7_, tdproductf0_.fishname as fishname7_, tdproductf0_.fish_store as fish3_7_, tdproductf0_.state as state7_, tdproductf0_.creationDate as creation5_7_, tdproductf0_.lastModifiedDate as lastModi6_7_ from LDU_Aquaculture.dbo.td_product_fish tdproductf0_  
数据LIST - 2 的大小 2  
@@@@@@@@@@数据从数据库中全部取出!  
@@@@@@@@@@数据打包完毕,全部放进了dictionaryInfoMap!  
==========~~~~~~~~~~重新加载字典表成功 

 

本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/peng_wu01/archive/2010/04/06/5453361.aspx#

从本地Win10到云端CentOS:我的第一个Spring Boot博客部署全记录(附WinSCP+域名绑定心得) 本文详细记录了从Windows本地开发环境到CentOS云服务器部署Spring Boot博客的全过程,包括服务器选购、环境配置、项目迁移、服务运行及域名绑定等关键步骤。特别适合初学者参考,提供了大量实用技巧和常见问题解决方法,帮助开发者顺利完成云端部署。 阅读详情

相关推荐

Spring Boot+Vue项目从零部署到PetaExpress云服务器全流程实战

在软件开发领域,项目部署是将本地开发的应用发布到线上服务器,使其能够通过互联网对外提供服务的关键环节。其核心原理在于构建一个稳定、安全的生产环境,将代码、依赖和配置进行标准化迁移与整合。掌握规范的部署流程具有重要的技术价值,它直接决定了应用的可用性、性能和安全性,是开发到运维的必经之路。典型的应用场景包括个人博客、企业官网、API服务以及前后端分离的Web应用上线。本文将以一个典型的Spring Boot后端与Vue.js前端分离项目为例,结合PetaExpress云服务器,详细解析从环境准备、安全配置、服

weixin_30387423的博客 395

SSH框架,在项目启动的时候加载数据库信息

1.启动类 package com.simpefect.listener; import java.util.List; import java.util.Map; import java.util.UUID; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; imp

littlebirdofjava的专栏 5273

若依(RuoYi)框架从零到部署:Spring Boot+Vue权限系统完整配置指南

在Java企业级应用开发中,Spring Boot作为构建微服务和单体应用的基石,极大地简化了项目初始化和配置流程。其核心原理在于通过自动配置和起步依赖,快速整合数据访问、安全认证、缓存等常用模块,显著提升开发效率。这一技术价值在需要快速构建后台管理系统的场景中尤为突出,例如权限管理、用户角色分配等通用需求。若依(RuoYi)框架正是基于Spring Boot和Vue.js的优秀实践,它封装了RBAC权限模型、代码生成器等高频功能,提供了开箱即用的解决方案。本文聚焦于若依框架的【环境配置】与【项目部署】,通

weixin_33984032的博客 455

linux跑服务用sshd吗,linux – 为什么我会使用“service sshd reload”优先于“service sshd restart”?...

当您运行服务sshd命令,其中opt可以重新加载/重新启动时,它实际上运行一个带有修改过的环境的程序,如下所示:env -i PATH="$PATH" TERM="$TERM" "${SERVICEDIR}/${SERVICE}" ${OPTIONS}例如.:env -i PATH=/sbin:/usr/sbin:/bin:/usr/bin TERM=xterm /etc/init.d/sshd ...

weixin_30909805的博客 760

GitHub Actions驱动的Java生产级CI/CD流水线:Maven编译、测试与SSH部署

CI/CD是现代软件交付的核心实践,其本质是通过自动化实现代码从提交到运行的确定性流转。在Java技术栈中,Maven作为事实标准的构建工具,天然承担着依赖管理、编译、测试与打包等关键生命周期职责。基于GitHub Actions构建CI/CD流水线,无需Docker或K8s等额外基础设施,仅依赖SSH与Java环境即可完成端到端部署,显著降低运维复杂度与学习成本。该方案强调可追溯性(Git Tag驱动发布)、原子性(软链接+systemd服务控制)与环境一致性(复用本地Maven配置),适用于Spring

weixin_30697239的博客 305

C++ REST API 与 Nginx 集成部署实战:从开发到上线的完整指南

这次我们来看一个典型的 C++ 后端项目实战,它集成了 REST API 设计、幂等性保障,并最终通过 Nginx 部署为静态资源服务器。对于 C++ 开发者而言,从编码到部署上线,每一步都充满挑战。本文将带你走通一个完整流程:从搭建 C++ REST 服务,到实现核心业务逻辑,再到通过 Nginx 进行高效、稳定的生产环境部署。如果你正在寻找一个能跑通、能复现、能直接用于自己项目的 C++ 后端开发与部署指南,这篇文章就是为你准备的。 我们将重点关注几个核心环节:如何用 C++ 构建一个具备幂等性保障的

weixin_34411563的博客 464

重新配置SSH远程服务端

为了提高SSH远程访问安全需要重新配置/etc/ssh/sshd_config文件,需要修改如下几点。 操作之前说明一下/etc/ssh目录下有 sshd_config 与 ssh_config 两个相似文件,两个文件区别: - sshd_config: 这是sshd服务器系统的配置文件 - ssh_config: 这是ssh客户端系统的配置文件...

weixin_33918114的博客 637

别再复制粘贴了!手把手教你用腾讯云CentOS 7.5搭建Spring Boot项目环境(含MySQL 5.7避坑指南)

本文详细介绍了在腾讯云CentOS 7.5服务器上从零搭建Spring Boot项目环境的全流程,包括系统配置、MySQL 5.7避坑指南、自动化部署及监控排错。特别针对开发者常见的部署问题提供深度解决方案,帮助高效完成项目部署和服务器配置。

weixin_30580341的博客 323

ssh设置:免密登入、修改默认端口、禁止root登入、限制错误登入次数,安全模式强制修改root密码

ssh需要做一些配置,比如修改默认服务器端口号、服务器不允许root登入、服务器限制最大的登入错误次数、客户端免密登入服务器

zz2230633069的博客 9170

Web应用部署实战:从传统部署到Docker容器化全流程详解

项目部署是将本地开发环境中的应用迁移至服务器,使其能够对外提供稳定服务的关键环节。其核心原理在于实现环境的一致性、服务的可靠性与访问的可用性。从技术价值看,自动化、标准化的部署流程是提升开发运维效率、保障线上服务稳定性的基石。在应用场景上,无论是单体应用、前后端分离项目,还是微服务架构,都需要根据项目特点选择合适的部署策略。本文聚焦于两种主流部署路径:传统手动部署与基于Docker的容器化部署。传统部署通过SSH、SCP等工具,在服务器上直接配置运行环境、安装依赖并配置Web服务器(如Nginx)与进程管理

culuo8053的博客 482

Spring Boot CRM客户关系管理系统:源码剖析与部署实践

客户关系管理系统(CRM)是企业级应用中的典型场景,Spring Boot凭借自动配置与生态优势,成为快速构建此类系统的首选框架。理解CRM的核心在于掌握客户、线索、商机、合同等模块的数据模型与权限设计,这不仅是Java后端开发的基础能力,也是springboot面试题中的高频考点。从开源项目如悟空CRM、芋道源码中学习业务闭环与代码架构,可以大幅提升二次开发效率。同时,系统部署涉及linux部署、环境配置、数据初始化等实操环节,开发者需兼顾开发与运维视角。本文围绕Spring Boot CRM源码,系统讲

weixin_34354173的博客 480

【原创】SSH开发框架中,实现系统启动加载类,读取数据库常用数据进入内存,利用Spring托管,并完成reload功能

各位看官,请做好心理准备,这个帖子会很长,因为小弟已经做好写很长的准备。 现在说一下需求,这次的项目是做一个水产养殖相关的项目,系统开启以后很多地方要用到数据库里的字典数据,比如部门表,养殖对象表,这些数据是可变的,但是变化频率很小,所有每次用到的时候都去数据库取数据很明显的是对资源的浪费,所以想按照以前的方法把数据从数据库里读取出来,放到内存,每次用到的时候直接去内存找就可以了。想法应该

Roc 9267

通过 CoovaChilli 和 FreeRADIUS 搭建一个公共 Wi-Fi 的认证系统,实现用户连接到 Wi-Fi 后通过 Captive Portal(强制登录页面)进行认证

要实现固定设备连接的功能,你可以通过MAC 地址认证来限制哪些设备可以通过 FreeRADIUS 进行身份验证和连接。你可以在 FreeRADIUS 的users文件中直接配置允许的设备的 MAC 地址,也可以通过数据库存储和查询设备信息,进一步提高管理效率。通过这些方法,你可以灵活地控制哪些设备能够访问你的 Wi-Fi 网络。

m0_69943017的博客 2644

SSH开发框架中,实现系统启动加载类,读取数据库常用数据进入内存,利用Spring托管,并完成reload功能...

各位看官,请做好心理准备,这个帖子会很长,因为小弟已经做好写很长的准备。 现在说一下需求,这次的项目是做一个水产养殖相关的项目,系统开启以后很多地方要用到数据库里的字典数据,比如部门表,养殖对象表,这些数据是可变的,但是变化频率很小,所有每次用到的时候都去数据库取数据很明显的是对资源的浪费,所以想按照以前的方法把数据从数据库里读取出来,放到内存,每次用到的时候直接去内存找就可以了。想法应该是...

我是传奇 254

EDSR图像超分辨程序复现(踩坑及解决记录)

EDSR图像超分辨程序复现(踩坑及解决记录)

Sunny_Coder的博客 3641

从波形图到参数调优:一次无感BLDC电机启动失败的深度解析

本文深入解析无感BLDC电机启动失败案例,通过波形分析揭示参数不匹配和IPM保护机制触发等关键问题。详细探讨了过零点检测、PWM周期设置及强拖参数调优的底层逻辑,并分享IPM模块保护机制与实战调优技巧,最终实现99.98%的启动成功率。

weixin_29182481的博客 819

全栈个人网站开发部署实战:Vue 3 + Spring Boot 3 从开发到上线

全栈开发是现代Web应用构建的核心模式,它通过前后端分离的架构,将用户界面与业务逻辑解耦,实现高效协作与独立部署。其技术原理在于前端框架(如Vue.js)负责视图渲染与用户交互,后端框架(如Spring Boot)提供RESTful API处理业务逻辑与数据持久化。这种模式的技术价值在于提升了开发效率、应用可维护性和团队协作能力,广泛应用于个人博客、企业官网、管理后台等场景。本文以个人网站项目为例,详细演示了如何利用Vue 3、TypeScript、Vite构建现代化前端,并结合Spring Boot 3、

weixin_33795093的博客 310

游戏玩家和排行数据抓取:使用 Python 爬虫抓取游戏中的玩家排名、角色数据和战绩

对于游戏开发者、分析师和玩家本身来说,抓取游戏中的玩家排名、角色数据和战绩信息是一项至关重要的任务。Python提供了强大的爬虫库和数据处理工具,可以帮助我们高效地抓取和分析游戏数据,为游戏分析师、开发者以及玩家本身提供有价值的数据支持。通过本篇博客,我们学习了如何使用Python爬虫技术抓取游戏中的玩家排名、角色数据和战绩。本篇博客将详细介绍如何使用Python编写爬虫来抓取游戏中的玩家排名、角色数据和战绩,并结合最新的技术来实现高效的数据抓取与处理。为了方便后续的数据处理,我们将抓取的数据保存到。

2201_76125261的博客 944

阿里云ECS部署实战:从服务器选购到项目上线的保姆级指南

云计算与服务器部署是现代应用开发的核心环节,其原理在于通过虚拟化技术将计算、存储和网络资源以服务的形式提供。掌握云端部署技术,对于提升应用的可访问性、可靠性和可扩展性具有重要价值,广泛应用于个人项目展示、企业级应用发布及测试环境搭建等场景。本文聚焦于阿里云ECS(弹性计算服务)这一主流平台,深入解析服务器初始化、安全加固、运行环境配置及项目部署的全流程。文中将详细探讨如何通过SSH密钥登录、防火墙配置等关键操作强化服务器安全,并分享Nginx反向代理、PM2进程管理等实用技巧,帮助开发者高效完成从本地开发到

congji3817的博客 366

Prompt进阶2:LangGPT(构建高性能Prompt策略和技巧)--最佳实践指南

Prompt进阶2:LangGPT(构建高性能Prompt策略和技巧)--最佳实践指南

丨汀、的博客 2650

利用 Python 构建高效爬虫爬取国家标准文献——从基础到进阶

然而,由于许多标准文献需要从特定网站获取,手动下载既耗时又低效,因此构建自动化爬虫成为一种实用且高效的解决方案。本文从技术选型、网站分析、代码实现到反爬优化,全面讲解了如何爬取国家标准文献。国家标准文献(National Standards Literature)是国家对各领域统一规范的文件,涵盖了技术参数、测试方法、生产工艺等内容。因此,通过自动化爬虫技术进行文献爬取和管理,不仅能解放劳动力,还可以提高数据管理效率。在构建爬虫前,我们需要对目标网站进行分析,包括页面结构、请求方式以及可能的反爬机制。

2201_76125261的博客 2104

阿里云ECS部署全流程:从服务器配置到项目上线实战指南

在云计算时代,将本地开发的应用部署到云服务器是开发者必须掌握的核心技能。其原理在于通过配置安全的网络环境与系统服务,为应用构建一个稳定、可远程访问的线上运行环境。这项技术的价值在于实现了应用的互联网化发布与持续服务,是产品从开发走向实际用户的关键一步。典型的应用场景包括个人项目上线、初创公司产品发布以及各类Web服务的云端托管。本文聚焦于阿里云ECS(弹性计算服务)的实战部署,详细解析了从服务器初始化、安全加固、运行环境搭建到项目打包上线的完整流程,涵盖了安全组配置、Nginx反向代理、PM2进程管理等关键

weixin_30591551的博客 394

全志T527-TP9930-Camera

TP9930 驱动模块主要实现将 4 路的 AHD/TVI/CVBS Camera 的数据转换为 BT656/BT1120 数据,从而实现在 T527 端来对数据进行处理和送显。

Linux驱动开发工程师,熟悉Linux/Android底层驱动、TP、显示、IIC、网络等通用外设调试适配,Linux上层应用开发。常用平台瑞芯微、全志、恩智浦等。 3232

Debian 9部署Tomcat 9实战:JDK8适配与systemd精细化托管

Tomcat作为Java Web应用的核心Servlet容器,其稳定运行依赖于JVM、操作系统内核与服务管理机制的深度协同。理解Servlet容器原理、JVM内存模型及Linux进程托管机制,是解决‘java: outofmemoryerror’‘java: 不支持发行版本’等高频问题的技术基础。在老旧但高可靠的Debian 9系统上,选择匹配的OpenJDK 8而非高版本JDK,可规避类加载器变更与GC日志不兼容风险;采用手动解压+systemd托管方案,能实现配置可审计、路径可预测、参数可复现的生产级部

chutisun0039的博客 412

【UNet 改进 | 注意机制篇】UNet引入CA注意力机制(2021 CVPR),二次创新

在医学图像分割任务中,病灶区域往往形态各异、边界模糊,且经常与周围组织的对比度较低,这要求模型具备极强的特征提取和细节辨别能力。传统的U-Net网络虽然通过跳跃连接融合了多尺度特征,但在处理复杂语义和精细边缘时仍有不足,尤其是在捕获特征时常常忽略位置信息。为了解决这些痛点,本文引入了在计算机视觉领域表现出色的 CA(Coordinate Attention,协调注意力)机制。CA 巧妙地将位置信息嵌入到了通道注意力中,通过水平和垂直两个方向的一维池化,同时捕获长距离依赖和精确的位置坐标。

在职AI算法工程师,擅长计算机视觉,YOLO目标检测、分割等,擅长web、pyqt界面可视化,好内容持续更新中,来这里跟大家一起学习,共同进步 183

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

上一篇: Weblogic 10.3.5/11g集群环境搭建
下一篇: Spring 的 BeanPostProcessor接口实现
7star_java
博客等级 码龄15年 80粉丝 127原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值