1、导入zxing代码和包

2、下面的类是解析二维码的主要类。

package com.gaint.nebula.interaction.ui.zxing;

import java.io.IOException;
import java.util.Vector; import android.app.Activity;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast; import com.gaint.nebula.interaction.R;
import com.gaint.nebula.interaction.ui.BaseActivity;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;
import com.mining.app.zxing.camera.CameraManager;
import com.mining.app.zxing.decoding.CaptureActivityHandler;
import com.mining.app.zxing.decoding.InactivityTimer;
import com.mining.app.zxing.view.ViewfinderView;
/**
* Initial the camera
* @author Ryan.Tang
*/
public class MipcaActivityCapture extends BaseActivity implements Callback { private CaptureActivityHandler handler;
private ViewfinderView viewfinderView;
private boolean hasSurface;
private Vector<BarcodeFormat> decodeFormats;
private String characterSet;
private InactivityTimer inactivityTimer;
private MediaPlayer mediaPlayer;
private boolean playBeep;
private static final float BEEP_VOLUME = 0.10f;
private boolean vibrate; /** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_capture);
//ViewUtil.addTopView(getApplicationContext(), this, R.string.scan_card);
CameraManager.init(getApplication());
viewfinderView = (ViewfinderView) findViewById(R.id.viewfinder_view); Button mButtonBack = (Button) findViewById(R.id.button_back);
mButtonBack.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
MipcaActivityCapture.this.finish(); }
});
hasSurface = false;
inactivityTimer = new InactivityTimer(this);
} @Override
protected void onResume() {
super.onResume();
SurfaceView surfaceView = (SurfaceView) findViewById(R.id.preview_view);
SurfaceHolder surfaceHolder = surfaceView.getHolder();
if (hasSurface) {
initCamera(surfaceHolder);
} else {
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
decodeFormats = null;
characterSet = null; playBeep = true;
AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE);
if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
playBeep = false;
}
initBeepSound();
vibrate = true; } @Override
protected void onPause() {
super.onPause();
if (handler != null) {
handler.quitSynchronously();
handler = null;
}
CameraManager.get().closeDriver();
} @Override
protected void onDestroy() {
inactivityTimer.shutdown();
super.onDestroy();
} /**
* ����ɨ����
* @param result
* @param barcode
*/
public void handleDecode(Result result, Bitmap barcode) {
inactivityTimer.onActivity();
playBeepSoundAndVibrate();
String resultString = result.getText();
if (resultString.equals("")) {
Toast.makeText(MipcaActivityCapture.this, "Scan failed!", Toast.LENGTH_SHORT).show();
}else {
Intent resultIntent = new Intent();
Bundle bundle = new Bundle();
bundle.putString("result", resultString);
bundle.putParcelable("bitmap", barcode);
resultIntent.putExtras(bundle);
this.setResult(RESULT_OK, resultIntent);
}
MipcaActivityCapture.this.finish();
} private void initCamera(SurfaceHolder surfaceHolder) {
try {
CameraManager.get().openDriver(surfaceHolder);
} catch (IOException ioe) {
return;
} catch (RuntimeException e) {
return;
}
if (handler == null) {
handler = new CaptureActivityHandler(this, decodeFormats,
characterSet);
}
} @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) { } @Override
public void surfaceCreated(SurfaceHolder holder) {
if (!hasSurface) {
hasSurface = true;
initCamera(holder);
} } @Override
public void surfaceDestroyed(SurfaceHolder holder) {
hasSurface = false; } public ViewfinderView getViewfinderView() {
return viewfinderView;
} public Handler getHandler() {
return handler;
} public void drawViewfinder() {
viewfinderView.drawViewfinder(); } private void initBeepSound() {
if (playBeep && mediaPlayer == null) {
// The volume on STREAM_SYSTEM is not adjustable, and users found it
// too loud,
// so we now play on the music stream.
setVolumeControlStream(AudioManager.STREAM_MUSIC);
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnCompletionListener(beepListener); AssetFileDescriptor file = getResources().openRawResourceFd(
R.raw.beep);
try {
mediaPlayer.setDataSource(file.getFileDescriptor(),
file.getStartOffset(), file.getLength());
file.close();
mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
mediaPlayer.prepare();
} catch (IOException e) {
mediaPlayer = null;
}
}
} private static final long VIBRATE_DURATION = 200L; private void playBeepSoundAndVibrate() {
if (playBeep && mediaPlayer != null) {
mediaPlayer.start();
}
if (vibrate) {
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(VIBRATE_DURATION);
}
} /**
* When the beep has finished playing, rewind to queue up another one.
*/
private final OnCompletionListener beepListener = new OnCompletionListener() {
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.seekTo(0);
}
}; }

