版权声明:本文为HaiyuKing原创文章,转载请注明出处!

前言

这个Demo只是记录极光推送的集成,不能运行。

使用步骤

一、项目组织结构图

注意事项:

1、  导入类文件后需要change包名以及重新import R文件路径

2、  Values目录下的文件(strings.xml、dimens.xml、colors.xml等),如果项目中存在,则复制里面的内容,不要整个覆盖

二、导入步骤

2.1、接入准备

参考官网《3 分钟快速使用 JPush Android Demo

创建极光推送开发者帐号——》创建应用——》获取APPkey

2.2、下载SDK

如果使用自动集成的话,不需要下载SDK,不过我个人倾向于手动集成,所以需要下载SDK。

下载地址:https://docs.jiguang.cn/jpush/resources/

下载后的压缩包解压后的目录:

说明:

2.3、集成SDK

为了便于管理,我在Demo中新建了一个ThirdLib的module,用于集成SDK。

(1)新建ThirdLib的module,并在app的build.gradle中引用

    //引用thirdlib
implementation project(':thirdlib')

(2)在ThirdLib这个module中集成SDK

  • 复制 libs/jcore-android-1.x.x.jar 到工程 libs/ 目录下。
  • 复制 libs/jpush-android-3.x.x.jar 到工程 libs/ 目录下。
  • 复制 libs/(cpu-type)/libjcore1xy.so 到你的工程中存放对应 cpu 类型的目录下(使用 jniLibs 文件夹导入 so 文件,则仅需将所有 cpu 类型的文件夹拷进去)。
  • 复制 res/ 中 drawable-hdpi, layout, values 文件夹中的资源文件到你的工程中 res/ 对应同名的目录下。
  • 定义没有阴影和渐变色的 jpush_notification_icon 资源文件并添加到drawable-hdpi目录下(若没有 res/drawable-xxxx/jpush_notification_icon 这个资源默认使用应用图标作为通知 icon,在 5.0 以上系统将应用图标作为 statusbar icon 可能显示不正常)。

因为是在thirdlib这个module中集成jar包,所以还需要在thirdlib这个module的build.gradle文件中引用libs目录下的jar包。

apply plugin: 'com.android.library'

android {
compileSdkVersion 28 defaultConfig {
minSdkVersion 16
targetSdkVersion 28
versionCode 1
versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
} } dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' //极光推送SDK
api files('libs/jcore-android-1.2.6.jar')
api files('libs/jpush-android-3.1.8.jar')
}

(3)配置 AndroidManifest.xml【注意是app这个module中的,不是thirdlib这个module中的】

