IDEA开发 Maven打包可执行的jar JSmooth转exe文件

这个文章主要解决这样几个问题

  1. IDEA如何用Maven管理项目
  2. Maven如何打包成可执行jar
  3. JSmooth转jar为exe文件

IDEA如何用Maven管理项目



Maven如何打包成可执行jar

在pom.xml中配置
com.rick.client.App是main函数所在的类

<plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <appendAssemblyId>false</appendAssemblyId>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>com.rick.client.App</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>assembly</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>ibiblio.org</id>
            <name>ibiblio Mirror of http://repo1.maven.org/maven2/</name>
            <url>http://mirrors.ibiblio.org/pub/mirrors/maven2</url>
        </repository>
    </repositories>

执行mvn命令,打包可执行jar

E:\p4v_location\watsonsTNA\fine>mvn assembly:assembly
E:\p4v_location\watsonsTNA\fine\target>java -jar exe-1.0-SNAPSHOT.jar

JSmooth转jar为exe文件



Python高级编程使用__slots__

这这一节主要是动态为对象/实例添加属性和方法

代码如下

from types import MethodType

#这是外部方法1
def set_name(self, name):
    self.name = name


#这是外部方法2
def set_score(self, score):
    self.score = score    

class Student(object):
    __slots__ = ('name')

    def set_age(self, age):
        self.age = age

stu = Student();
stu.age = 10
stu.set_age(20)

#给实例绑定一个方法,此处绑定到实例stu,对其他实例不起作用
stu.set_name = MethodType(set_name, stu) # 给实例绑定一个方法
stu.set_name('Rick')

print(stu.name)    

#给类绑定一个方法,所有的实例都可以使用
Student.set_score = MethodType(set_score, Student)
stu.set_score(99.5)
print(stu.score)

使用slots

但是,如果我们想要限制实例的属性怎么办?比如,只允许对Student实例添加namescore属性

class Student(object):
    __slots__ = ('name', 'store') # 用tuple定义允许绑定的属性名称

如果有不允许的属性,将会抛出异常

F:\python>python slots.py
Traceback (most recent call last):
  File "slots.py", line 18, in <module>
    stu.age = 10
AttributeError: 'Student' object has no attribute 'age'

Note:
使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的:

spring开发邮件设置及注意事项

spring开发邮件设置及注意事项

常见的电子邮件协议有以下几种:SMTP(简单邮件传输协议)、POP3(邮局协议)、IMAP(Internet邮件访问协议)。这几种协议都是由TCP/IP协议族定义的。

  • SMTP(Simple Mail Transfer Protocol):SMTP主要负责底层的邮件系统如何将邮件从一台机器传至另外一台机器。
  • POP(Post Office Protocol):版本为POP3,POP3是把邮件从电子邮箱中传输到本地计算机的协议。
  • IMAP(Internet Message Access Protocol):版本为IMAP4,是POP3的一种替代协议,提供了邮件检索和邮件处理的新功能,这样用户可以完全不必下载邮件正文就可以看到邮件的标题摘要,从邮件客户端软件就可以对服务器上的邮件和文件夹目录等进行操作。IMAP协议增强了电子邮件的灵活性,同时也减少了垃圾邮件对本地系统的直接危害,同时相对节省了用户察看电子邮件的时间。除此之外,IMAP协议可以记忆用户在脱机状态下对邮件的操作(例如移动邮件,删除邮件等)在下一次打开网络连接的时候会自动执行。

开发中默认的协议就是SMTP

我本地用163邮箱进行测试,通过,代码如下

JavaMailSenderImpl senderImpl = new JavaMailSenderImpl(); 

//设定mail server 
senderImpl.setHost("smtp.163.com"); 

//邮件的默认设置协议是`smtp`,端口`25`
//senderImpl.setPort(25); 
//senderImpl.setProtocol("smtp");
//建立邮件消息,发送简单邮件和html邮件的区别 
MimeMessage mailMessage = senderImpl.createMimeMessage(); 
MimeMessageHelper messageHelper = new MimeMessageHelper(mailMessage); 

//设置收件人,寄件人 
messageHelper.setTo("Rick.Xu@movit-tech.com"); 
messageHelper.setFrom("jkxyx205@163.com"); 
messageHelper.setSubject("这个是主题"); 
//true 表示启动HTML格式的邮件 
messageHelper.setText("<html><head></head><body><h1>hello!!spring html Mail</h1></body></html>",true); 
senderImpl.setUsername("jkxyx205@163.com") ; //设置username
//      senderImpl.setPassword("xxx") ; // 设置password

//发送邮件 
senderImpl.send(mailMessage); 

System.out.println("邮件发送成功..."); 

生产环境,客户给出的邮件配置信息

host:10.32.186.111
port:25
sender:support@abc.net
pwd:空

相应的设置只需要修改host,端口和协议默认即可

senderImpl.setHost("10.32.186.111"); 
messageHelper.setFrom("support@abc.net"); 

这时候会抛出异常:

org.springframework.mail.MailAuthenticationException: Authentication failed; nested exception is javax.mail.AuthenticationFailedException: failed to connect, no password specified?

异常给出的提示,说密码不能为空,做如下设置就可以使密码可以为空

Properties prop = new Properties() ;
prop.put("mail.smtp.auth", "false") ; // 如果这个参数设为true,让服务器进行认证,认证用户名和密码是否正确
senderImpl.setJavaMailProperties(prop); 

常用的邮箱服务器(SMTP、POP3)地址、端口

gmail(google.com)
POP3服务器地址:pop.gmail.com(SSL启用 端口:995)
SMTP服务器地址:smtp.gmail.com(SSL启用 端口:587)

21cn.com: 
POP3服务器地址:pop.21cn.com(端口:110)
SMTP服务器地址:smtp.21cn.com(端口:25)

sina.com: 
POP3服务器地址:pop3.sina.com.cn(端口:110)
SMTP服务器地址:smtp.sina.com.cn(端口:25) 

tom.com: 
POP3服务器地址:pop.tom.com(端口:110)
SMTP服务器地址:smtp.tom.com(端口:25)

163.com: 
POP3服务器地址:pop.163.com(端口:110)
SMTP服务器地址:smtp.163.com(端口:25)

263.net: 
POP3服务器地址:pop3.263.net(端口:110)
SMTP服务器地址:smtp.263.net(端口:25)

yahoo.com: 
POP3服务器地址:pop.mail.yahoo.com
SMTP服务器地址:smtp.mail.yahoo.com

263.net.cn: 
POP3服务器地址:pop.263.net.cn(端口:110)
SMTP服务器地址:smtp.263.net.cn(端口:25)

Foxmail:
POP3服务器地址:POP.foxmail.com(端口:110)
SMTP服务器地址:SMTP.foxmail.com(端口:25)

sinaVIP  
POP3服务器:pop3.vip.sina.com (端口:110)
SMTP服务器:smtp.vip.sina.com (端口:25)

sohu.com: 
POP3服务器地址:pop3.sohu.com(端口:110)
SMTP服务器地址:smtp.sohu.com(端口:25)

etang.com: 
POP3服务器地址:pop.etang.com
SMTP服务器地址:smtp.etang.com

x263.net: 
POP3服务器地址:pop.x263.net(端口:110)
SMTP服务器地址:smtp.x263.net(端口:25)

yahoo.com.cn: 
POP3服务器地址:pop.mail.yahoo.com.cn(端口:995)
SMTP服务器地址:smtp.mail.yahoo.com.cn(端口:587)
雅虎邮箱POP3的SSL不启用端口为110,POP3的SSL启用端口995;SMTP的SSL不启用端口为25,SMTP的SSL启用端口为465

QQ邮箱                                       QQ企业邮箱           
POP3服务器地址:pop.qq.com(端口:110)            POP3服务器地址:pop.exmail.qq.com (SSL启用 端口:995)        
SMTP服务器地址:smtp.qq.com (端口:25)           SMTP服务器地址:smtp.exmail.qq.com(SSL启用 端口:587/465)
SMTP服务器需要身份验证

126邮箱                                      HotMail
POP3服务器地址:pop.126.com(端口:110)            POP3服务器地址:pop.live.com (端口:995)
SMTP服务器地址:smtp.126.com(端口:25)            SMTP服务器地址:smtp.live.com (端口:587)

china.com:                                   139邮箱
POP3服务器地址:pop.china.com(端口:110)         POP3服务器地址:POP.139.com(端口:110) 
SMTP服务器地址:smtp.china.com(端口:25)         SMTP服务器地址:SMTP.139.com(端口:25)

POI导出excel性能问题

POI导出excel性能问题

认识Excel

Excel有2种大的版本,20032007(2010/2013总体架构于2007差不多)。Excel中的数据多少将会影响客户端打开数据的速度。
Excel中的数据是由行*列来决定的,一个10列5000行的excel打开是在用户可以接受的范围内的,但是对excel做相关操作,比如“筛选”,可能会爆掉。
另外2003和2007有个最大的不同,2003所能存储216=65,536,而2007所能存储220=1,048,576

认识POI

Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。针对2003和2007有两套不同的实现。
结构:

  • HSSF - 提供读写Microsoft Excel格式档案的功能。2003
  • XSSF - 提供读写Microsoft Excel OOXML格式档案的功能。 2007

POI实现Excel

我们用POI去实现Excel的导出功能,有两个性能问题:1. 导出的时间太长;2. 打开Excel的时间太长。你可以认为由于数据太大引起的性能问题,但是对于不可以避免的
数据量有可以解决的问题吗?就这两方面做一个浅浅的分析。

  1. 导出的时间

    a. 首先检查后台代码是否有可以优化的空间,过于复杂的SQL查询,多余的循环等等。如果你是一次性将所有结果放入List中,那么内存可能会逸出,可以考虑分页查询或者边查边写。

    b. 选择导出2003或2007,一般人可能会认为导出2007无疑是更好的选择,几乎没有行数的限制,版本高写入速度快。但是通过我的测试导出2003比2007快10倍,选择2003,行数的限制怎么办?

  2. 打开Excel的时间

    a. 当文件生成后,打开速度慢已经不是我们可以决定的了。之前说过,数据量影响打开的速度,去掉哪些可有可无的列

    b. 换台高配的电脑