3、调用此类:

Intent intent = new Intent();
intent.setClass(BaseActivity.this, MipcaActivityCapture.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivityForResult(intent, SCANNIN_GREQUEST_CODE);

4、回传信息,可以看到二维码图片和内容。

 @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SCANNIN_GREQUEST_CODE) {
if (data==null) {
return;
}
Bitmap mBitmap = data.getParcelableExtra("bitmap");
final String result = data.getStringExtra("result");
Logger.getLogger().i(result+" -- "+mBitmap);
View view = LayoutInflater.from(this).inflate(R.layout.scan, null);
ImageView icon = (ImageView) view.findViewById(R.id.iv_scan_icon);
TextView textView = (TextView) view.findViewById(R.id.tv_scan_title);
icon.setImageBitmap(mBitmap);
textView.setText(result);
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
dialog.setTitle("扫描结果");
dialog.setView(view);
dialog.setMessage(data.getDataString());
dialog.setNegativeButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 用默认浏览器打开扫描得到的地址
Intent intent = new Intent();
intent.setAction("android.intent.action.VIEW");
Uri content_url = Uri.parse(result);
intent.setData(content_url);
startActivity(intent);
dialog.dismiss();
}
});
dialog.setPositiveButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
dialog.create().show();
}
super.onActivityResult(requestCode, resultCode, data);
}

5、生成二维码

/**
* @类功能说明: 生成二维码图片示例
*/
public class CreateQRImageTest {
private ImageView sweepIV;
private int QR_WIDTH = 200, QR_HEIGHT = 200; /**
* @方法功能说明: 生成二维码图片,实际使用时要初始化sweepIV,不然会报空指针错误
* @参数: @param url 要转换的地址或字符串,可以是中文
* @return void
* @throws
*/ // 要转换的地址或字符串,可以是中文
public void createQRImage(String url) {
try {
// 判断URL合法性
if (url == null || "".equals(url) || url.length() < 1) {
return;
}
Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
// 图像数据转换,使用了矩阵转换
BitMatrix bitMatrix = new QRCodeWriter().encode(url,
BarcodeFormat.QR_CODE, QR_WIDTH, QR_HEIGHT, hints);
int[] pixels = new int[QR_WIDTH * QR_HEIGHT];
// 下面这里按照二维码的算法,逐个生成二维码的图片,
// 两个for循环是图片横列扫描的结果
for (int y = 0; y < QR_HEIGHT; y++) {
for (int x = 0; x < QR_WIDTH; x++) {
if (bitMatrix.get(x, y)) {
pixels[y * QR_WIDTH + x] = 0xff000000;
} else {
pixels[y * QR_WIDTH + x] = 0xffffffff;
}
}
}
// 生成二维码图片的格式,使用ARGB_8888
Bitmap bitmap = Bitmap.createBitmap(QR_WIDTH, QR_HEIGHT,
Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, QR_WIDTH, 0, 0, QR_WIDTH, QR_HEIGHT);
// 显示到一个ImageView上面
sweepIV.setImageBitmap(bitmap);
} catch (WriterException e) {
e.printStackTrace();
}
}
}

6、zxing包

http://www.cnblogs.com/weixing/archive/2013/08/28/3287120.html

