SpringMVC 接口版本管理/IP访问控制/ANT打包发布到LINUX

2023-10-27

前言

最近懒了很多也忙了很多,好多东西没办法分享到blog,因为知识点比较杂,没有时间整理。
写这篇文章主要原因是,因为遇到了同样的问题,但是网上没有很好的解决方案于是自己解决后,分享给大家   
源码在csdn download
文章尾部可以下载

IOC迭代版
SpringMVC IOC DI接口版本管理(迭代版)
http://blog.csdn.net/crazyzxljing0621/article/details/76677865
(2017-8-4更新 )
概述
1.springMVC 多版本接口 
2.接口有IP访问控制
3.支持jsonp
4.log发送到email
5.springMVC+mybatis
6.ANT打包通过SSH发布到linux 
7.springMVC @ResponseBody乱码问题

准备工作

Java8

安装java8环境 
java version "1.8.0_91"
Java(TM) SE Runtime Environment (build 1.8.0_91-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.91-b15, mixed mode)


Tomcat 7.x +

安装tomcat7.x或tomcat8 总之要支持java8

Ant

下载ant,配置ant环境变量。
设置ANT_HOME,然后path追加 %ANT_HOME%/bin;
Apache Ant(TM) version 1.10.1 compiled on February 2 2017


其他

Centos 64bit
有安装ant插件的eclipse
mysql

开始

多版本接口到底有何问题?

我们想提供多版本接口正常来看,获取一个version参数,通过判断不同参数,指向不同的函数或class
if(version == 1)
{
     Controller.save();
}
else if(version == 2)
{
    Controller.save(name)
}
高耦合不易修改,因为你要为你每个版本都提供一套if else...
按照之前网上一些文章所说我们可以在@RequestMapping中配置
@RequestMapping("/v1/xxxx")
public String save1()
@RequestMapping("/v2/xxxx")
public String save2()
耦合依然存在只不过是把if的操作交给了@requestMapping修改起来也不符合我们的最终目的

来看看我的思路

@requestMapping ("/{domain}/{version}")
class   CoreController{
     @requestMapping ("/**")
     public Object execute(@PathVariable domain,@PathVariable String version)
     {  
 return null;
     }
}
通过domain和version我们告诉抽象工厂去调用谁的 Controller
	/**
	 * 获取class
	 * 
	 * @param version
	 * @param domain
	 * @return
	 * @throws Exception
	 */
	private Class<?> selectClass(String version, String domain) throws Exception {
		switch (domain) {
		case ROOM:
			return ControllerAbstractFactoryImpl.instance(version).iRoomController().Class();
		case USER:
			return ControllerAbstractFactoryImpl.instance(version).iUserController().Class();

		default:
			return null;
		}
	}
package com.api.controller.factory;

import com.api.controller.factory.inf.IController;

/**
 * controller层抽象工厂
 * @author Allen 2017年5月24日
 *
 */
public interface IControllerAbstractFactory {

	IController iController() throws Exception; 

}
 通过反射来拼classPath并得到他的实例返回给使用者
package com.api.controller.factory;

import com.api.controller.factory.inf.IController;
import com.api.modules.Conf;
import com.api.util.exception.ApiVersionException;

/**
 * controller层抽象工厂
 * 
 * @author Allen 2017年5月24日
 *
 */
public class ControllerAbstractFactoryImpl implements IControllerAbstractFactory {

	/** class Constant **/
	final StringBuilder CONTROLLER_PATH = new StringBuilder("com.api.controller.factory.inf.Controller");

	private String version;

	private ControllerAbstractFactoryImpl(String version) {
		this.version = version;
	}

	private ControllerAbstractFactoryImpl() {
		// TODO Auto-generated constructor stub
	}

	public static IController instance(String version) throws Exception {
		if (!version.matches(Conf.PATTERN_COMPLIE_VERSION))
			throw new ApiVersionException();
		else
			return new ControllerAbstractFactoryImpl(version).iController();
	}