注意下面标记橙色代码:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.why.project.jpushdemo"> <!-- ======================极光推送SDK====================== -->
<!-- Required -->
<permission
android:name="${applicationId}.permission.JPUSH_MESSAGE"
android:protectionLevel="signature" /> <!-- Required 一些系统要求的权限,如访问网络等-->
<uses-permission android:name="${applicationId}.permission.JPUSH_MESSAGE" />
<uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!--(必须需要,否则设置别名失败)-->
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<!--(必须需要,否则设置别名失败)-->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- Optional for location -->
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <!-- 用于开启 debug 版本的应用在6.0 系统上 层叠窗口权限 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_TASKS" /> <application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity> <!-- ======================极光推送SDK========================== -->
<!-- 状态通知栏需要打开的Activity -->
<activity android:name="com.why.project.jpushdemo.jpush.JpushActivity"
android:exported="false">
<intent-filter>
<action android:name="jpush.testAction" />
<category android:name="jpush.testCategory" />
</intent-filter>
</activity> <!-- Rich push 核心功能 since 2.0.6-->
<activity
android:name="cn.jpush.android.ui.PopWinActivity"
android:theme="@style/MyDialogStyle"
android:exported="false">
</activity> <!-- Required SDK核心功能-->
<activity
android:name="cn.jpush.android.ui.PushActivity"
android:configChanges="orientation|keyboardHidden"
android:theme="@android:style/Theme.NoTitleBar"
android:exported="false">
<intent-filter>
<action android:name="cn.jpush.android.ui.PushActivity" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="${applicationId}" />
</intent-filter>
</activity> <!-- Required SDK 核心功能-->
<!-- 可配置android:process参数将PushService放在其他进程中 -->
<service
android:name="cn.jpush.android.service.PushService"
android:process=":pushcore"
android:exported="false">
<intent-filter>
<action android:name="cn.jpush.android.intent.REGISTER" />
<action android:name="cn.jpush.android.intent.REPORT" />
<action android:name="cn.jpush.android.intent.PushService" />
<action android:name="cn.jpush.android.intent.PUSH_TIME" />
</intent-filter>
</service>
<!-- since 3.0.9 Required SDK 核心功能-->
<provider
android:authorities="${applicationId}.DataProvider"
android:name="cn.jpush.android.service.DataProvider"
android:process=":pushcore"
android:exported="false"
/> <!-- since 1.8.0 option 可选项。用于同一设备中不同应用的JPush服务相互拉起的功能。 -->
<!-- 若不启用该功能可删除该组件,将不拉起其他应用也不能被其他应用拉起 -->
<service
android:name="cn.jpush.android.service.DaemonService"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="cn.jpush.android.intent.DaemonService" />
<category android:name="${applicationId}" />
</intent-filter> </service>
<!-- since 3.1.0 Required SDK 核心功能-->
<provider
android:authorities="${applicationId}.DownloadProvider"
android:name="cn.jpush.android.service.DownloadProvider"
android:exported="true"
/>
<!-- Required SDK核心功能-->
<receiver
android:name="cn.jpush.android.service.PushReceiver"
android:enabled="true"
android:exported="false">
<intent-filter android:priority="1000">
<action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_PROXY" /> <!--Required 显示通知栏 -->
<category android:name="${applicationId}" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.USER_PRESENT" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
<!-- Optional -->
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" /> <data android:scheme="package" />
</intent-filter>
</receiver> <!-- Required SDK核心功能-->
<receiver android:name="cn.jpush.android.service.AlarmReceiver" android:exported="false"/> <!-- User defined. For test only 用户自定义的广播接收器-->
<receiver
android:name="com.why.project.jpushdemo.jpush.JpushReceiver"
android:exported="false"
android:enabled="true">
<intent-filter>
<action android:name="cn.jpush.android.intent.REGISTRATION" /> <!--Required 用户注册SDK的intent-->
<action android:name="cn.jpush.android.intent.MESSAGE_RECEIVED" /> <!--Required 用户接收SDK消息的intent-->
<action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED" /> <!--Required 用户接收SDK通知栏信息的intent-->
<action android:name="cn.jpush.android.intent.NOTIFICATION_OPENED" /> <!--Required 用户打开自定义通知栏的intent-->
<action android:name="cn.jpush.android.intent.CONNECTION" /><!-- 接收网络变化 连接/断开 since 1.6.3 -->
<category android:name="${applicationId}" />
</intent-filter>
</receiver> <!-- User defined. For test only 用户自定义接收消息器,3.0.7开始支持,目前新tag/alias接口设置结果会在该广播接收器对应的方法中回调-->
<receiver android:name="com.why.project.jpushdemo.jpush.MyJPushMessageReceiver">
<intent-filter>
<action android:name="cn.jpush.android.intent.RECEIVE_MESSAGE" />
<category android:name="${applicationId}"></category>
</intent-filter>
</receiver>
<!-- Required . Enable it you can get statistics data with channel -->
<meta-data android:name="JPUSH_CHANNEL" android:value="developer-default"/>
<meta-data android:name="JPUSH_APPKEY" android:value="9fed5bcb7b9b87413678c407" /> <!-- </>值来自开发者平台取得的AppKey--> </application> </manifest>