ZXing开源项目Google Code地址:https://code.google.com/p/zxing/

ZXingDemo下载:ZXingDemo2013-8-25.rar

二、修改二维码代码

1、是扫描二维码的文字居中。

找到类ViewfinderView,其中widthPixels是屏幕的宽度。

paint.setColor(Color.WHITE);
paint.setTextSize(TEXT_SIZE * density);
paint.setAlpha(0x40);
paint.setTypeface(Typeface.create("System", Typeface.BOLD));
//获取文字宽度,让其居中显示
float wtext = paint.measureText(getResources().getString(R.string.scan_text));
canvas.drawText(getResources().getString(R.string.scan_text), (widthPixels-wtext)/2, (float) (frame.bottom + (float)TEXT_PADDING_TOP *density), paint);

2、修改二维码窗口大小。默认情况下,窗口的大小是屏幕的四分之三,有最小值和最大值。

找到CameraManager类的getFramingRect方法,就可以看到。

public Rect getFramingRect() {
Point screenResolution = configManager.getScreenResolution();
if (framingRect == null) {
if (camera == null) {
return null;
}
int width = screenResolution.x * 3 / 4;
if (width < MIN_FRAME_WIDTH) {
width = MIN_FRAME_WIDTH;
} else if (width > MAX_FRAME_WIDTH) {
width = MAX_FRAME_WIDTH;
}
int height = screenResolution.y * 3 / 4;
if (height < MIN_FRAME_HEIGHT) {
height = MIN_FRAME_HEIGHT;
} else if (height > MAX_FRAME_HEIGHT) {
height = MAX_FRAME_HEIGHT;
}
int leftOffset = (screenResolution.x - width) / 2;
int topOffset = (screenResolution.y - height) / 2;
framingRect = new Rect(leftOffset, topOffset, leftOffset + width, topOffset + height);
Log.d(TAG, "Calculated framing rect: " + framingRect);
}
return framingRect;
}

最近没事做了下二维码扫描,用的是ZXing的开源代码,官方源码地址:http://code.google.com/p/zxing/downloads/list;

我是在ZXing2.2基础上做的,因此只下载了ZXing-2.2.zip;

此外还需要ZXing的核心Jar包,下载地址:http://repo1.maven.org/maven2/com/google/zxing/core/2.2/,只需下载core-2.2.jar就行;

将下载的ZXing-2.2.zip解压出来,我们只需要用到android目录中的示例项目,如图:

 

将android项目导入eclipse,同时别忘了将core-2.2.jar导入libs,此时该示例项目应该可以运行了,不过该项目很多功能我们不需要,并且其扫描界面为横向的,因此需对其修改。



接下去我们来将该示例项目简化:

第一步:拷贝必要的包和类

新建自己的项目并导入core-2.2.jar,将示例项目中的必要代码全部拷贝到自己的项目中,至于示例项目中各个包和类的功能此处就不做解释的,有兴趣可以自己去研究下;

我自己对包结构做了一点改动,导入完成后会有很多红叉,大都和包的访问权限有关,因为示例代码中很多类是final型的,我们将其public就行;

此外还需要res下一些关联的文件(values下的color.xml、ids.xml、strings.xml,raw下的beep.ogg)。

初步调整后包结构如下:

 



第二步:PreferencesActivity和CaptureActivity修改

示例项目用到了大量的配置,因此很多地方都用到了PreferencesActivity这个类,其实留着它也无所谓,但别忘了将示例项目中res下一些关联文件拷贝过来(preferences.xml、arrays.xml);

不过PreferencesActivity完全是多余的,看着也碍眼,因此我将其去掉,需要将用到PreferencesActivity的类都修改,就是剩余那些报红叉的类,我们需要将一些配置固定化,多余的设置判断去掉,此处我就不贴代码了;

同样CaptureActivity中也有很多方法是我们不需要的,大都是关于解码成功后的处理,如果要保留的话则需要额外拷贝很多类,因此将其去掉,此处也不贴代码了,附件源码中都有。