	@Override
	public IController iController() throws Exception {
		return  (IController) Class.forName(CONTROLLER_PATH.append(version).toString()).newInstance();
	}
	 
}
在CoreController中得到了对应版本和domain的Controller后,执行函数调用
这里通过反射来遍历目标class中所有的methods以及父级methods,寻找与我们 自定义的注释@requestAlias匹配的method并调用他,当然也是要判断我们自定义的注释
@RequestStrategyUtils,确保访问IP时策略内
	/**
	 * 执行目标函数
	 * 
	 * @param clazz
	 * @param method
	 * @return
	 * @throws NoSuchMethodException
	 * @throws InstantiationException
	 * @throws SecurityException
	 * @throws InvocationTargetException
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 */
	private int targetMethod(Class<?> clazz, HttpServletRequest req)
			throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
			SecurityException, InstantiationException {
		Method[] methods = clazz.getMethods();
		// 找到目标method并配置参数类型class
		for (Method m : methods) {
			// 通过注解判断是否匹配访问domain
			if (m.isAnnotationPresent(RequestAlias.class)
					&& m.getAnnotation(RequestAlias.class).value().equals(methodName)) {
				if (!ipControl(getRemoteHost(req), clazz, m)) {
					// ip不匹配访问权限
					return -1;
				}
				result = clazz.getMethod(m.getName(), m.getParameterTypes()).invoke(clazz.newInstance(), obParam);
				return 0;
			}
		}
		return -2;
	}
/**
	 * IP访问控制
	 * 
	 * @param request
	 * @param response
	 * @param handler
	 * @return
	 */
	private boolean ipControl(String requestIp, Class<?> clazz, Method m) { 
			if (clazz != null && m != null) {
				boolean isClazz = clazz.isAnnotationPresent(RequestStrategyUtils.class);
				boolean isMethod = m.isAnnotationPresent(RequestStrategyUtils.class);
				RequestStrategyUtils rc = null;
				// 如果方法和类声明中同时存在这个注解,那么方法中的会覆盖类中的设定。
				rc = isMethod ? m.getAnnotation(RequestStrategyUtils.class)
						: isClazz ? clazz.getAnnotation(RequestStrategyUtils.class) : null;
				if (rc == null)
					return false;
				String[] value = rc.ip();
				// 包含则true
				return Arrays.asList(value).stream().anyMatch(s -> s.equals(Conf.All_IP)
						|| ((s.equals(Conf.LOCAL_IP) || (s.equals(Conf.DEVELOP_IP))) && s.indexOf(requestIp) != -1));
			} 
		return false; 
	}
这里是我们的UserController1_1版本,他的父级是1_0
import com.api.modules.Conf;
import com.api.service.factory.ServiceAbstractFactoryImpl;
import com.api.util.annotations.RequestAlias;
import com.api.util.annotations.RequestStrategyUtils;

/**
 * 用户
 * 
 * @author Allen 2017年5月25日
 *
 */
@RequestStrategyUtils(ip = { Conf.LOCAL_IP, Conf.DEVELOP_IP })
public class UserController1_1 extends UserController1_0 {

	@RequestAlias("save")
	public Object save(String version, String name, String alias) throws Exception {
		// TODO Auto-generated method stub
		return ServiceAbstractFactoryImpl.instance(version).iUser().save(name, alias);
	}

}
通过以上步骤锁定目标Controller并进行调用成功
ResultValue是我们封装的针对返回值组装为Vo并利用spring jackson,自动返回为json格式
 