如果想既不受行的限制,又能快速并查看导出,如何处理?

目前我能想到2种方案是:

  1. 以2003的方式导5000条记录为一个文件,最后打包成zip提供客户下载
  2. 因为Excel可以浏览CSV文件,可导到一个CSV文件中,注意英文环境下中文乱码的问题

英文操作系统,Excel打开csv乱码解决方案

首先需要了解CSV

逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据。CSV文件由任意数目的记录组成,记录间以某种换行符分隔;每条记录由字段组成,字段间的分隔符是其它字符或字符串,最常见的是逗号或制表符。通常,所有记录都有完全相同的字段序列。

用记事本打开CSV,ANSI,UTF-8都不会出现乱码的,但是,CSV是用Excel打开utf-8 without BOM是会显示乱码的,这个尤其注意;用ANSI、UTF-8(有BOM)可以打开,为什么UTF-8(有BOM)却可以打开呢?知乎上有人是这么回答的,姑且就这么认为吧

UTF-8 不需要 BOM,尽管 Unicode 标准允许在 UTF-8 中使用 BOM。
所以不含 BOM 的 UTF-8 才是标准形式,在 UTF-8 文件中放置 BOM 主要是微软的习惯(顺便提一下:把带有 BOM 的小端序 UTF-16 称作「Unicode」而又不详细说明,这也是微软的习惯)

有上面可知,只要保证CSV文件是ANSI就可以了,在中文操作系统,文件格式指定GBK即可

在简体中文Windows操作系统中,ANSI 编码代表 GBK 编码;在繁体中文Windows操作系统中,ANSI编码代表Big5;在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码

但是有一天客户跟我们说,他的英文操作系统打开CSV出现了乱码

这时候可以采用UTF-8(有BOM)存储CSV文件,在java中指定UTF-8都是有BOM,需要自己转换

public void utf2bom(File file) throws IOException {
        byte[] content = FileUtils.readFileToByteArray(file);

        byte[] bomContent = new byte[content.length + 3];
        bomContent[0] = (byte) 0xEF; 
        bomContent[1] = (byte) 0xBB; 
        bomContent[2] = (byte) 0xBF;

        System.arraycopy(content, 0, bomContent, 3, content.length);

        FileUtils.writeByteArrayToFile(file, bomContent);
}

客户端调用,这样你储存的文件就是UTF-8 with BOM,就不会受操作系统环境的影响了

File file = new File(excelDir + fullName);
OutputStreamWriter fwriter = new OutputStreamWriter(  
        new FileOutputStream(file), "UTF-8");
//转换utf-8 bom
utf2bom(file);        

CSV文件中包数字,转义

  • CSV用逗号隔开数据,用换行符产生一行一行的数据, 逗号就是第一个特殊字符,如果数据内容中出现了逗号,就要用半角双引把数据内容包起来,所以比如数据是 xilang,yan, 就要改成 “xilang,yan”。第二个特殊字符就是引号:”,数据中如果有引号,就要换成两个引号,比如xilang”yan要转义为xilang””yan。
  • 如果数据是存数字,并且第一个是0, 在excel下不会显示出来,解决方法就是,先用引号把数据包起来,再在数据前加一等号,比如:0123456就变成=”0123456″。但是这种解决方法有限,如果自己内容很长的话,也不能正确显示,不过还好,正常情况下,数字应该不会很长

Python面向对象(七)

在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)

#任何类都是继承自object
class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age


    def printPerson(self):
        print('%s is %d years old'%(self.name,self.age))

per = Person('Mike',54)
per.printPerson()

#类如何去实现继承关系
#一个学生是一个人,而且应该有成绩

#直接继承Person类,不实现任何方法
"""
class Student(Person):
    pass
"""

class Student(Person):
    def __init__(self, name, age, score):
        Person.__init__(self, name, age) #初始化父类构造器
        self.score = score
        self.__id = '123456'             #属性私有化

    def printScore(self):
        #Person.printPerson(self) #调用父类方法
        print('%s\'s score is %d' % (self.name,self.score))

    #getter setter方法

    def set_id(self, id):
        self.__id = id

    def get_id(self):
        return self.__id

stu = Student('Jim',13,98)   

stu.printPerson()
stu.printScore()

#外部可以访问属性
print(stu.score)

#print(stu.__id)
"""
访问私有变量会抛出异常
Traceback (most recent call last):
  File "oo.py", line 51, in <module>
    print(stu.__id)
AttributeError: 'Student' object has no attribute '__id'
"""
#设置值之前
print(stu.get_id())
stu.set_id('987654')
#设置值之后
print(stu.get_id())
小结

继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写。