第三部:修改为竖屏

经过上面两步,我们自己的项目应该可以运行了(别忘了加权限),当然此时是横屏的,因此我们需要修改几处地方将其修改为竖屏:

1.CameraConfigurationManager类的initFromCameraParameters()方法中将以下代码注释掉:

代码片段,双击复制
01
02
03
04
05
06
if(width
< height) {
   Log.i(TAG,"Display
reports portrait orientation; assuming this is incorrect"
);
   inttemp
= width;
   width
= height;
     height
= temp;
   }

2.CameraConfigurationManager类的setDesiredCameraParameters()方法中在camera.setParameters(parameters)之前加入以下代码:

代码片段,双击复制
01
camera.setDisplayOrientation(90);

3.CameraManager类的getFramingRectInPreview()方法中将以下代码替换:

代码片段,双击复制
01
02
03
04
rect.left
= rect.left * cameraResolution.x / screenResolution.x;
rect.right
= rect.right * cameraResolution.x / screenResolution.x;
rect.top
= rect.top * cameraResolution.y / screenResolution.y;
rect.bottom
= rect.bottom * cameraResolution.y / screenResolution.y;

替换为

代码片段,双击复制
01
02
03
04
rect.left
= rect.left * cameraResolution.y / screenResolution.x;
rect.right
= rect.right * cameraResolution.y / screenResolution.x;
rect.top
= rect.top * cameraResolution.x / screenResolution.y;
rect.bottom
= rect.bottom * cameraResolution.x / screenResolution.y;

4.DecodeHandler类的decode方法中在activity.getCameraManager().buildLuminanceSource()之前添加以下代码:

代码片段,双击复制
01
02
03
04
05
06
07
08
09
byte[]
rotatedData =
newbyte[data.length];
for(inty
=
0;
y < height; y++) {
   for(intx
=
0;
x < width; x++)
    
   
rotatedData[x
* height + height - y -
1]
= data[x + y * width];
    
   
}
 inttmp
= width;
 width
= height;
 height
= tmp;
 data
= rotatedData;

5.很关键的一步,解决竖屏后图像拉伸问题。CameraConfigurationManager类的initFromCameraParameters()方法中:

在Log.i(TAG, "Screen resolution: " + screenResolution);之后添加以下代码:

代码片段,双击复制
01
02
03
04
05
06
07
Point
screenResolutionForCamera =
newPoint();
screenResolutionForCamera.x
= screenResolution.x;
screenResolutionForCamera.y
= screenResolution.y;
if(screenResolution.x
< screenResolution.y) {
   screenResolutionForCamera.x
= screenResolution.y;
   screenResolutionForCamera.y
= screenResolution.x;
   }

同时修改下一句为cameraResolution = findBestPreviewSizeValue(parameters,screenResolutionForCamera);



此外manifest中别忘了设置android:screenOrientation="portrait",至此竖屏修改完毕。



第四步:扫描框位置和大小修改

此时的扫描框是竖直拉伸的矩形,很难看,我们可以将其修改为正方形或扁平型的。

CameraManager类的getFramingRect()方法中替换以下代码:

代码片段,双击复制
01
02
intwidth
= findDesiredDimensionInRange(screenResolution.x, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH);
intheight
= findDesiredDimensionInRange(screenResolution.y,MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT);

替换为

代码片段,双击复制
01
02
03
DisplayMetrics
metrics = context.getResources().getDisplayMetrics();
intwidth
= (
int)
(metrics.widthPixels *
0.6);
intheight
= (
int)
(width *
0.9);

此处我们根据屏幕分辨率来定扫描框大小更灵活一点,同时将偏移量topOffset修改为(screenResolution.y - height)/4



第五步:扫描框四个角和扫描线条修改

示例代码中的线条是居中且不动的,我们可以将其修改为上下移动的扫描线,且可以改变线条的样式。

在自定义扫描布局ViewfinderView类中的onDraw()方法中绘制四个角,关键代码如下:

代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
//
画出四个角
paint.setColor(getResources().getColor(R.color.green));
//
左上角
canvas.drawRect(frame.left,
frame.top, frame.left +
15,frame.top
+
5,
paint);
canvas.drawRect(frame.left,
frame.top, frame.left +
5,frame.top
+
15,
paint);
//
右上角
canvas.drawRect(frame.right
-
15,
frame.top, frame.right,frame.top +
5,
paint);
canvas.drawRect(frame.right
-
5,
frame.top, frame.right,frame.top +
15,
paint);
//
左下角
canvas.drawRect(frame.left,
frame.bottom -
5,
frame.left +
15,frame.bottom,
paint);
canvas.drawRect(frame.left,
frame.bottom -
15,
frame.left +
5,frame.bottom,
paint);
//
右下角
canvas.drawRect(frame.right
-
15,
frame.bottom -
5,
frame.right,frame.bottom, paint);
canvas.drawRect(frame.right
-
5,
frame.bottom -
15,
frame.right,frame.bottom, paint);

此外将扫描线条修改为上下扫描的线,关键代码如下:

代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
if((i
+=
5)
< frame.bottom - frame.top) {
    
   
/*
以下为用渐变线条作为扫描线 */
    
   
//
渐变图为矩形
    
   
//
mDrawable.setShape(GradientDrawable.RECTANGLE);
    
   
//
渐变图为线型
    
   
//
mDrawable.setGradientType(GradientDrawable.LINEAR_GRADIENT);
    
   
//
线型矩形的四个圆角半径
    
   
//
// mDrawable
    
   
//
// .setCornerRadii(new float[] { 8, 8, 8, 8, 8, 8, 8, 8 });
    
   
//
位置边界
    
   
//
mRect.set(frame.left + 10, frame.top + i, frame.right - 10,
    
   
//
frame.top + 1 + i);
    
   
//
设置渐变图填充边界
    
   
//
mDrawable.setBounds(mRect);
    
   
//
画出渐变线条
    
   
//
mDrawable.draw(canvas);
 
    
   
/*
以下为图片作为扫描线 */
    
   
mRect.set(frame.left
-
6,
frame.top + i -
6,
frame.right +
6,frame.top
+
6+
i);
    
   
lineDrawable.setBounds(mRect);
    
   
lineDrawable.draw(canvas);
 
    
   
//
刷新
    
   
invalidate();
    
 
}else{
    
       
i
=
0;
    
 
}

此处采用了两种线条样式,一种是渐变线条,还有一种是类似微信的图片扫描线。

详细代码请看附件源码。



运行截图如下:

 此为渐变线条 
            此为图片线条,用的是微信的图片,不过微信扫描用的应该是动画很平滑,此处用的是多次绘制



另外,扫描成功后的手机震动和提示音在BeepManager中修改,里面我额外放了两种提示音文件





示例源码工程,core包和我修改简化后的源码放都附件中



 ZXing示例源码和核心core包.rar (1010.76
KB, 下载次数: 36) 

 简化后源码.rar (2.38
MB, 下载次数: 293)

http://blog.csdn.net/xinchen200/article/details/18036695