if (flag == -1) {// IP访问权限不足
return ResultValue.execute(State.IPPERMISSIONS, callback);
} else if (flag == -2) {// 找不到的访问域
return ResultValue.execute(State.DOMAINNOTFOUND, callback);
} else if (result == null) { // 返回值为null,controller业务参数判定有无
return ResultValue.execute(State.NPE, callback);
} else { // success
return ResultValue.execute(State.SUCCESS, result, callback);
}
result JSON:
{ state: "100", stateValue: "成功", value: [ { id: 1, name: "若风" }, { id: 2, name: "Miss&7号" }, { id: 3, name: "55开" } ] }
至此Controller多版本问题解决,并解耦
下面来看我们如果要增加一个新的版本就简单很多
1.新建UserController1_2
2.UserController1_2 extends UserController1_1
3.UserController1_2 编写新特性或重写老版本函数
4.然后在调用的时候 url version中传入1_2就可以了
5.无需修改任何IF ELSE
再看一下如何实现的多版本接口过程
1.用户发起请求 https://127.0.0.1/MyApi/room/1_1/save/李毅/国足大帝
2.CoreController是唯一添加了 @Controller的Controller类,所以他得到了请求
3.解析得到domain为room,version为1_1 ,请求method alias save ,传入参数 李毅,国足大帝
4.通过domain 选择不同的 具体Controller   
  switch (domain) {
		case ROOM:
			return ControllerAbstractFactoryImpl.instance(version).iRoomController().Class();
		case USER:
			return ControllerAbstractFactoryImpl.instance(version).iUserController().Class();
                 }
5.通过vesion在抽象工厂中通过反射得到目标版本的 Controller
6.回到CoreController。
7.拿着version版的Controller,去反射查alias匹配的method
8.查到method后再匹配ip访问权限
9.然后入参,调用
因为Controller提供的是访问控制,代码具体体现在参数和访问上,然而我们在具体的业务中,新版本接口可能差异从Dao就开始不同了。
我的做法是Service也做了抽象工厂的版本,当然Dao层我没有做,我认为没有必要,因为耦合永远都是存在的,无论是什么设计模式还是架构,只不过是把耦合从表面上放到了桌子下面,让更多的人无需了解桌子下面的细节罢了。

UML

其他

MySql

创建一个库myapi
CREATE TABLE `room` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(25) COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
 
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(25) COLLATE utf8_bin NOT NULL,
  `alias` varchar(25) COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

insert  into `room`(`id`,`name`) values (1,'若风'),(2,'Miss&7号'),(3,'55开');


乱码问题

按照我下面的web和springmvc的xml来配就不会有问题
web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	id="WebApp_ID" version="3.0">
	<display-name>liveApi</display-name>
	<filter>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>utf-8</param-value>
		</init-param>
	</filter>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list> 
	<servlet>
		<servlet-name>springDispatcherServlet</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<!-- 配置Spring mvc下的配置文件的位置和名称 -->
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>/WEB-INF/springmvc.xml</param-value>
		</init-param>

		<load-on-startup>1</load-on-startup>
	</servlet>
	<!-- 防止Spring内存溢出监听器 -->
	<listener>
		<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
	</listener>
	<servlet-mapping>
		<servlet-name>springDispatcherServlet</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	<!-- 静态资源访问 -->
	<servlet-mapping>
		<servlet-name>default</servlet-name>
		<url-pattern>*.css</url-pattern>
	</servlet-mapping>

	<servlet-mapping>
		<servlet-name>default</servlet-name>
		<url-pattern>*.gif</url-pattern>
	</servlet-mapping>

	<servlet-mapping>
		<servlet-name>default</servlet-name>
		<url-pattern>*.jpg</url-pattern>
	</servlet-mapping>

	<servlet-mapping>
		<servlet-name>default</servlet-name>
		<url-pattern>*.js</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>default</servlet-name>
		<url-pattern>*.html</url-pattern>
	</servlet-mapping>
	<!-- 异常页面捕获 -->
	<error-page>
		<exception-type>java.lang.Throwable</exception-type>
		<location>/500.html</location>
	</error-page>
	<error-page>
		<error-code>500</error-code>
		<location>/500.html</location>
	</error-page>
	<error-page>
		<error-code>404</error-code>
		<location>/404.html</location>
	</error-page>
</web-app>