(4)在项目中添加jpush包中的文件

其中,关键的是JpushActivity和JpushReceiver这两个文件。

JpushReceiver:主要用于点开通知栏,判断跳转打开的界面

JpushActivity:主要用于展现点击通知打开的界面;

package com.why.project.jpushdemo.jpush;

import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.KeyEvent;
import android.view.View;
import android.widget.TextView; import com.why.project.jpushdemo.R; import org.json.JSONException;
import org.json.JSONObject; import cn.jpush.android.api.JPushInterface; /**
* Used 极光推送点开通知后打开的界面
* 和WebViewPreviewActivity共用一个布局文件
* 需要先检查是否已经登录,如果没有登录,直接登录即可,不需要返回到登录界面了
* 极光推送SDK
*/
public class JpushActivity extends AppCompatActivity {
private static final String TAG = JpushActivity.class.getSimpleName(); /**从登录界面打开的标记(传递参数用)*/
public static final String EXTRA_ONLOGIN = "onlogin"; /*Jpush传递过来的参数*/
private Bundle jPushBundle;
/**通知标题*/
private String jPushTitle;
/**通知内容*/
private String jPushContent;
/**通知附加字段*/
private String jPushExtraJson;
/**通知id值*/
private int jPushId; //展现在导航栏上的标题
private String bundle_title;
//网页url地址
private String bundle_url; /**标记是否从登录界面打开的状态值*/
private boolean bundle_onlogin = false; private Context mContext; private Toolbar mToolbar; private MyWebView myWebView; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_webviewpreview); mContext = this; //初始化控件
initViews();
//初始化数据
initData();
initToolBar();//初始化toolbar
} @Override
public void onDestroy()
{
//销毁webview控件
myWebView.removeAllViews();
myWebView.destroy();
super.onDestroy();
} /**
* 初始化view
*/
private void initViews() {
myWebView = (MyWebView)findViewById(R.id.id_webView);
myWebView.setCanBackPreviousPage(true,JpushActivity.this);//可以返回上一页
} /**
* 初始化数据【接收点击通知栏传过来的数据:通知、自定义消息两种(这里只需要处理通知的即可)】
*/
private void initData() {
Intent intent = getIntent();
if (null != intent) {
jPushBundle = getIntent().getExtras();
jPushTitle = jPushBundle.getString(JPushInterface.EXTRA_NOTIFICATION_TITLE);//保存服务器推送下来的通知的标题
jPushContent = jPushBundle.getString(JPushInterface.EXTRA_ALERT);//保存服务器推送下来的通知内容
jPushExtraJson = jPushBundle.getString(JPushInterface.EXTRA_EXTRA);//保存服务器推送下来的附加字段。这是个 JSON 字符串
jPushId = jPushBundle.getInt(JPushInterface.EXTRA_NOTIFICATION_ID);//SDK 1.3.5 以上版本支持,通知栏的Notification ID,可以用于清除Notification bundle_onlogin = jPushBundle.getBoolean(EXTRA_ONLOGIN);
} if(!jPushExtraJson.equals("")){
try {
JSONObject extraJsonObj = new JSONObject(jPushExtraJson);
if(extraJsonObj.has("from")){
extraJsonObj = new JSONObject(extraJsonObj.getString("from"));
}
if(!extraJsonObj.getString("exTraTitle").equals("")){
//获取标题
bundle_title = extraJsonObj.getString("exTraTitle");
}
if(!extraJsonObj.getString("url").equals("")){
//获取网页地址
bundle_url = extraJsonObj.getString("url");
}
} catch (Resources.NotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} if(! bundle_onlogin){//如果是从登录界面打开的话,那么不用验证了
initCheckLoginState();//验证是否需要重新登录
}else{
loadWebUrl();//打开网页
} } private void initToolBar() {
mToolbar = findViewById(R.id.toolbar_base);
mToolbar.setTitle("");//这样设置的话,自带的标题就不会显示
//设置自定义的标题(居中)
TextView toolBarTitle = mToolbar.findViewById(R.id.toolbarTitle);
toolBarTitle.setText(bundle_title);
setSupportActionBar(mToolbar);//由于toolbar只是一个普通控件,我们将ToolBar设置为ActionBar
//设置导航图标要在setSupportActionBar方法之后
mToolbar.setNavigationIcon(R.drawable.nav_back);//设置为空的话,就会不显示左侧的图标
//对NavigationIcon添加点击
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//返回到首页界面(重新登录的情况下)或者直接关闭自己(不需要重新登录的情况下)
backHomeOrFinish();
}
});
} /**
* 点击返回键
* event.getRepeatCount() == 0:点后退键的时候,为了防止点得过快,触发两次后退事件,故做此设置。
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
//返回到首页界面(如果是从登录界面打开的)或者关闭自己(从通知打开的)
backHomeOrFinish();
}
return super.onKeyDown(keyCode, event);
} //返回功能
private void backHomeOrFinish() {
if (bundle_onlogin) {
ActivityJump.NormalJumpAndFinish(JpushActivity.this, HomeActivity.class);
} else {
ActivityJump.Back(this);
}
} /**
* 网络请求检查登录状态,主要判断是否在线
*/
private void initCheckLoginState() {
if(result.indexOf("alert(") != -1){
//登陆身份失效,请重新登陆
ActivityJump.BundleJumpAndFinish(JpushActivity.this, LoginActivity.class,jPushBundle);
}
else{
loadWebUrl();//加载网页
}
} /**
* 加载URL地址
*/
private void loadWebUrl() {
syncCookie(JpushActivity.this, ServerApi.SERVER_URL); if (!bundle_url.equals("")) {
myWebView.loadWebUrl(ServerApi.SERVER_URL + bundle_url);
} else {
myWebView.loadUrl("about:blank");//加载一个空白页
}
} /**
* Sync Cookie
*/
public static void syncCookie(Context context, String url){
//参考本博客的《okhttputils【 Android 一个改善的okHttp封装库】使用(二)》
}
}

