<repo_name>mutongliwansui/JavaLearning01<file_sep>/src/main/java/com/mutongli/concurrent/item/OrderDelayItem.java
package com.mutongli.concurrent.item;

import org.apache.log4j.Logger;
import org.junit.Test;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public class OrderDelayItem  implements Delayed {

    private static final Logger LOGGER = Logger.getLogger(OrderDelayItem.class);

    private String ordercode; //订单编码
    private long exptime; //过期时间(豪秒)
    private long createtime; //创建时间(毫秒)
    private static final TimeUnit DEFAULT_TIMEUNIT = TimeUnit.MILLISECONDS;
    public static final String DEFAULT_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    private OrderDelayItem() {
    }
    /**
     * 创建订单项，并赋予创建时间和过期时间
     * @param ordercode 订单号
     * @param exptime 过期时间
     * @param unit 过期时间单位
     * @param date 创建时间
     * @return
     */
    public static OrderDelayItem newInstance(String ordercode, long exptime, TimeUnit unit, Date date){
        OrderDelayItem item = new OrderDelayItem();
        item.setOrdercode(ordercode);
        item.setCreatetime(date.getTime());
        item.setExptime(DEFAULT_TIMEUNIT.convert(exptime,unit) +  item.createtime);
        return item;
    }
    /**
     * 创建订单项，并赋予创建时间和过期时间
     * @param ordercode 订单号
     * @param exptime 过期时间
     * @param unit 过期时间单位
     * @param createtime 创建时间
     * @param pattern 创建时间格式(默认yyyy-mm-dd hh:mi:ss)
     * @return
     */
    public static OrderDelayItem newInstance(String ordercode, long exptime, TimeUnit unit, String createtime, String pattern){
        OrderDelayItem item = null;
        try {
            DateFormat format = new SimpleDateFormat(pattern);
            Date date = format.parse(createtime);
            item = newInstance(ordercode,exptime,unit,date);
        } catch (ParseException e) {
            LOGGER.error("parse createtime failed",e);
        }finally {
            return item;
        }
    }

    /**
     * 创建订单项，并赋予创建时间和过期时间
     * @param ordercode 订单号
     * @param exptime 过期时间
     * @param unit 过期时间单位
     * @param createtime 创建时间(默认格式yyyy-mm-dd)
     * @return
     */
    public static OrderDelayItem newInstance(String ordercode, long exptime, TimeUnit unit, String createtime){
        return newInstance(ordercode,exptime,unit,createtime,DEFAULT_TIME_PATTERN);
    }

    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(this.exptime - System.currentTimeMillis(),DEFAULT_TIMEUNIT);
    }

    @Override
    public int compareTo(Delayed o) {
        return Long.valueOf(this.exptime).compareTo(Long.valueOf(((OrderDelayItem)o).getExptime()));
    }

    public String getOrdercode() {
        return ordercode;
    }

    public void setOrdercode(String ordercode) {
        this.ordercode = ordercode;
    }

    public long getExptime() {
        return exptime;
    }

    public void setExptime(long exptime) {
        this.exptime = exptime;
    }

    public long getCreatetime() {
        return createtime;
    }

    public void setCreatetime(long createtime) {
        this.createtime = createtime;
    }
}
<file_sep>/src/main/java/com/mutongli/hash/LrnHashMap.java
package com.mutongli.hash;

import java.util.HashMap;
import java.util.Map;

/**
 * @author mtl
 * @Description: HashMap学习
 * @date 2019/7/30 17:26
 */
public class LrnHashMap {
    public void testPutReturn(){
        HashMap hb = new HashMap();
        Object rt1 = hb.put("123","345"); //HashMap的put方法返回的是之前的值,此时hb是第一次存入key="123",所以之前的值为空
        System.out.println(rt1);
        Object rt2 = hb.put("123","456"); //此时是第二次存入key="123",所以之前的值是345
        System.out.println(rt2);
    }

    public static void main(String[] args) {
        new LrnHashMap().testPutReturn();
    }
}
<file_sep>/src/main/java/com/mutongli/innerclass/AnonymousInnerDemo.java
package com.mutongli.innerclass;

/**
 * @author mtl
 * @Description: 匿名内部类
 * @date 2019/7/29 21:50
 */
public class AnonymousInnerDemo {
    public void setInf(Interface inf){
        inf.method();
    }

    public void test(final int a,int b){
//        b = 5; //如果对b没有改变值，则匿名内部类可以访问该变量，等同于被final修饰,如果改变了b的值，则匿名内部类访问该变量会编译报错
        int c = 0;
//        c = 3; //与变量b相同
        this.setInf(new Interface() {
            @Override
            public void method() {
                System.out.println("param1:"+a);
                System.out.println("param2:"+b); //匿名内部类只能访问外部的常量(被final修饰，或者在外部除了定义时赋值，后续没有再改变值的)
                System.out.println("param3:"+c);
                System.out.println("test => setInf => method");
            }
        });
    }

    public static void main(String[] args) {
        new AnonymousInnerDemo().test(1,2);
    }
}

interface Interface{
    void method();
}
<file_sep>/src/main/java/com/mutongli/inf/TestBed.java
package com.mutongli.inf;

public interface TestBed {
    public void fun();
    class TestInner{

    }
}
<file_sep>/src/main/java/com/mutongli/innerclass/StaticInnerDemo.java
package com.mutongli.innerclass;

/**
 * @author mtl
 * @Description: 静态内部类
 * @date 2019/7/29 21:25
 */