springMVC.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
            http://www.springframework.org/schema/tx   
        http://www.springframework.org/schema/tx/spring-tx-4.0.xsd  
         http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">

	<!-- ====================================================== -->
	<!-- 配置@ResponseBody 保证返回值为UTF-8 -->
	<!-- 因为StringHttpMessageConverter默认是ISO8859-1 -->
	<!-- 用于使用@ResponseBody后返回中文避免乱码 -->
	<bean id="utf8Charset" class="java.nio.charset.Charset"
		factory-method="forName">
		<constructor-arg value="UTF-8" />
	</bean>
	<mvc:annotation-driven>
		<mvc:message-converters>
			<bean class="org.springframework.http.converter.StringHttpMessageConverter">
				<constructor-arg ref="utf8Charset" />
			</bean>
		</mvc:message-converters>
	</mvc:annotation-driven>
	<!-- 启动SpringMVC的注解功能,完成请求和注解POJO的映射 -->
	<bean id="mappingJacksonHttpMessageConverter"
		class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
		<property name="supportedMediaTypes">
			<list>
				<value>text/html;charset=UTF-8</value>
			</list>
		</property>
	</bean>
	<bean
		class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
		<property name="messageConverters">
			<list>
				<ref bean="mappingJacksonHttpMessageConverter" />	<!-- JSON转换器 -->
			</list>
		</property>
	</bean>
	<!-- ====================================================== -->
	<!-- 配置自动扫描的包 -->
	<context:component-scan base-package="com"></context:component-scan>

	<!-- ====================================================== -->
</beans>

配置conf.properties

properties调用很麻烦我们在一个conf.java中与之进行匹配和初始化
#=========================
#======== Mybatis ========
#=========================
url=jdbc:mysql://你的ip:3306/myapi?useUnicode=true&characterEncoding=utf-8&autoReconnect=true
driver=com.mysql.jdbc.Driver
username=root
password=123456

#=========================
#========  通用   ========
#=========================
#时间格式化标准(在不了解调用细节的情况下不建议修改)
date_format=yyyy-MM-dd HH:mm:ss
pattern_complie_version=^[0-9]\\d*_?[0-9]*$
#=================================
#========  邮件 && 日志   ========
#=================================
#邮件标题(local)
local_title=我是一个标题
#邮件标题(release)
release_title=我是发布后的标题
#邮件头 
mail_head_title=【异常】直播服务器
#错误日志收件人
notice_mail=123@qq.com
#发件箱账户
from_account=123@163.com;
#发件箱  
from_password=123
#发件箱smtp 
smtp_host=smtp.163.com 
这样以后在使用中就可以直接Conf.abc这样很方便,当然你还可以扩展他,改成debug模式,增加一个配置每次都去获取他的值,如果是true则重新获取properties数据
package com.api.modules;

import java.util.Properties;

import com.api.util.PropertiesUtil;

/**
 * 全局公用常量
 * 
 * @author Allen 2017年5月18日
 *
 */
public class Conf {

	/************************
	 * 内外网访问策略 Final不可配在conf.properties Controller注解中配置策略用
	 **********************/
	/** 本地ip **/
	public final static String LOCAL_IP = "127.0.0.1";
	/** 白名单机 **/
	public final static String DEVELOP_IP = "172.26.106.38";
	/** 全域 **/
	public final static String All_IP = "*";

	/************************
	 * 通用
	 **********************/
	public static String DATE_FORMAT = value("date_format");
	public static String PATTERN_COMPLIE_VERSION = value("pattern_complie_version");

	/************************
	 * Log && E-Mail
	 **********************/
	public static String LOCAL_TITLE = value("local_title");
	public static String RELEASE_TITLE = value("release_title");
	public static String MAIL_HEAD_TITLE = value("mail_head_title");
	public static String NOTICE_MAIL = value("notice_mail");
	public static String FROM_ACCOUNT = value("from_account");
	public static String FROM_PASSWORD = value("from_password");
	public static String SMTP_HOST = value("smtp_host");

	static Properties properties;
	static {
		properties = PropertiesUtil.getProperties("conf.properties");
	}

	private static String value(String key) {
		if (properties == null)
			properties = PropertiesUtil.getProperties("conf.properties");
		return properties.getProperty(key);
	}
}

Log&Mail

这里没什么好说的得到exception堆栈日志,发送到邮箱即可,注意的是邮件标题很有可能被邮箱拒收,被认作垃圾邮件,所以有条件还是用公司自己的smtp邮件服务器好

