当前位置:首页 » 网页前端 » webapi20
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

webapi20

发布时间: 2023-04-15 17:11:09

A. JRebel启动报错

项目概况:SpringMVC

新接手的项目,安装JRebel插誉喊迟件(JRebel for IntelliJ v2019.1.1)后,启动报错,在此之前是可以正常启动项目。

报错核心信息: Exception in thread "Timer-RefreshDataTask" java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext

报庆李错详细信息:

五月 10, 2019 10:37:36 上午 org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc

严重: The web application [/edi-web] registered the JDBC driver [com.alibaba.druid.proxy.DruidDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.

五月 10, 2019 10:37:36 上渗伏午 org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc

严重: The web application [/edi-web] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.

五月 10, 2019 10:37:36 上午 org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc

严重: The web application [/edi-web] registered the JDBC driver [oracle.jdbc.driver.OracleDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.

五月 10, 2019 10:37:36 上午 org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks

严重: The web application [/edi-web] created a ThreadLocal with key of type [net.sf.json.AbstractJSON.CycleSet] (value [net.sf.json.AbstractJSON$CycleSet@52abeb56]) and a value of type [java.lang.ref.SoftReference] (value [java.lang.ref.SoftReference@73639524]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.

[2019-05-10 10:37:36,507] Artifact xbwl-edi-web:war exploded: Error ring artifact deployment. See server log for details.

log4j:WARN No appenders could be found for logger (org.springframework.scheling.quartz.SchelerFactoryBean).

log4j:WARN Please initialize the log4j system properly.

log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.

五月 10, 2019 10:37:45 上午 org.apache.catalina.loader.WebappClassLoader loadClass

信息: Illegal access: this web application instance has been stopped already.  Could not load org.springframework.core.NestedExceptionUtils.  The eventual following stack trace is caused by an error thrown for debugging purposes as well as to attempt to terminate the thread which caused the illegal access, and has no functional impact.

java.lang.IllegalStateException

at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1612)

at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1571)

at org.springframework.core.NestedRuntimeException.<clinit>(NestedRuntimeException.java:45)

at org.springframework.scheling.quartz.SchelerFactoryBean$1.run(SchelerFactoryBean.java:673)

Exception in thread "Quartz Scheler [SYSSTATIC_SCHEDULE]" java.lang.NoClassDefFoundError: org/springframework/core/NestedExceptionUtils

at org.springframework.core.NestedRuntimeException.<clinit>(NestedRuntimeException.java:45)

at org.springframework.scheling.quartz.SchelerFactoryBean$1.run(SchelerFactoryBean.java:673)

Caused by: java.lang.ClassNotFoundException: org.springframework.core.NestedExceptionUtils

at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1720)

at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1571)

... 2 more

Exception in thread "Timer-RefreshDataTask" java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext

at org.springframework.context.support..getBeanFactory(.java:170)

at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:985)

at com.xbwl.core.cache.CacheManager.<init>(CacheManager.java:20)

at com.xbwl.core.cache.CacheManager.getInstance(CacheManager.java:54)

at com.xbwl.core.mq.rabbitMq.service.impl.RabbitMqServiceImpl$RefreshDataTask.run(RabbitMqServiceImpl.java:107)

at java.util.TimerThread.mainLoop(Timer.java:555)

at java.util.TimerThread.run(Timer.java:505)

Exception in thread "Timer-RefreshDataTask" java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext

at org.springframework.context.support..getBeanFactory(.java:170)

at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:985)

at com.xbwl.core.cache.CacheManager.<init>(CacheManager.java:20)

at com.xbwl.core.cache.CacheManager.getInstance(CacheManager.java:54)

at com.xbwl.core.mq.MqInterceptor.initMqCache(MqInterceptor.java:70)

at com.xbwl.core.mq.MqInterceptor.access$000(MqInterceptor.java:26)

at com.xbwl.core.mq.MqInterceptor$RefreshDataTask.run(MqInterceptor.java:64)

at java.util.TimerThread.mainLoop(Timer.java:555)

at java.util.TimerThread.run(Timer.java:505)

Exception in thread "Timer-RefreshDataTask" java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext

at org.springframework.context.support..getBeanFactory(.java:170)

at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:985)