(5)初始化SDK

在MyApplication中执行

package com.why.project.jpushdemo;

import android.app.Application;

import cn.jpush.android.api.JPushInterface;

/**
* Created by HaiyuKing
* Used
*/
public class MyApplication extends Application { @Override
public void onCreate() {
super.onCreate(); initJpush();//极光推送SDK初始化
} //极光推送SDK
private void initJpush() {
JPushInterface.setDebugMode(true);// 设置开启日志,发布时请关闭日志
JPushInterface.init(this);// 初始化 JPush
}

三、使用方法【仅供参考】

package com.why.project.jpushdemo;

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils; import com.why.project.jpushdemo.jpush.ExampleUtil;
import com.why.project.jpushdemo.jpush.TagAliasOperatorHelper; import cn.jpush.android.api.JPushInterface; public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName(); private Context mContext; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); mContext = this; /*=======================================极光推送SDK相关=============================================*/
//请求服务器删除alias,然后再重新注册alias,这样实现一个别名只能绑定一台设备
updateJpushDeviceId();
} /*=======================================极光推送SDK相关=============================================*/ /**
* 更新设备id接口
*/
private void updateJpushDeviceId() {
String regId = JPushInterface.getRegistrationID(mContext);//可能不会那么快就能获得resId值,所以如果极光推送没有初始化好,那么这里获取到的是null
requestDeviceId(regId);//判断是请求接口还是弹出对话框
} //请求接口存储设备id或者token的方法
private void requestDeviceId(String regId) { //首要条件是设备id值或者token值不为空,否则下面的判断没有意义了
//如果没有设置过别名,或者则需要设置别名
//如果服务器上的deviceID值是空值,表明当前用户还没有绑定任何设备,则直接请求接口,不需要弹出对话框;
//如果服务器上的deviceID值不为空,并且客户端获取的设备id值和服务器上的deviceID值相同,则不需要弹出对话框,直接请求接口(这个是卸载重新安装的情况)
//如果服务器上的deviceid值不为空,并且客户端获取的设备id值和服务器上的deviceID值不同,则需要弹出对话框(这个是换设备的情况)
if (!TextUtils.isEmpty(regId)) {
//如果已经设置过别名(存储过了设备id值)了,但是当前的别名(设备id值)和服务器上的不一致,则需要重新设置别名(存储设备id值)(这个是其他设备上登录的情况)
} //设置极光推送别名
setAlias(PreferencesUtils.getString(mContext,Globals.USERNAME_KEY));
} // 这是来自 JPush Example 的设置别名的 Activity 里的代码。一般 App 的设置的调用入口,在任何方便的地方调用都可以。
private void setAlias(String alias) {
if (TextUtils.isEmpty(alias)) {
ToastUtil.showShortToast(getResources().getString(R.string.error_alias_empty));//alias别名不能为空
return;
}
if (!ExampleUtil.isValidTagAndAlias(alias)) {
ToastUtil.showShortToast(getResources().getString(R.string.error_tag_gs_empty));//格式不对
return;
} // 调用 JPush 接口来设置别名。
TagAliasOperatorHelper.TagAliasBean tagAliasBean = new TagAliasOperatorHelper.TagAliasBean();
tagAliasBean.action = TagAliasOperatorHelper.ACTION_SET;
tagAliasBean.alias = alias;
tagAliasBean.isAliasAction = true;
TagAliasOperatorHelper.getInstance().handleAction(MyApplication.getAppContext(), TagAliasOperatorHelper.sequence++, tagAliasBean);
//已经设置了别名
String aliasKey = Globals.UPDATEJPUSHRESID_KEY;
PreferencesUtils.putBoolean(mContext,aliasKey,true);
}
}