Ant 

ant环境变量安装好后,执行build.xml 进行发布。记得看好配置,这个ant支持多服务器发布,所以会弹出选框。
jsch-0.1.54.jar  
SSH2的jar,把这个添加到ant中,Windows->preferences->ant->runtime->classpath->ant home Entries 把这个jar添加进去

org.eclipse.jdt-4.6.3.zip
org.eclipse.jdt.compiler.tool_1.1.100.v20160418-1457.jar
org.eclipse.jdt.core_3.12.3.v20170228-1205.jar
org.eclipse.jdt.debug.ui_3.7.201.v20160811-0450.jar
把zip解压缩把以上3个jar放到 ant/lib中,然后在eclipse->选中build.xml->run as -> 第二个ant build -> JRE -> select " run in  the same  JRE as the workspace "

总结

最后你发现你不需要维护if else  ,你只需要做一个新的controller来集成父级,来写新的业务即可,其他的都不需要你考虑的
看看我们用抽象工厂和反射来解决了这个看似复杂的问题
我们不需要在if(version),我们只需要extends,其他任何细节都不需要考虑,是不是美妙了许多 偷笑

下载地址

http://download.csdn.net/detail/crazyzxljing0621/9852818

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringMVC 接口版本管理/IP访问控制/ANT打包发布到LINUX 的相关文章