public class StaticInnerDemo {

    private String name;
    private static String password = "123";

    private static void printPassword(){
        System.out.println("outter:" + password);
    }

    private void printName(){
        System.out.println("outter:"+name);
    }

    static class Inner{
        public void test(){
//            System.out.println(StaticInnerDemo.this.name); //静态内部类无法访问外部类的非静态成员变量或者方法
            System.out.println(password); //可以访问外部类的静态变量和静态方法
//            StaticInnerDemo.this.printName();
            printPassword();
        }
        private static String password = "<PASSWORD>"; //静态内部类可以定义静态变量
        //静态内部类可以定义静态方法
        public static void testStatic(){
            System.out.println(password);
            System.out.println(StaticInnerDemo.password);
        }
    }

    public static void main(String[] args) {
        new StaticInnerDemo.Inner().test(); //静态内部类创建不需要依赖外部类对象，直接new 外部类名.内部类名()就可以创建了
    }
}
<file_sep>/src/main/java/com/mutongli/TestNioSocket.java
package com.mutongli;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;

public class TestNioSocket {
    public static void main(String[] args) {
        try {
            //创建ServerSocketChannel，监听8080端口
            ServerSocketChannel socketChannel = ServerSocketChannel.open();
            InetSocketAddress socketAddress = new InetSocketAddress(8080);
            socketChannel.socket().bind(socketAddress);
            //设置为非阻塞模式
            socketChannel.configureBlocking(false);
            //为socketChannel注册选择器
            Selector  selector = Selector.open();
            socketChannel.register(selector, SelectionKey.OP_ACCEPT);
            //创建处理器
            while (true){
                //等待请求，每次等待阻塞3s，超过3s后线程继续向下运行，如果传入0或者不传参数将一直阻塞
                if(selector.select(3000) == 0){
                    continue;
                }
                //获取待处理的SelectionKey
                Iterator<SelectionKey> keyiter = selector.selectedKeys().iterator();

                while (keyiter.hasNext()){
                    SelectionKey key = keyiter.next();
                    //启动新线程处理SelectionKey
                    HttpHandler handler = new HttpHandler(key);
                    //处理完后，从待处理的SelectionKey迭代器中移除当前使用的key
                    new Thread(handler).run();
                    keyiter.remove();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private static class HttpHandler implements Runnable{
        private int bufferSize = 1024;
        private String localCharset = "UTF-8";
        private SelectionKey key;

        public HttpHandler(SelectionKey key) {
            this.key = key;
        }

        public void handleAccept() throws IOException{
            SocketChannel cilentChannel = ((ServerSocketChannel)key.channel()).accept();
            cilentChannel.configureBlocking(false);
            cilentChannel.register(key.selector(),SelectionKey.OP_READ, ByteBuffer.allocate(bufferSize));
        }

        public void handleRead() throws IOException{
            //获取channel
            SocketChannel sc = (SocketChannel) key.channel();
            //获取buffer并重置
            ByteBuffer buffer = (ByteBuffer) key.attachment();
            buffer.clear();
            //没有读取到内容则关闭
            if(sc.read(buffer) == -1){
                sc.close();
            }else{
                //接收请求数据
                buffer.flip();
                String receivedStr = Charset.forName(localCharset).newDecoder().decode(buffer).toString();
                //控制台打印请求报文头
                String [] requestMessage = receivedStr.split("\r\n");
                for (String s :
                        requestMessage) {
                    System.out.println(s);
                    //遇到空行说明报文头已经打印完
                    if(s.isEmpty()){
                        break;
                    }
                }
                //控制台打印首行信息
                String [] firstLine = requestMessage[0].split(" ");
                System.out.println();
                System.out.println("Method:\t"+firstLine[0]);
                System.out.println("url:\t"+firstLine[1]);
                System.out.println("HTTP Version:\t"+firstLine[2]);
                System.out.println();

                //返回客户端
                StringBuilder sendStr = new StringBuilder();
                sendStr.append("HTTP/1.1 200 OK\r\n");
                sendStr.append("Content-Type:text/html;charset="+localCharset+"\r\n");
                sendStr.append("\r\n");

                sendStr.append("<html><head><title>显示报文</title></head><body>");
                sendStr.append("接收到请求报文是：</br>");
                for (String s :
                        requestMessage) {
                    sendStr.append(s + "<br/>");
                }
                sendStr.append("</body></html>");
                buffer = ByteBuffer.wrap(sendStr.toString().getBytes(localCharset));
                sc.write(buffer);
                sc.close();
            }
        }

        @Override
        public void run() {
                try {
                    //接收到连接请求时
                    if(key.isAcceptable()){
                            handleAccept();
                    }
                    //读数据
                    if(key.isReadable()){
                        handleRead();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }
}
<file_sep>/src/main/resources/log4j.properties
log4j.rootCategory=INFO, stdout , R

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=[JavaLearning01] %d %p %t %c - %m%n

log4j.appender.R=org.apache.log4j.DailyRollingFileAppender

log4j.appender.R.File=${catalina.home}/JavaLearning01/logs/log.txt

log4j.appender.R.layout=org.apache.log4j.PatternLayout
 
log4j.appender.R.DatePattern  ='.'yyyy-MM-dd

log4j.appender.R.layout.ConversionPattern=[JavaLearning01] %d- %p %t %c - %m%n

log4j.logger.com.halo=INFO

log4j.logger.org.hibernate=ERROR

log4j.logger.org.opensymphony=ERROR

log4j.logger.org.springframework=ERROR