at com.xbwl.core.cache.CacheManager.<init>(CacheManager.java:20)

at com.xbwl.core.cache.CacheManager.getInstance(CacheManager.java:54)

at com.xbwl.core.service.impl.BaiWebApiServiceImpl$RefreshDataTask.run(BaiWebApiServiceImpl.java:41)

at java.util.TimerThread.mainLoop(Timer.java:555)

at java.util.TimerThread.run(Timer.java:505)

暂未解决,待续

B. mob短信验证错误码

错误码参考

SMSSDK for Android API回调中,当result=SMSSDK.RESULT_ERROR,则data的类型为Throwable;如果这个Throwable的message就存放有json数据,你可以从中读取status的错误码信息。一部分是服务器返回的。还有一部分是SDK本地生成的。
服务器错误码:
错误码 描述 说明
400 无效请求 客户端请求不能被识别。
405 AppKey为空 请求的AppKey为空。
406 AppKey错误 请求的AppKey不存在。
407 缺少数据 请求提交的数据缺少必要的数据。
408 无效的参数 无效的请求参数。
418 内部接口调用失败 内部接口调用失败。
450 权限不足 无权执行该操作。
454 数据格式错误 请求传递的数据格式错误,服务器无法转换为JSON格式的数据。
455 签名无效 签名检验。
456 手机号码为空 提交的手机号码或者区号为空。
457 手机号码格式错误 提交的手机号格式不正确(包括手机的区号)。
458 手机号码在黑名单中 手机号码在发送黑名单中。
459 无appKey的控制数据 获取appKey控制发送短信的数据失败。
460 无权限发送短信 没有打开客户端发送短信的开关。
461 不支持该地区发送短信 没有开乱扮通给当前地区发送短信的功能。
462 每分钟发送次数超限 每分钟发送短信的数量超过限制。
463 手机号码每天发送次数超限 手机号码在当前APP内每天发送短早陪码信的次数超出限制。
464 每台手机每天发送次数超限 每台手机每天发送短信的次数超限。
465 号码在App中每天发送短信的次数超限 手机号码在APP中每天发送短信的数量超限。
466 校验的验证码为空 提交的校验验证码为空。
467 校验验证码请求频繁 5分钟内校验错误超过3次,验证码失效。
468 需要校验的验证码错误 用户提交校验的验证码错误。
469 未开启web发送短信 没有打开通过网页端发送短信的开关。
470 账户余额不足 账户的短信余额不足。
471 请求IP错误 通过服务端发送或验证短信的IP错误
472 客户端请求发送短信验证过于频繁 客户端请求发送短信验证过于频繁
473 服务端根据id获取平台错误 服务端根据id获取平台错误
474 没有打开服务端验证开关 没有打开服务端验证开关
475 appKey的应用信息不存在 appKey的应用信息不存在
476 当前appkey发送短信的数量超过限额 如果当前appkey对应的包名陆哪没有通过审核,每天次appkey+包名最多可以发送20条短信
477 当前手机号发送短信的数量超过限额 当前手机号码在SMSSDK平台内每天最多可发送短信10条,包括客户端发送和WebApi发送
478 当前手机号在当前应用内发送超过限额 当前手机号码在当前应用下 12小时内最多可发送文本验证码5条
500 服务器内部错误 服务端程序报错。
本地错误码:
错误码 描述 说明
600 API使用受限制 API使用受限制
601 短信发送受限 短信发送受限
602 无法发送此地区短信 无法发送此地区短信
603 请填写正确的手机号码 请填写正确的手机号码
604 当前服务暂不支持此国家 当前服务暂不支持此国家,请选择其它国家

C. webapi 返回类型到底应该是什么才合适,这是个问题

我们知道在WebAPi中对于响应结果我们都是这样用的:
public HttpResponseMessage GetResult<T>(T t)
{
return Request.CreateResponse<T>(HttpStatusCode.OK, t);
}

在项目中前端为了和其他统一,封装了一套响应的结果和状态码,要求直接返回对象,于是将上述修改成比如如下:

public Result<List<Person>> GetResult()
{
var result = new Result<List<Person>>();
return result;
}

public class Result<T> : BaseResult
{
public T Data;
}

public class BaseResult
{
public string Message;
public int Status;
public ErrorCode ErrorCode;
}