随机推荐

  • Mac下使用命令行 mvn 给Maven打包

    使用命令行 mvn 给Maven打包 sudo mvn clean install Dmaven test skip true Dmaven javadoc skip true Dmaven test skip true 跳过单元测试 Dm
  • wms仓储信息化的应用和发展趋势

    随着在线零售市场日益成熟 电子商务不断蓬勃发展 电商仓储需求也呈现高速增长的态势 仓储业也进入到了质的变化阶段 wms仓储信息化的应用和发展趋势 在电商供应链中 企业尤为关心的 是如何把货物更快更准确地送到客户手中 以及如何应对随时变化的订
  • 畅购中

    项目第七天 ES类型 要答出 type版本前和版本后的改变 ES查询方法 使用ElasticsearchRestTemplate对象来构建 ES的默认规则 ES能够自动存储未提交创建字段信息的数据 目的 未指定时ES为了可以更好的支持聚合和
  • python列表索引超出范围怎么解决_Python的列表怎么用?你会吗?Python每日学习打卡...

    Python的列表怎么用 你会用吗 本文主要介绍了Python中列表 List 的详解操作方法 包含创建 访问 更新 删除 其它操作等 需要的朋友可以参考下 Python列表 1 创建列表 只要把逗号分隔的不同的数据项使用方括号括起来即可
  • MFC CListctrl里面使用编辑框和下拉框

    对于需要使用到子控件的单元格 就把子控件移动到需要使用的位置就好 1 创建工程 添加控件CEdit和CListCtrl到对话框 分别添加控件变量 protected CEdit m Edit CListCtrl m ListCtrl int
  • 分布式注册中心 Eureka 与 zookeeper 的区别、原理及各自优缺点

    前言 在微服务的开发过程中 如果使用的是 Dubbo 那就必须使用到 Zookeeper 在使用 Spring Cloud Eureka 时 自然其功能更强大得多 博主也不得不感叹 Spring Cloud Eureka 后来者居上呀 Du
  • vue3 使用 vue.config.js 配置使用scss全局变量

    vue3 使用 vue config js 配置使用scss全局变量 记录学习和开发中遇到的问题或难题 刚开始我在网上查找了许多资料 都是需要什么安装安装 sass resources loader 和配置什么乱七八糟的 我没有尝试过 因为
  • 【社区图书馆】《实战大数据—— 分布式大数据分析处理系统开发与应用》书评

    实战大数据 分布式大数据分析处理系统开发与应用 从大数据技术基础概念出发 介绍了大数据分析的流程和大数据分析处理系统的组成 以及大数据集群的搭建 并在此基础上讲解了多种不同技术构成的离线 实时数据分析系统实战项目 全书共10章 包括大数据概
  • Vue.js 项目查看 vue版本号

    vue V或者是vue version查询的是vue cli的版本 也就是vue脚手架的版本 如果想要查看vue的版本 直接去项目中 在根目录下 找到package json文件夹 找 dependencies 然后就可以看到你装的vue的
  • day2作业

    作业说明 请在下方提示位置 补充代码 完成 青春有你2 选手图片爬取 将爬取图片进行保存 保证代码正常运行 打印爬取的所有图片的绝对路径 以及爬取的图片总数 此部分已经给出代码 请在提交前 一定要保证有打印结果 如下图所示 深度学习一般过程
  • nvm包管理工具下载安装

    1 去github官网 输入nvm windows 点击第一个nvm项目 在右侧点击releases 选择箭头指向的安装包 2 下载很快 但是安装前 得先卸载本机的nodejs 并且为nvm的包创建一个英文文件夹 这里我在D盘创建了一个no
  • JAVA遇见HTML—JSP篇—Mac系统(一.JAVA WEB)

    1 什么是Web应用程序 Web应用程序是一种可以通过Web访问的应用程序 Web应用程序的最大好处是用户很容易访问应用程序 用户只需要有浏览器即可 不需要再安装其他软件 为什么要学习Web应用程序 我们说Web应用程序开发 是目前软件开发
  • CC00202.CloudKubernetes——

    一 NoSchedule静止调度 容器强制驱逐 为master01打一个污点 NoSchedule类型 静止调度 容器会被强制驱逐 为master01节点打入污点 NoExecute类型 root k8s master01 kubectl
  • vscode统计项目代码行数插件——vecode counter

    vscode统计项目代码行数插件 vscode counter vscode counter 安装插件 使用方式 插件缺点 仅针对go来说的 vscode counter 安装插件 按照途中的地方进行搜索就能找到该插件的入口 点击insta
  • 如何监控windows进程的句柄、内存和cpu(二)

    接下来 我们看如何获取进程的CPU使用率 CPU使用率 指进程在一段时间内消耗的CPU时间与该时间段长度的比值 windows本身并没有提供直接获取进程CPU使用率的函数 但我们可以根据进程的计时信息来间接计算出进程的瞬时CPU占用 1 记
  • 抖音广告如何起量,这四点不能忽视

    抖音广告如何起量 你要知道这几点 抖音是一个流行短视频平台 我们在其中经常能看见一些热门的精彩视频广告和经典案例广告 很精彩也很吸引人 可是你知道这些优质的视频广告是如何拍出来的吗 快来跟小编看看 1 背景音乐的选择 抖音抖音 音 很重要
  • 登录文件服务器 换用户,win7切换用户访问共享、切换用户账户访问共享、共享文件夹切换用户的方法...

    现在 很多单位都有文件服务器 通常会对局域网设置共享 并且为了方便访问 通常就会设置 记住访问密码 这样以后访问共享文件时就不需要每次都输入密码了 虽然方便了共享文件访问 但是 当用户想切换访问共享文件的用户时 就比较麻烦 具体如何操作呢
  • 如何防御Java中的SQL注入

    SQL注入是应用程序遭受的最常见的攻击类型之一 鉴于其常见性及潜在的破坏性 需要在了解原理的基础上探讨如何保护应用程序免受其害 什么是SQL注入 SQL注入 也称为SQLi 是指攻击者成功篡改Web应用输入 并在该应用上执行任意SQL查询
  • C、C++、C#、python、java编程—程序结构

    C资料 菜鸟教程 C语言中文网 C community C 资料 菜鸟教程 cplusplus C community C 资料 菜鸟教程 microsoftC 文档 python资料 菜鸟教程 python标准库 Java资料 菜鸟教程
  • SpringMVC 接口版本管理/IP访问控制/ANT打包发布到LINUX

    前言 最近懒了很多也忙了很多 好多东西没办法分享到blog 因为知识点比较杂 没有时间整理 写这篇文章主要原因是 因为遇到了同样的问题 但是网上没有很好的解决方案于是自己解决后 分享给大家 源码在csdn download 文章尾部可以下载