四、发送消息

混淆配置

#====极光推送SDK====
-dontoptimize
-dontpreverify -dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }
-keep class * extends cn.jpush.android.helpers.JPushMessageReceiver { *; } -dontwarn cn.jiguang.**
-keep class cn.jiguang.** { *; }

参考资料

暂时空缺

项目demo下载地址

链接:https://pan.baidu.com/s/1eHSnRrw07LC9mq1I7IP2gw 提取码:wn99

JPushDemo【极光推送集成,基于v3.1.8版本】的更多相关文章

  1. Android 极光推送集成

    集成Jpush 1.用Android Studio创建一个Demo 2.创建激光推送开发者账号,要创建极光推送开发者帐号,请访问极光推送官方网站https://www.jiguang.cn/push ...

  2. 极光推送集成——iOS10 接受消息问题及解决

    iOS10升级后极光推送发生了很大的变化,要求Xcode更新到8.0及以上版本才可以实现iOS10接受消息的方法 常见错误 这个问题困扰了我一天,辛亏好友盼神帮我解决,在此再次感谢盼神.一下是解决办法 ...

  3. iOS极光推送集成步骤

    1.下载SDK,导入Xcode 2.在苹果开发者中心建立AppId与bundleID进行关联,注意勾选推送功能 3.在苹果开发者中心建立推送证书 4.在极光后台建立应用且上传推送证书 5.建立描述文件 ...

  4. Android集成极光推送

    要说学习极光推送,个人感觉官方文档就非常好啦,但是没法,人太懒啦,为了下次能够快速的将极光推送集成到项目中,故结合之前开发的项目和官方文档记录下简单的Android集成极光推送,在这之前,先上一张简单 ...

  5. iOS 集成极光推送

    最近极光推送更新到V3版本之后,推送又不成功!配合服务器联调了半天,发现是服务器环境配置有问题. 想着就把极光推送的步骤给记录下来. 一.配置push证书 这个可以到极光文档里写,很详细 二.导入必要 ...

  6. Xamarin.Forms学习系列之Android集成极光推送

    一般App都会有消息推送的功能,如果是原生安卓或者IOS集成消息推送很容易,各大推送平台都有相关的Sample,但是关于Xamarin.Forms的消息推送集成的资料非常少,下面就说下Xamarin. ...

  7. iOS推送(利用极光推送)

    本文主要是基于极光推送的SDK封装的一个快速集成极光推送的类的封装(不喜勿喷) (1)首先说一下推送的一些原理: Push的原理: Push 的工作机制可以简单的概括为下图 图中,Provider是指 ...

  8. android推送,极光推送

    android中简单易用的消息推送方式之中的一个 -------> 极光推送 首先来介绍一下极光推送. 极光推送:英文简称 JPush,是一个面向普通开发人员免费.开放的第三方消息推送服务,我们 ...

  9. 极光推送Jpush(v3)服务端PHP版本集成(V3版本只调用推送API)

    因为版本升级,极光推送的API也有了V3,功能也更丰富了,但是对于我们有的用户来说,我们还是只需要调用推送的API就够了. 下载了一份PHP服务端的SDK(下载地址:http://docs.jpush ...

随机推荐

  1. CSS基础知识01

    一.CSS基础知识介绍 1.css是cascading style sheet层叠式样式表的简写 2.css小用法 加粗:font-weight:bold;             正常用:norma ...

  2. CentOS的启动流程

    因6和7俩个系列的启动流程有区别,所以我把他们分开来写 linux可看作是内核和根文件系统组成我们把内核单独拿出来总结一下 CentOS6系列启动流程 首先总结一下总体的流程,接下来展开来叙述:POS ...

  3. win10汇编环境的搭建

    第一步:下载DOSBox0.74-win32-installer 可以去官网:http://www.dosbox.com/ 或者链接:https://pan.baidu.com/s/1UA77qTLO ...

  4. mybatis查询异常-Error querying database. Cause: java.lang.ClassCastException: org.apache.ibatis.executor.ExecutionPlaceholder cannot be cast to java.util.List

    背景,mybatis查询的时候直接取的sqlsession,没有包装成SqlSessionTemplate,没有走spring提供的代理. 然后我写的获取sqlsession的代码没有考虑到并发的情况 ...

  5. Redis之实战篇(与Mybatis整合)

    摘要: 现在市面流行的java框架,一个是ssh(spring.struts2.hibernate),另一个是ssm(spring.springmvc.mybatis),由于之前已经有整合过ssm框架 ...

  6. Ubuntu安装和卸载.bundle格式的VMware

    本文由荒原之梦原创,原文链接:http://zhaokaifeng.com/?p=628 前言: 本文中用于演示的.bundle文件是VMware-Workstation-Full-14.1.1-75 ...

  7. Day3 《机器学习》第三章学习笔记

    这一章也是本书基本理论的一章,我对这章后面有些公式看的比较模糊,这一会章涉及线性代数和概率论基础知识,讲了几种经典的线性模型,回归,分类(二分类和多分类)任务. 3.1 基本形式 给定由d个属性描述的 ...

  8. MIT KIT OpenID Connect Demo Client

    Hello world! You are NOT currently logged in. This example application is configured with several pa ...

  9. Scrapy 1.4 文档 02 安装指南

    安装 Scrapy Scrapy 运行在 Python 2.7 和 Python 3.3 或更高版本上. 如果您使用的是 Anaconda 或 Miniconda,则可以从 conda-forge 通 ...

  10. java基础之抽象类与接口的形式参数和返回值

    抽象类与接口形式参数和返回值问题 1.形参问题 /* 1.形式参数: 基本类型(太简单,不是我今天要讲解的) 引用类型 (1)类名:(匿名对象的时候其实我们已经讲过了) 需要的是该类的对象 (2)抽象 ...