public enum ErrorCode
{
......
}

统观以上两种方法,一种是WebAPi内置响应的结果,另外一种则是直接返回自定义响应结果。
于是乎,我开始思索这两种方法虽然都能得到我们想要的结果,但是有什么区别没有呢?说的更加明确一点的是,二者在数据响应上有没有性能上的差异呢?
WebAPi响应结果和自定义响应结果二者性能差异
以上则是需要返回对象来进行处理,而有些我们则不需要返回任何对象来进行处理例如直接返回void,而在WebAPi中对应需要返回 IHttpActionResult 例如自定义返回则是如下:
public void GetFirst()
{.....}

在WebAPi中则是进行如下返回:
public IHttpActionResult GetSecond()
{
return OK();
}

下面我们在控制台中分别来测试这二者在WebHost以及在SelfHost上的差异,我们如何获取其差异呢?我们通过对void方法和http方法在控制台中发出1000个请求来获取其总共花费时间来进行比较。
SelfHost

[HttpGet]
public void GetFirst()
{
StringBuilder stringbuilder = new StringBuilder();
for (int i = 0; i < 20; i++)
{
stringbuilder.Append("something");
}
}

[HttpGet]
public IHttpActionResult GetSecond()
{
StringBuilder stringbuilder = new StringBuilder();
for (int i = 0; i < 20; i++)
{
stringbuilder.Append("something");
}
return Ok();
}

在控制台中方法如下:

private const string voidUrl = "http://localhost:8080/api/home/GetFirst";
private const string httpUrl = "http://localhost:8080/api/home/GetSecond";
private static List<TimeSpan> voidTimes = new List<TimeSpan>();
private static List<TimeSpan> httpTimes = new List<TimeSpan>();
static void Main(string[] args)
{
Console.WriteLine("Start Test....");
for (int i = 0; i < 1000; i++)
{
voidTimes.Add(getResponse(voidUrl));
Thread.Sleep(10);
Console.WriteLine("void Test " + i);
}
Console.WriteLine("Finished Void Test");
for (int i = 0; i < 1000; i++)
{
httpTimes.Add(getResponse(httpUrl));
Thread.Sleep(10);
Console.WriteLine("http Test " + i);
}
Console.WriteLine("Finished Http Test");
var voidTotalTime = voidTimes.Sum(t => t.Milliseconds);
Console.WriteLine("void方法发出1000个请求总共需要时间:" + voidTotalTime);
Console.WriteLine("void方法平均每一个请求需要时间:" + voidTotalTime / 1000.00 + "秒");

var httpTotalTime = httpTimes.Sum(t => t.Milliseconds);
Console.WriteLine("http方法发出1000个请求总共需要时间: " + httpTotalTime);
Console.WriteLine("http方法平均每一个请求需要时间: " + httpTotalTime / 1000.00 + "秒");

Console.Read();
}

static TimeSpan getResponse(string url)
{
var stopWatch = new Stopwatch();
stopWatch.Start();
var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(url);
var task = httpClient.GetAsync(httpClient.BaseAddress).Result;
var result = task.Content.ReadAsAsync(typeof(object));
var timeSpan = stopWatch.Elapsed;
stopWatch.Stop();
return timeSpan;
}

D. 用MVC WebApi写接口,网闸上了之后,方法访问不到,端口已经全部开放

