首页 文章 精选 留言 我的

精选列表

搜索[人设自定义],共10000篇文章
优秀的个人博客,低调大师

巧用fastjson自定义序列化类实现字段的转换

项目中突然需要增加另一个字段的查找,而这个查找需要查另一张表的记录。 但现在产品很多地方都要增加该字段,如何最快的实现该功能呢。 办法如下: 通过fastjson序列化时,增加该字段的序列化类,该序列化类通过CODE查找名称,并序列化到前端。 VO的功能修改 @Data public class SysDictItemSelectVo implements Serializable{ private static final long serialVersionUID = 1L; @JSONField(serializeUsing=ToSystemNameSerializer.class) private String systemName; public String getSystemName(){ return this.getCode(); } } 序列化的类的属性 import com.alibaba.fastjson.serializer.JSONSerializer; import com.alibaba.fastjson.serializer.ObjectSerializer; import com.alibaba.fastjson.serializer.SerializeWriter; import java.io.IOException; import java.lang.reflect.Type; public class ToSystemNameSerializer implements ObjectSerializer { public static final ToSystemNameSerializer instance = new ToSystemNameSerializer(); @Override public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException { SerializeWriter out = serializer.out; if (object == null) { out.writeNull(); return; } //原来的值code String strVal = object.toString(); System.out.println(strVal); //通过code查找相关名称,测试先写死值 String name="std"; out.writeString(name); } } 经测试,序列化正常,其他地方只需要在VO增加该注解即可.

优秀的个人博客,低调大师

eBPF监控工具bcc系列三自定义工具trace

上篇中是通用的直接可用工具。 trace工具可以指定跟踪函数并显示,可控制其输出格式来显示函数参数和返回值。 例如跟踪文件拥有者的属性更改,也就是跟踪三个文件系统调用chown,fchown,lchown。使用如下: trace.py 'p::SyS_chown "file = %s, to_uid = %d, to_gid = %d, from_uid = %d", arg1, arg2, arg3, $uid' 'p::SyS_fchown "fd = %d, to_uid = %d, to_gid = %d, from_uid = %d", arg1, arg2, arg3, $uid' 'p::SyS_lchown "file = %s, to_uid = %d, to_gid = %d, from_uid = %d", arg1, arg2, arg3, $uid' 例如跟踪非主动上下文切换。 trace.py -p 1134138 't:sched:sched_switch (args->prev_state == TASK_STATE_MAX || args->prev_state == 0)' 跟踪系统中所有exec调用 # trace 'sys_execve "%s", arg1' 其中sys_execve是内核函数,%s表示打印字符串,这个被复制为arg1就是程序的入参。 例如跟踪系统读操作read,所读大小大于20000(这个参数可以通过man read查看是在第三个位置上),所以跟踪函数如下: trace 'sys_read (arg3 > 20000) "read %d bytes", arg3' 还可以跟踪用户层函数,例如跟踪bash上readline脚本,并输出返回值,可以如下书写 trace 'r:bash:readline "%s", retval' 其中r表示retprobe是返回探针。 跟踪读写失败的命令 trace 'r:c:read ((int)retval < 0) "read failed: %d", retval' 'r:c:write ((int)retval < 0) "write failed: %d", retval' -T 1. 内核tracepoints 还可以跟踪内核的tracepoints,例如跟踪block:block_rq_complete的tracepoint,并打印多少扇区被传输。 trace 't:block:block_rq_complete "sectors=%d", args->nr_sector' -T 如果不清楚跟踪点的数据结构格式,可以使用tplist工具来获得,例如 tplist -v block:block_rq_complete 得到数据结构后就可以用做参数来获取nr_sector了。 2. 第三方库 越来越多高级库支持探针,就像内核tracepoint一样可以用来被跟踪。 例如跟踪pthread_create函数 trace 'u:pthread:pthread_create "%U", arg3' -T -C 其中%U表示将arg3解析成用户层符号。同样,内核的是%K. 现在Ruby,Node,OpenJDK都支持。 跟踪ruby示例: trace 'u:ruby:method__entry "%s.%s", arg1, arg2' -p $(pidof irb) -T 跟踪共享库函数如下: trace.py 'r:/usr/lib64/libtinfo.so:curses_version "Version=%s", retval' 3. 高级过滤 跟踪open,同时指出其打开的文件名字为test.txt trace 'p:c:open (STRCMP("test.txt", arg1)) "opening %s", arg1' -T trace 'p::SyS_nanosleep(struct timespec *ts) "sleep for %lld ns", ts->tv_nsec' 跟踪指定进程的指定函数,使用-p参数,如下: trace -p 2740 'do_sys_open "%s", arg2' -T

优秀的个人博客,低调大师

Android 自定义注解之运行时注解(RetentionPolicy.RUNTIME)

RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在 获取注解的常用方法: /** * 获取指定类型的注解 */ public <A extends Annotation> A getAnnotation(Class<A> annotationType); /** * 获取所有注解,如果有的话 */ public Annotation[] getAnnotations(); /** * 获取所有注解,忽略继承的注解 */ public Annotation[] getDeclaredAnnotations(); /** * 指定注解是否存在该元素上,如果有则返回true,否则false */ public boolean isAnnotationPresent(Class<? extends Annotation> annotationType); /** * 获取Method中参数的所有注解 */ public Annotation[][] getParameterAnnotations(); 1. 定义注解 /** * @author mazaiting * @date 2018/1/16 */ public class RuntimeAnnotation { /** * 适用类、接口(包括注解类型)或枚举 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface ClassInfo { String value(); } /** * 适用变量,也包括枚举常量 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface FieldInfo { int[] value(); } /** * 适用方法 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MethodInfo { String name() default "long"; String data(); int age() default 24; } } 2. 使用注解 /** * @author mazaiting * @date 2018/1/16 */ @RuntimeAnnotation.ClassInfo("TestRuntimeAnnotation class") public class TestRuntimeAnnotation { @RuntimeAnnotation.FieldInfo(value = {1, 2}) public String fieldnfo = "FieldInfo"; @RuntimeAnnotation.FieldInfo(value = {10086}) public int i = 100; @RuntimeAnnotation.MethodInfo(name = "mazaiting", data = "big") public static String getMethodInfo() { return TestRuntimeAnnotation.class.getSimpleName(); } } 3. 解析注解 public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView textView = (TextView) findViewById(R.id.textView); /**运行时注解*/ textView.setText(parse()); } /** * 解析运行时注解 */ private String parse() { // 创建一个线程安全的字符串拼接对象 StringBuffer sb = new StringBuffer(); // 获取类字节码 Class cls = TestRuntimeAnnotation.class; // 获取构造方法 Constructor[] constructors = cls.getConstructors(); // 获取指定类型的注解 // 获取ClassInfo注解 sb.append("Class注解:").append("\n"); RuntimeAnnotation.ClassInfo classInfo = (RuntimeAnnotation.ClassInfo) cls.getAnnotation(RuntimeAnnotation.ClassInfo.class); if (null != classInfo) { // 拼接访问修饰符和类名 sb.append(Modifier.toString(cls.getModifiers())).append(" ") .append(cls.getSimpleName()).append("\n"); sb.append("注解值:").append(classInfo.value()).append("\n\n"); } // 获取FieldInfo注解 Field[] fields = cls.getDeclaredFields(); for (Field field : fields) { RuntimeAnnotation.FieldInfo fieldInfo = field.getAnnotation(RuntimeAnnotation.FieldInfo.class); if (null != fieldInfo) { // 拼接访问修饰符,类型名,字段名 sb.append(Modifier.toString(field.getModifiers())).append(" ") .append(field.getType().getSimpleName()).append(" ") .append(field.getName()).append("\n"); sb.append("注解值:").append(Arrays.toString(fieldInfo.value())).append("\n\n"); } } // 获取MethodInfo注解 sb.append("Method注解:").append("\n"); Method[] methods = cls.getDeclaredMethods(); for (Method method: methods) { RuntimeAnnotation.MethodInfo methodInfo = method.getAnnotation(RuntimeAnnotation.MethodInfo.class); if (null != methodInfo) { // 拼接访问修饰符、返回值类型、方法名 sb.append(Modifier.toString(method.getModifiers())).append(" ") .append(method.getReturnType().getSimpleName()).append(" ") .append(method.getName()).append("\n"); // 注解值 sb.append("注解值:").append("\n"); sb.append("name: ").append(methodInfo.name()).append("\n"); sb.append("data: ").append(methodInfo.data()).append("\n"); sb.append("age: ").append(methodInfo.age()).append("\n"); } } return sb.toString(); } } 效果图: 效果图.png

优秀的个人博客,低调大师

用脚本为本blog增加了几项自定义功能

这段时间的工作主要是研究客户端的脚本编程,所以顺便使用脚本为blog提供了几个小功能,这些功能有的是便于读者阅读,而有的是便于作者管理blog的。包括:banner广播、页面反色、搜索跟踪和Google广告。下面分别说说他们是怎么弄得。 从上到下说吧,第一个添加一个Banner广播,这个是干什么用的呢?就是写一些问候的话语放在这里了,效果如下图: 这个广播播的内容是:怎么老是这些广告啊,真是烦人:< 这个东西的实现基于了页面的布局,这个Banner条目的位置正好是我使用这个主题的一个ID为sub的DIV里。所以我替换DIV里的内容,就弄出这个广播了。我这里都是介绍google广告的,当然你可以自己订制放任何的东西。 添加Banner广播的代码如下: < script language ="javascript" > </ script > 第二个功能是增加了一个页面 色彩反转,其开关在'公告'下的计数器旁边(如右图),您可以自己选择是否将页面反色,并且现在的结果会保存在cookie里,将在以后的浏览中继续生效。这个功能其实提供了又一段时间了,不过一直没有提供customize,也就一直没有介绍。后来居然搞得有人抱怨说在反色状态下老是点错滚动条 。 第三个功能是提供了一个Google的广告,是通过Google AdSense计划加入的。由于Google广告是先详细分析页面内容,然后再提供与页面紧密相关的广告条目,所以可以给浏览文章的人提示很友好的广告内容。当然点击Google也会给我们带来一点点的好处 ,AdSense是会根据点击付费的。 第四个功能是增强了'搜索跟踪'功能,原来我曾介绍过 通过注入脚本给页面添加了一个GoogleTrack的功能。不过后来我发现对于中文内容的搜索,Baidu还是有其优势的,本来我对Baidu有些成见(因为有一年Google被阿共封锁了, www.google.com居然被解析成了baidu@_@)。但是这么长时间了,Baidu也还是在进步,何必老是翻那些陈年老账呢,要于时俱进嘛,所以又添加了一个'百度跟踪'。而且可以通过右图下端的一组RadioButton来选择使用什么Track,它们分别是:GoogleTrack,BaiduTrack和随机选取Tracker。 注入Search Tracker的代码如下: < script Language ="javascript" > </ script > 由于Baidu搜索引擎接受的是GB码的escape形式,所以在代码使用了一段VBScript来编码。 < script language ="vbscript" > function vbGetGBCode(str) dim i,length,slength = len (str) for i = 1 to lengthhexCode = hex ( asc (str.charAt(i - 1 ))) if ( len (hexCode) mod 2 ) = 0 then s = s & " % " & mid (hexCode, 1 , 2 ) if ( len (hexCode) = 4 ) then s = s & " % " & mid (hexCode, 3 , 2 ) end if else s = s & " %0 " & hexCode end if next vbGetGBCode = s endfunction </ script > 而Google搜索引擎是接受encodeURIComponent的编码,所以就简单多了。 注入百度Tracker的效果如图所示: 本来这些功能除了反色以外都可以很容易的在服务器端做的,不过毛主席不是教导过大家'自己动手风衣足食'嘛。 本文转自博客园鸟食轩的博客,原文链接:http://www.cnblogs.com/birdshome/,如需转载请自行联系原博主。

优秀的个人博客,低调大师

SharePoint 2010:自定义XSLT List View webpart的行为和样式

添加一个List view webpart用于显示Links列表的内容,如下: 点击Add后,如下: 使用SPD可以看到Webpart的xml definition,如下: <XmlDefinition> <View Name="{48E14159-6F55-489A-BF10-98ECF486F0A7}" MobileView="TRUE" Type="HTML" Hidden="TRUE" OrderedView="TRUE" DisplayName="" Url="/sites/team1/sub1/Part3/SitePages/testxlv.aspx" Level="1" BaseViewID="1" ContentTypeID="0x" ImageUrl="/_layouts/images/links.png"> <Query> <OrderBy> <FieldRef Name="Order" Ascending="TRUE"/> </OrderBy> </Query> <ViewFields> <FieldRef Name="DocIcon"/> <FieldRef Name="Edit"/> <FieldRef Name="URLwMenu"/> <FieldRef Name="Comments"/> </ViewFields> <RowLimit Paged="TRUE">30</RowLimit> <Toolbar Type="Freeform"/> </View> </XmlDefinition> 选中WebPart,切换到Design的tab,然后点击Customize XSLT下拉菜单中的Customize Entire View 点击之后页面会显示出XSL的代码,可以从页面的代码行数看出,增加很多,我们就可以直接在页面上进行修改了。找到下面代码: <a onfocus="OnLink(this)" href="{$url}"> <xsl:choose> <xsl:when test="$desc=''"> <xsl:value-of disable-output-escaping="no" select="$url" /> </xsl:when> <xsl:otherwise> <xsl:value-of select="$desc" /> </xsl:otherwise> </xsl:choose> </a> 我们可以修改样式和行为,举个简单的例子,默认的link点击是在本网页打开的,我们可以将其改为在新窗口打开,我们只要将上面第一行改为如下: <a onfocus="OnLink(this)" href="javascript:void();" onclick="window.open('{$url}');"> 本文转自Justin博客园博客,原文链接:http://www.cnblogs.com/carysun/archive/2011/01/02/moss2010-cusxlv.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android开发实践:自定义带消息循环(Looper)的工作线程

1. 首先,我们完成一个简单的线程框架。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public class LooperThread{ private volatile boolean mIsLooperQuit= false ; private ThreadmThread; public void start(){ if (mThread!= null ){ return ; } mIsLooperQuit= false ; mThread= new Thread(mLooperRunnable); mThread.start(); } public void stop(){ if (mThread== null ){ return ; } mIsLooperQuit= true ; mThread= null ; } protected RunnablemLooperRunnable= new Runnable(){ @Override public void run(){ while (!mIsLooperQuit){ } } }; } 如上述代码所示,mLooperRunnable.run()循环执行线程任务,mIsLooperQuit则是线程退出循环的条件。下面,我们将添加消息的发送和处理代码。 2. 添加线程循环的消息发送和处理代码 (1) 定义消息结构体,创建消息队列 1 2 3 4 5 6 7 8 public class LooperThread{ private Queue<Message>mMessageQueue= new LinkedList<Message>(); public static class Message{ int what; } } (2) 创建互斥锁和条件变量 1 2 3 4 5 public class LooperThread{ private LockmLock= new ReentrantLock(); private ConditionmCondition=mLock.newCondition(); } (3) 创建发送消息的函数 1 2 3 4 5 6 7 8 9 10 //发送消息,由外部其他模块调用,发送消息给线程 public void sendMessage(Messagemessage){ if (mThread== null ){ return ; } mLock.lock(); mMessageQueue.add(message); //添加消息到消息队列 mCondition.signal(); //通知线程循环,有消息来了,请立即处理 mLock.unlock(); } (4) 创建处理消息的函数 1 2 3 4 //处理消息,由线程内部调用 public void handleMessage(Messagemessage){ //这里可以通过一个Callback来回调监听者 } (5) 在mLooperRunnable.run()循环中解析消息 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 protected RunnablemLooperRunnable= new Runnable(){ @Override public void run(){ while (!mIsLooperQuit){ mLock.lock(); Messagemessage= null ; try { while (!mIsLooperQuit&&mMessageQueue.isEmpty()){ mCondition.await(); //没有消息到来则休眠 } message=mMessageQueue.poll(); } catch (InterruptedExceptione){ e.printStackTrace(); } finally { mLock.unlock(); } handleMessage(message); } }; } (6) 修改线程的Stop()函数,唤醒休眠的消息循环 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public void stop(){ if (mThread== null ){ return ; } mIsLooperQuit= true ; mLock.lock(); mCondition.signal(); mLock.unlock(); mMessageQueue.clear(); mThread= null ; } 到这里,一个基本的带有消息循环的线程类封装就完成了,相信大家应该从编写这段代码的过程中,理解了系统是如何实现消息循环的。 本文转自 Jhuster 51CTO博客,原文链接:http://blog.51cto.com/ticktick/1565272,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android笔记:通过RadioGroup/RadioButton自定义tabhost的简单方法

XML代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 <RelativeLayout xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http://schemas.android.com/tools" android:layout_width= "match_parent" android:layout_height= "match_parent" tools:context= ".MainActivity" > <TabHost android:id= "@android:id/tabhost" android:layout_width= "match_parent" android:layout_height= "match_parent" android:layout_alignParentLeft= "true" android:layout_alignParentTop= "true" > <LinearLayout android:layout_width= "match_parent" android:layout_height= "match_parent" android:orientation= "vertical" > <TabWidget android:id= "@android:id/tabs" android:layout_width= "match_parent" android:layout_height= "wrap_content" android:visibility= "gone" > </TabWidget> <FrameLayout android:id= "@android:id/tabcontent" android:layout_width= "match_parent" android:layout_height= "0dp" android:layout_weight= "1" > </FrameLayout> <RadioGroup android:layout_width= "match_parent" android:layout_height= "wrap_content" android:layout_gravity= "bottom" android:orientation= "horizontal" > <RadioButton android:id= "@+id/maintab_radio_tab1" style= "@style/tab_button" android:checked= "true" android:text= "主页" android:background= "#ff00ff00" /> <RadioButton android:id= "@+id/maintab_radio_tab2" style= "@style/tab_button" android:text= "分页" android:background= "#ff00ff00" /> <RadioButton android:id= "@+id/maintab_radio_tab3" style= "@style/tab_button" android:text= "设置" android:background= "#ff00ff00" /> </RadioGroup> </LinearLayout> </TabHost> </RelativeLayout> style="@style/tab_button"文件: 1 2 3 4 5 6 7 8 9 10 11 12 <!-- 主页底部RadioButton样式 --> <style name= "tab_button" > <item name= "android:layout_width" >fill_parent</item> <item name= "android:layout_height" >wrap_content</item> <item name= "android:ellipsize" >marquee</item> <item name= "android:button" > @null </item> <item name= "android:paddingTop" >1dp</item> <item name= "android:layout_weight" > 1.0 </item> <item name= "android:gravity" >center_horizontal</item> <item name= "android:singleLine" > true </item> <item name= "android:drawablePadding" > 1 .0dip</item> </style> 布局结构:(将TabWidget隐藏,用一组去掉button勾选框的RadioButton替代) java代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 public class MainActivity extends TabActivity implements OnClickListener { private RadioButton mBtn_tab1; private RadioButton mBtn_tab2; private RadioButton mBtn_tab3; private TabHost mTabHost; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); initTab(); } //初始化界面 private void init() { mBtn_tab1 = (RadioButton)findViewById(R.id.maintab_radio_tab1); mBtn_tab2 = (RadioButton)findViewById(R.id.maintab_radio_tab2); mBtn_tab3 = (RadioButton)findViewById(R.id.maintab_radio_tab3); mBtn_tab1.setOnClickListener( this ); mBtn_tab2.setOnClickListener( this ); mBtn_tab3.setOnClickListener( this ); } //初始化底部标签栏 private void initTab() { mTabHost = getTabHost(); mTabHost.addTab(mTabHost.newTabSpec( "tab1" ).setIndicator( "tab1" ).setContent( new Intent( this , Tab1Activity. class ))); mTabHost.addTab(mTabHost.newTabSpec( "tab2" ).setIndicator( "tab2" ).setContent( new Intent( this , Tab2Activity. class ))); mTabHost.addTab(mTabHost.newTabSpec( "tab3" ).setIndicator( "tab3" ).setContent( new Intent( this , Tab1Activity. class ))); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.maintab_radio_tab1: mTabHost.setCurrentTabByTag( "tab1" ); break ; case R.id.maintab_radio_tab2: mTabHost.setCurrentTabByTag( "tab2" ); break ; case R.id.maintab_radio_tab3: mTabHost.setCurrentTabByTag( "tab3" ); break ; default : break ; } } } 本文转自 glblong 51CTO博客,原文链接:http://blog.51cto.com/glblong/1281759,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android Studio 第五十三期 - 自定义EditText密码键盘

代码已经整理好,效果如下图: code: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 //设置输入为密码模式 inputETP1.setInputType(InputType.TYPE_CLASS_NUMBER|EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD); inputETP1.setDrawableRightListener( new EditTextPassword.DrawableRightListener(){ @Override public void onDrawableRightClick(){ //同样地可以在这可以实现其他的效果,比如一键清空 if (mIsShow1){ inputETP1.setCompoundDrawablesWithIntrinsicBounds( 0 , 0 ,R.drawable.eye_grey, 0 ); inputETP1.setInputType(InputType.TYPE_CLASS_NUMBER|EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD); } else { inputETP1.setCompoundDrawablesWithIntrinsicBounds( 0 , 0 ,R.drawable.eye_orange, 0 ); //inputETP.setInputType(InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD); inputETP1.setInputType(InputType.TYPE_CLASS_NUMBER|EditorInfo.TYPE_NUMBER_VARIATION_NORMAL); } mIsShow1=!mIsShow1; } }); 地址:https://github.com/geeklx/MyApplication/tree/master/p039_edittextpwd 本文转自 吴雨声 51CTO博客,原文链接:http://blog.51cto.com/liangxiao/1965175,如需转载请自行联系原作者

优秀的个人博客,低调大师

Android 图片裁剪功能实现详解(类似QQ自定义头像裁剪)

最近有看到有朋友在讨论QQ头像的裁剪上传是怎么实现的,吼吼,小马也没做过,好奇之下学习下,发现以前项目中有类型的功能,结合官方文档里面的解释,就更好玩了,周末,急急忙忙写的,记录在博客里,希望能与大家交流学习,也恳请高手能解答小马在代码注释中提出的疑问,不管有没有人回答,小马先谢谢了,一样的,先看下效果图(效果图小马不解释了,直接流水写下去,小马是直接在模拟器里写的,能在真机上使用,因为很简单),再看代码是怎么实现的: 一:主布局界面 二:点击控件触发事件后效果图 三:拍照完之后效果图 四:裁剪界面效果图 五:点击相册后返回的图片效果图 六:裁剪完从相册PICK的保存后的效果图 下面直接来看下主控制类代码,如下: packagecom.xiaoma.piccut.demo; importjava.io.File; importandroid.app.Activity; importandroid.app.AlertDialog; importandroid.content.DialogInterface; importandroid.content.Intent; importandroid.graphics.Bitmap; importandroid.graphics.drawable.BitmapDrawable; importandroid.graphics.drawable.Drawable; importandroid.net.Uri; importandroid.os.Bundle; importandroid.os.Environment; importandroid.provider.MediaStore; importandroid.view.View; importandroid.view.View.OnClickListener; importandroid.widget.Button; importandroid.widget.ImageButton; importandroid.widget.ImageView; /** *@Title:PicCutDemoActivity.java *@Packagecom.xiaoma.piccut.demo *@Description:图片裁剪功能测试 *@authorXiaoMa */ publicclassPicCutDemoActivityextendsActivityimplementsOnClickListener{ privateImageButtonib=null; privateImageViewiv=null; privateButtonbtn=null; privateStringtp=null; /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); //初始化 init(); } /** *初始化方法实现 */ privatevoidinit(){ ib=(ImageButton)findViewById(R.id.imageButton1); iv=(ImageView)findViewById(R.id.imageView1); btn=(Button)findViewById(R.id.button1); ib.setOnClickListener(this); iv.setOnClickListener(this); btn.setOnClickListener(this); } /** *控件点击事件实现 * *因为有朋友问不同控件的背景图裁剪怎么实现, *我就在这个地方用了三个控件,只为了自己记录学习 *大家觉得没用的可以跳过啦 */ @Override publicvoidonClick(Viewv){ switch(v.getId()){ caseR.id.imageButton1: ShowPickDialog(); break; caseR.id.imageView1: ShowPickDialog(); break; caseR.id.button1: ShowPickDialog(); break; default: break; } } /** *选择提示对话框 */ privatevoidShowPickDialog(){ newAlertDialog.Builder(this) .setTitle("设置头像...") .setNegativeButton("相册",newDialogInterface.OnClickListener(){ publicvoidonClick(DialogInterfacedialog,intwhich){ dialog.dismiss(); /** *刚开始,我自己也不知道ACTION_PICK是干嘛的,后来直接看Intent源码, *可以发现里面很多东西,Intent是个很强大的东西,大家一定仔细阅读下 */ Intentintent=newIntent(Intent.ACTION_PICK,null); /** *下面这句话,与其它方式写是一样的效果,如果: *intent.setData(MediaStore.Images.Media.EXTERNAL_CONTENT_URI); *intent.setType(""image/*");设置数据类型 *如果朋友们要限制上传到服务器的图片类型时可以直接写如:"image/jpeg、image/png等的类型" *这个地方小马有个疑问,希望高手解答下:就是这个数据URI与类型为什么要分两种形式来写呀?有什么区别? */ intent.setDataAndType( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*"); startActivityForResult(intent,1); } }) .setPositiveButton("拍照",newDialogInterface.OnClickListener(){ publicvoidonClick(DialogInterfacedialog,intwhichButton){ dialog.dismiss(); /** *下面这句还是老样子,调用快速拍照功能,至于为什么叫快速拍照,大家可以参考如下官方 *文档,you_sdk_path/docs/guide/topics/media/camera.html *我刚看的时候因为太长就认真看,其实是错的,这个里面有用的太多了,所以大家不要认为 *官方文档太长了就不看了,其实是错的,这个地方小马也错了,必须改正 */ Intentintent=newIntent( MediaStore.ACTION_IMAGE_CAPTURE); //下面这句指定调用相机拍照后的照片存储的路径 intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri .fromFile(newFile(Environment .getExternalStorageDirectory(), "xiaoma.jpg"))); startActivityForResult(intent,2); } }).show(); } @Override protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){ switch(requestCode){ //如果是直接从相册获取 case1: startPhotoZoom(data.getData()); break; //如果是调用相机拍照时 case2: Filetemp=newFile(Environment.getExternalStorageDirectory() +"/xiaoma.jpg"); startPhotoZoom(Uri.fromFile(temp)); break; //取得裁剪后的图片 case3: /** *非空判断大家一定要验证,如果不验证的话, *在剪裁之后如果发现不满意,要重新裁剪,丢弃 *当前功能时,会报NullException,小马只 *在这个地方加下,大家可以根据不同情况在合适的 *地方做判断处理类似情况 * */ if(data!=null){ setPicToView(data); } break; default: break; } super.onActivityResult(requestCode,resultCode,data); } /** *裁剪图片方法实现 *@paramuri */ publicvoidstartPhotoZoom(Uriuri){ /* *至于下面这个Intent的ACTION是怎么知道的,大家可以看下自己路径下的如下网页 *yourself_sdk_path/docs/reference/android/content/Intent.html *直接在里面Ctrl+F搜:CROP,之前小马没仔细看过,其实安卓系统早已经有自带图片裁剪功能, *是直接调本地库的,小马不懂CC++这个不做详细了解去了,有轮子就用轮子,不再研究轮子是怎么 *制做的了...吼吼 */ Intentintent=newIntent("com.android.camera.action.CROP"); intent.setDataAndType(uri,"image/*"); //下面这个crop=true是设置在开启的Intent中设置显示的VIEW可裁剪 intent.putExtra("crop","true"); //aspectXaspectY是宽高的比例 intent.putExtra("aspectX",1); intent.putExtra("aspectY",1); //outputXoutputY是裁剪图片宽高 intent.putExtra("outputX",150); intent.putExtra("outputY",150); intent.putExtra("return-data",true); startActivityForResult(intent,3); } /** *保存裁剪之后的图片数据 *@parampicdata */ privatevoidsetPicToView(Intentpicdata){ Bundleextras=picdata.getExtras(); if(extras!=null){ Bitmapphoto=extras.getParcelable("data"); Drawabledrawable=newBitmapDrawable(photo); /** *下面注释的方法是将裁剪之后的图片以Base64Coder的字符方式上 *传到服务器,QQ头像上传采用的方法跟这个类似 */ /*ByteArrayOutputStreamstream=newByteArrayOutputStream(); photo.compress(Bitmap.CompressFormat.JPEG,60,stream); byte[]b=stream.toByteArray(); //将图片流以字符串形式存储下来 tp=newString(Base64Coder.encodeLines(b)); 这个地方大家可以写下给服务器上传图片的实现,直接把tp直接上传就可以了, 服务器处理的方法是服务器那边的事了,吼吼 如果下载到的服务器的数据还是以Base64Coder的形式的话,可以用以下方式转换 为我们可以用的图片类型就OK啦...吼吼 BitmapdBitmap=BitmapFactory.decodeFile(tp); Drawabledrawable=newBitmapDrawable(dBitmap); */ ib.setBackgroundDrawable(drawable); iv.setBackgroundDrawable(drawable); } } } 下面来看下裁剪中用到的类,大家详细看下头注释: packagecom.xiaoma.piccut.demo; /** *下面这些注释是下载这个类的时候本来就有的,本来要删除的,但看了下竟然是license,吼吼, *好东西,留在注释里,以备不时之用,大家有需要加license的可以到下面的网址找哦 */ //EPL,EclipsePublicLicense,V1.0orlater,http://www.eclipse.org/legal //LGPL,GNULesserGeneralPublicLicense,V2.1orlater,http://www.gnu.org/licenses/lgpl.html //GPL,GNUGeneralPublicLicense,V2orlater,http://www.gnu.org/licenses/gpl.html //AL,ApacheLicense,V2.0orlater,http://www.apache.org/licenses //BSD,BSDLicense,http://www.opensource.org/licenses/bsd-license.php /** *ABase64encoder/decoder. * *<p> *ThisclassisusedtoencodeanddecodedatainBase64formatasdescribedinRFC1521. * *<p> *Projecthomepage:<ahref="http://www.source-code.biz/base64coder/java/">www.source-code.biz/base64coder/java</a><br> *Author:Christiand'Heureuse,InventecInformatikAG,Zurich,Switzerland<br> *Multi-licensed:EPL/LGPL/GPL/AL/BSD. */ /** *这个类在上面注释的网址中有,大家可以自行下载下,也可以直接用这个, *公开的Base64Coder类(不用深究它是怎么实现的, *还是那句话,有轮子直接用轮子),好用的要死人了... *小马也很无耻的引用了这个网址下的东东,吼吼... *@Title:Base64Coder.java *@Packagecom.xiaoma.piccut.demo *@Description:TODO *@authorXiaoMa */ publicclassBase64Coder{ //Thelineseparatorstringoftheoperatingsystem. privatestaticfinalStringsystemLineSeparator=System.getProperty("line.separator"); //Mappingtablefrom6-bitnibblestoBase64characters. privatestaticchar[]map1=newchar[64]; static{ inti=0; for(charc='A';c<='Z';c++)map1[i++]=c; for(charc='a';c<='z';c++)map1[i++]=c; for(charc='0';c<='9';c++)map1[i++]=c; map1[i++]='+';map1[i++]='/';} //MappingtablefromBase64charactersto6-bitnibbles. privatestaticbyte[]map2=newbyte[128]; static{ for(inti=0;i<map2.length;i++)map2[i]=-1; for(inti=0;i<64;i++)map2[map1[i]]=(byte)i;} /** *EncodesastringintoBase64format. *Noblanksorlinebreaksareinserted. *@paramsAStringtobeencoded. *@returnAStringcontainingtheBase64encodeddata. */ publicstaticStringencodeString(Strings){ returnnewString(encode(s.getBytes()));} /** *EncodesabytearrayintoBase64formatandbreakstheoutputintolinesof76characters. *Thismethodiscompatiblewith<code>sun.misc.BASE64Encoder.encodeBuffer(byte[])</code>. *@paraminAnarraycontainingthedatabytestobeencoded. *@returnAStringcontainingtheBase64encodeddata,brokenintolines. */ publicstaticStringencodeLines(byte[]in){ returnencodeLines(in,0,in.length,76,systemLineSeparator);} /** *EncodesabytearrayintoBase64formatandbreakstheoutputintolines. *@paraminAnarraycontainingthedatabytestobeencoded. *@paramiOffOffsetofthefirstbytein<code>in</code>tobeprocessed. *@paramiLenNumberofbytestobeprocessedin<code>in</code>,startingat<code>iOff</code>. *@paramlineLenLinelengthfortheoutputdata.Shouldbeamultipleof4. *@paramlineSeparatorThelineseparatortobeusedtoseparatetheoutputlines. *@returnAStringcontainingtheBase64encodeddata,brokenintolines. */ publicstaticStringencodeLines(byte[]in,intiOff,intiLen,intlineLen,StringlineSeparator){ intblockLen=(lineLen*3)/4; if(blockLen<=0)thrownewIllegalArgumentException(); intlines=(iLen+blockLen-1)/blockLen; intbufLen=((iLen+2)/3)*4+lines*lineSeparator.length(); StringBuilderbuf=newStringBuilder(bufLen); intip=0; while(ip<iLen){ intl=Math.min(iLen-ip,blockLen); buf.append(encode(in,iOff+ip,l)); buf.append(lineSeparator); ip+=l;} returnbuf.toString();} /** *EncodesabytearrayintoBase64format. *Noblanksorlinebreaksareinsertedintheoutput. *@paraminAnarraycontainingthedatabytestobeencoded. *@returnAcharacterarraycontainingtheBase64encodeddata. */ publicstaticchar[]encode(byte[]in){ returnencode(in,0,in.length);} /** *EncodesabytearrayintoBase64format. *Noblanksorlinebreaksareinsertedintheoutput. *@paraminAnarraycontainingthedatabytestobeencoded. *@paramiLenNumberofbytestoprocessin<code>in</code>. *@returnAcharacterarraycontainingtheBase64encodeddata. */ publicstaticchar[]encode(byte[]in,intiLen){ returnencode(in,0,iLen);} /** *EncodesabytearrayintoBase64format. *Noblanksorlinebreaksareinsertedintheoutput. *@paraminAnarraycontainingthedatabytestobeencoded. *@paramiOffOffsetofthefirstbytein<code>in</code>tobeprocessed. *@paramiLenNumberofbytestoprocessin<code>in</code>,startingat<code>iOff</code>. *@returnAcharacterarraycontainingtheBase64encodeddata. */ publicstaticchar[]encode(byte[]in,intiOff,intiLen){ intoDataLen=(iLen*4+2)/3;//outputlengthwithoutpadding intoLen=((iLen+2)/3)*4;//outputlengthincludingpadding char[]out=newchar[oLen]; intip=iOff; intiEnd=iOff+iLen; intop=0; while(ip<iEnd){ inti0=in[ip++]&0xff; inti1=ip<iEnd?in[ip++]&0xff:0; inti2=ip<iEnd?in[ip++]&0xff:0; into0=i0>>>2; into1=((i0&3)<<4)|(i1>>>4); into2=((i1&0xf)<<2)|(i2>>>6); into3=i2&0x3F; out[op++]=map1[o0]; out[op++]=map1[o1]; out[op]=op<oDataLen?map1[o2]:'=';op++; out[op]=op<oDataLen?map1[o3]:'=';op++;} returnout;} /** *DecodesastringfromBase64format. *NoblanksorlinebreaksareallowedwithintheBase64encodedinputdata. *@paramsABase64Stringtobedecoded. *@returnAStringcontainingthedecodeddata. *@throwsIllegalArgumentExceptionIftheinputisnotvalidBase64encodeddata. */ publicstaticStringdecodeString(Strings){ returnnewString(decode(s));} /** *DecodesabytearrayfromBase64formatandignoreslineseparators,tabsandblanks. *CR,LF,TabandSpacecharactersareignoredintheinputdata. *Thismethodiscompatiblewith<code>sun.misc.BASE64Decoder.decodeBuffer(String)</code>. *@paramsABase64Stringtobedecoded. *@returnAnarraycontainingthedecodeddatabytes. *@throwsIllegalArgumentExceptionIftheinputisnotvalidBase64encodeddata. */ publicstaticbyte[]decodeLines(Strings){ char[]buf=newchar[s.length()+3]; intp=0; for(intip=0;ip<s.length();ip++){ charc=s.charAt(ip); if(c!=''&&c!='\r'&&c!='\n'&&c!='\t') buf[p++]=c;} while((p%4)!=0) buf[p++]='0'; returndecode(buf,0,p);} /** *DecodesabytearrayfromBase64format. *NoblanksorlinebreaksareallowedwithintheBase64encodedinputdata. *@paramsABase64Stringtobedecoded. *@returnAnarraycontainingthedecodeddatabytes. *@throwsIllegalArgumentExceptionIftheinputisnotvalidBase64encodeddata. */ publicstaticbyte[]decode(Strings){ returndecode(s.toCharArray());} /** *DecodesabytearrayfromBase64format. *NoblanksorlinebreaksareallowedwithintheBase64encodedinputdata. *@paraminAcharacterarraycontainingtheBase64encodeddata. *@returnAnarraycontainingthedecodeddatabytes. *@throwsIllegalArgumentExceptionIftheinputisnotvalidBase64encodeddata. */ publicstaticbyte[]decode(char[]in){ returndecode(in,0,in.length);} /** *DecodesabytearrayfromBase64format. *NoblanksorlinebreaksareallowedwithintheBase64encodedinputdata. *@paraminAcharacterarraycontainingtheBase64encodeddata. *@paramiOffOffsetofthefirstcharacterin<code>in</code>tobeprocessed. *@paramiLenNumberofcharacterstoprocessin<code>in</code>,startingat<code>iOff</code>. *@returnAnarraycontainingthedecodeddatabytes. *@throwsIllegalArgumentExceptionIftheinputisnotvalidBase64encodeddata. */ publicstaticbyte[]decode(char[]in,intiOff,intiLen){ if(iLen%4!=0)thrownewIllegalArgumentException("LengthofBase64encodedinputstringisnotamultipleof4."); while(iLen>0&&in[iOff+iLen-1]=='=')iLen--; intoLen=(iLen*3)/4; byte[]out=newbyte[oLen]; intip=iOff; intiEnd=iOff+iLen; intop=0; while(ip<iEnd){ inti0=in[ip++]; inti1=in[ip++]; inti2=ip<iEnd?in[ip++]:'A'; inti3=ip<iEnd?in[ip++]:'A'; if(i0>127||i1>127||i2>127||i3>127) thrownewIllegalArgumentException("IllegalcharacterinBase64encodeddata."); intb0=map2[i0]; intb1=map2[i1]; intb2=map2[i2]; intb3=map2[i3]; if(b0<0||b1<0||b2<0||b3<0) thrownewIllegalArgumentException("IllegalcharacterinBase64encodeddata."); into0=(b0<<2)|(b1>>>4); into1=((b1&0xf)<<4)|(b2>>>2); into2=((b2&3)<<6)|b3; out[op++]=(byte)o0; if(op<oLen)out[op++]=(byte)o1; if(op<oLen)out[op++]=(byte)o2;} returnout;} //Dummyconstructor. privateBase64Coder(){} }//endclassBase64Coder 最后,小马还把小DEMO源码放在附件里面,有需要的朋友可以下载下来,共同交流学习,也恳请高人回答下小马在文章注释中提出的问题,谢谢,文章是小马急急忙忙在家写的,在网吧发的,晕...不是我有多用功,这边下雨,讨厌下雨,下雨我就郁闷,来网吧玩的,顺带发下文章,吼吼,该玩的时候死命的玩,该工作的时候死命的工作,年轻时疯狂,老了不后悔,吼吼,加油加油!大家工作,也注意身体健康,嘿嘿,你懂的,不解释...哈哈 本文转自华华世界 51CTO博客,原文链接:http://blog.51cto.com/mzh3344258/808837,如需转载请自行联系原作者

优秀的个人博客,低调大师

利用阿里云容器服务实现自定义节点伸缩

简介 阿里云容器服务很早就提供了基于集群CPU/内存的平均使用量触发节点自动伸缩功能,帮助许多客户自如应对业务压力的弹性变化。其原理是利用阿里云的云监控能力,在资源使用(cpu和memory)达到阈值时,触发节点伸缩。 同时还有一些企业级用户希望根据自身的监控数据和逻辑判断是否进行扩容和缩容操作,甚至可以按照固定时间进行节点扩容和缩容,针对这种场景,就需要调用的是扩容或者缩容触发器。 容器服务目前提供创建节点触发器的功能,调用节点触发器,并可以利用openAPI查看扩容出来的ECS节点方便管理和自动化的需求. 本文将向您介绍完成这一能力的步骤。 创建节点伸缩触发器trigger_url 登录 容器服务管理控制台。 单击左侧导航栏中的 集群。 在 集群列表 页面,选择要设置的集群,点击 管理。 单击左侧导航栏中的 节点伸缩,单击 请新建自动伸缩规则

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册