ZXing 二维码应用的更多相关文章

  1. Atitit zxing二维码qr码识别解析

    Atitit zxing二维码qr码识别解析 1.1. qr码识别解析 by zxing1 1.2. 解码lib:qrcode.jar  2 1.3. atitit.二维码生成总结java zxing ...

  2. Android项目实战(二十八):Zxing二维码实现及优化

    前言: 多年之前接触过zxing实现二维码,没想到今日项目中再此使用竟然使用的还是zxing,百度之,竟是如此牛的玩意. 当然,项目中我们也许只会用到二维码的扫描和生成两个功能,所以不必下载完整的ja ...

  3. 程序猿媛 九:Adroid zxing 二维码3.1集成(源码无删减)

    Adroid zxing 二维码3.1集成 声明:博文为原创,文章内容为,效果展示,思路阐述,及代码片段. 转载请保留原文出处“http://my.oschina.net/gluoyer/blog”, ...

  4. 谷歌zxing 二维码生成工具

    一.加入maven依赖 <!-- 谷歌zxing 二维码 --> <dependency> <groupId>com.google.zxing</groupI ...

  5. (转载)Android项目实战(二十八):Zxing二维码实现及优化

    Android项目实战(二十八):Zxing二维码实现及优化   前言: 多年之前接触过zxing实现二维码,没想到今日项目中再此使用竟然使用的还是zxing,百度之,竟是如此牛的玩意. 当然,项目中 ...

  6. Android项目实战(四十四):Zxing二维码切换横屏扫描

    原文:Android项目实战(四十四):Zxing二维码切换横屏扫描 Demo链接 默认是竖屏扫描,但是当我们在清单文件中配置横屏显示的时候: <activity android:name=&q ...

  7. ZXing二维码生成在Unity3D中出错,数组超出界限的解决办法

    错误截图: IndexOutOfRangeException: Array index is out of range.ZXing.Color32Renderer.Render (ZXing.Comm ...

  8. Android—ZXing二维码扫描遇到的问题

    最近工作中需要开发带有二维码扫描功能的软件(基于开源项目ZXing),遇到的问题记录一下,也希望给大家带来帮助. 1.首先因为扫描要开摄像机所以加权限是一定的,不然后面什么都不能进行 <uses ...

  9. Google Zxing 二维码生成与解析

    生成二维码的开源项目可谓是琳琅满目,SwetakeQRCode.BarCode4j.Zxing...... 前端有JQuery-qrcode,同样能实现生成二维码. 选择Zxing的原因可能是对 Go ...

  10. ZXing二维码的生成和解析

    Zxing是Google提供的关于条码(一维码.二维码)的解析工具,提供了二维码的生成与解析的方法, 现在我简单介绍一下使用Java利用Zxing生成与解析二维码 注意: 二维码的生成需要借助辅助类( ...

随机推荐

  1. RequireJS 是一个JavaScript模块加载器

    RequireJS 是一个JavaScript模块加载器.它非常适合在浏览器中使用, 它非常适合在浏览器中使用,但它也可以用在其他脚本环境, 就像 Rhino and Node. 使用RequireJ ...

  2. POJ P3667 Hotel——solution

    Description The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and e ...

  3. 02.CSS选择器-->:focus

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. localStorage跟cookie的使用

    最近做了记住密码功能,用localStorage跟cookie都尝试用了一下,感觉都挺好哈,很方便,特此记录 html代码: <input type="text" id=&q ...

  5. Spring的大框架

    初识Spring: Spring作者:Rod Johnson Spring框架由20个模块组成,这些模块分成六个部分,分别是Core Container,Data Access/Integration ...

  6. Mybatis学习第三天——输入输出映射以及动态SQL

    注意:以下传入数据与输出数据类型部分使用别名的方式,别名在SqlMapConfig.xml核心文件中配置 1.输入映射 1.1 传递简单数据类型 1.2 传递pojo中的类类型 1.3 传递Query ...

  7. spring+quarts常见问题

    javax/transaction/UserTransactionCaused by: java.lang.NoClassDefFoundError: javax/transaction/UserTr ...

  8. laravel model relationship

    laravel支持多种模型之间的relation,对应着模型间的one2one, one2many,many2many,hasManyThrough,Polymorphic, many2many po ...

  9. SQL Server Management Studio 2012 键盘快捷键(转)

    无论是对于DBA还是Developer,键盘快捷键都是很常用的,动动键盘可比鼠标快多了,不过SQL Server 2012对SSMS(SQL Server Management Studio)中的快捷 ...

  10. Python实例---三级菜单的实现[high]

    # version: python3.2.5 # author: 'FTL1012' # time: 2017/12/7 09:16 menu = { '陕西': { '西安': { '未名区': [ ...