VisualStudio为我们提供了专门用于创建ASP.NETWebAPI应用的项目模板,借助于此项目模板提供的向导,我们可以“一键式”创建一个完整的ASP.NETWebAPI项目。在项目创建过程中,VisualStudio会自动为我们添加必要的程序集引用和配置,甚至会为我们自动生成相关的代码,总之一句话:这种通过向导生成的项目在被创建之后其本身就是一个可执行的应用。对于IDE提供的这种旨在提高生产效率的自动化机制,我个人自然是推崇的,但是我更推荐读者朋友们去了解一下这些自动化机制具体为我们做了什么?做这些的目的何在?哪些是必需的,哪些又是不必要的?正是基于这样的目的,在接下来演示的实例中,我们将摒弃VisualStudio为我们提供的向导,完全在创建的空项目中编写我们的程序。这些空项目体现在如右图所示的解决方案结构中。如右图所示,整个解决方案一共包含6个项目,上面介绍的作为“联系人管理器”的单页Web应用对应着项目WebApp,下面的列表给出了包括它在内的所有项目的类型和扮演的角色。·Common:这是一个空的类库项目,仅仅定义了表示联系人的数据类型而已。之所以将数据类型定义在独立的项目中,只要是考虑到它会被多个项目(WebApi和ConsoleApp)所使用。WebApi:这是一个空的类库项目,表现为HttpController类型的WebAPI就定义在此项目中,它具有对Common的项目引用。WebHost:这是一个空的ASP.NETWeb应用,它实现了针对ASP.NETWebAPI的WebHost寄宿,该项目具有针对WebApi的项目引用。SelfHost:这是一个空的控制台应用,旨在模拟ASP.NETWebAPI的SelfHost寄宿模式,它同样具有针对WebApi的项目引用。WebApp:这是一个空的ASP.NETWeb应用,代表“联系人管理器”的网页就存在于该项目之中,至于具体的联系人管理功能,自然通过以Ajax的形式调用WebAPI来完成。ConsoleApp:这是一个空的控制台应用,我们用它来模拟如何利用客户端代理来实现对WebAPI的远程调用,它具有针对Common的项目引用。二、定义WebAPI在正式定义WebAPI之前,我们需要在项目Common中定义代表联系人的数据类型Contact。简单起见,我们仅仅为Contact定义了如下几个简单的属性,它们分别代表联系人的ID、姓名、联系电话、电子邮箱和联系地址。1:publicclassContact2:{3:publicstringId{get;set;}4:publicstringName{get;set;}5:publicstringPhoneNo{get;set;}6:publicstringEmailAddress{get;set;}7:publicstringAddress{get;set;}8:}表现为HttpController的WebAPI定义在WebApi项目之中,我们一般将ApiController作为继承的基类。ApiController定义在“System.Web.Http.dll”程序集中,我们可以在目录“%ProgramFiles%\MicrosoftASP.NET\ASP.NETWebStack5\Packages\”中找到这个程序集。具体来说,该程序集存在于子目录“Microsoft.AspNet.WebApi.Core.5.0.0\lib\net45”中。WebAPI体现在如下所示的ContactsController类型中。在该类型中,我们定义了Get、Post、Put和Delete这4个Action方法,它们分别实现了针对联系人的查询、添加、修改和删除操作。Action方法Get具有一个表示联系人ID的可缺省参数,如果该参数存在则返回对应的联系人,否则返回整个联系人列表。由于ASP.NETWebAPI默认实现了Action方法与HTTP方法的映射,所以方法名也体现了它们各自所能处理请求必须采用的HTTP方法。1:publicclassContactsController:ApiController2:{3:staticListcontacts;4:staticintcounter=2;5:6:staticContactsController()7:{8:contacts=newList();9:contacts.Add(newContact{Id="001",Name="张三",10:PhoneNo="0512-12345678",EmailAddress="[email protected]",11:Address="江苏省苏州市星湖街328号"});12:contacts.Add(newContact{Id="002",Name="李四",13:PhoneNo="0512-23456789",EmailAddress="[email protected]",14:Address="江苏省苏州市金鸡湖大道328号"});15:}16:17:publicIEnumerableGet(stringid=null)18:{19:returnfromcontactincontacts20:wherecontact.Id==id||string.IsNullOrEmpty(id)21:selectcontact;22:}23:24:publicvoidPost(Contactcontact)25:{26:Interlocked.Increment(refcounter);27:contact.Id=counter.ToString("D3");28:contacts.Add(contact);29:}30:31:publicvoidPut(Contactcontact)32:{33:contacts.Remove(contacts.First(c=>c.Id==contact.Id));34:contacts.Add(contact);35:}36:37:publicvoidDelete(stringid)38:{39:contacts.Remove(contacts.First(c=>c.Id==id));40:}41:}简单起见,我们利用一个静态字段(contacts)表示存储的联系人列表。当ContactsController类型被加载的时候,我们添加了两个ID分别为“001”和“002”的联系人记录。至于实现联系人CRUD操作的Action方法,我们也省略了必要的验证,对于本书后续的演示的实例,我们基本上也会采用这种“简写”的风格。