最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

spring+netty服務(wù)器搭建的方法

 更新時間:2018年01月30日 14:28:53   作者:病毒先生  
本篇文章主要介紹了spring+netty服務(wù)器搭建的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

游戲一般是長連接,自定義協(xié)議,不用http協(xié)議,BIO,NIO,AIO這些我就不說了,自己查資料

我現(xiàn)在用spring+netty搭起簡單的游戲服

思路:1自定義協(xié)議和協(xié)議包;2spring+netty整合;3半包粘包處理,心跳機制等;4請求分發(fā)(目前自己搞的都是單例模式)
下個是測試用的,結(jié)構(gòu)如下

首先自定義包頭

Header.java

package com.test.netty.message;    
/** 
 * Header.java 
 * 自定義協(xié)議包頭 
 * @author janehuang 
 * @version 1.0 
 */  
public class Header {  
  private byte tag;  
 /* 編碼*/  
  private byte encode;  
  /*加密*/  
  private byte encrypt;  
  /*其他字段*/  
  private byte extend1;  
  /*其他2*/  
  private byte extend2;  
  /*會話id*/  
  private String sessionid;  
  /*包的長度*/  
  private int length = 1024;  
  /*命令*/  
  private int cammand;  
  
  public Header() {  
  
  }  
  
  public Header(String sessionid) {  
    this.encode = 0;  
    this.encrypt = 0;  
    this.sessionid = sessionid;  
  }  
  
  public Header(byte tag, byte encode, byte encrypt, byte extend1, byte extend2, String sessionid, int length, int cammand) {  
    this.tag = tag;  
    this.encode = encode;  
    this.encrypt = encrypt;  
    this.extend1 = extend1;  
    this.extend2 = extend2;  
    this.sessionid = sessionid;  
    this.length = length;  
    this.cammand = cammand;  
  }  
  
  @Override  
  public String toString() {  
    return "header [tag=" + tag + "encode=" + encode + ",encrypt=" + encrypt + ",extend1=" + extend1 + ",extend2=" + extend2 + ",sessionid=" + sessionid + ",length=" + length + ",cammand="  
        + cammand + "]";  
  }  
  
  public byte getTag() {  
    return tag;  
  }  
  
  public void setTag(byte tag) {  
    this.tag = tag;  
  }  
  
  public byte getEncode() {  
    return encode;  
  }  
  
  public void setEncode(byte encode) {  
    this.encode = encode;  
  }  
  
  public byte getEncrypt() {  
    return encrypt;  
  }  
  
  public void setEncrypt(byte encrypt) {  
    this.encrypt = encrypt;  
  }  
  
  public byte getExtend1() {  
    return extend1;  
  }  
  
  public void setExtend1(byte extend1) {  
    this.extend1 = extend1;  
  }  
  
  public byte getExtend2() {  
    return extend2;  
  }  
  
  public void setExtend2(byte extend2) {  
    this.extend2 = extend2;  
  }  
  
  public String getSessionid() {  
    return sessionid;  
  }  
  
  public void setSessionid(String sessionid) {  
    this.sessionid = sessionid;  
  }  
  
  public int getLength() {  
    return length;  
  }  
  
  public void setLength(int length) {  
    this.length = length;  
  }  
  
  public int getCammand() {  
    return cammand;  
  }  
  
  public void setCammand(int cammand) {  
    this.cammand = cammand;  
  }  
}  

包體,我簡單處理用字符串轉(zhuǎn)字節(jié)碼,一般好多游戲用probuf系列化成二進制

Message.java

package com.test.netty.message;    
import io.netty.buffer.ByteBuf;  
import io.netty.buffer.Unpooled;   
import java.io.ByteArrayOutputStream;  
import java.io.IOException;  
import java.io.UnsupportedEncodingException;   
import com.test.netty.decoder.MessageDecoder;   
/** 
 * Message.java 
 *  
 * @author janehuang 
 * @version 1.0 
 */  
public class Message {  
  
  private Header header;  
  
  private String data;  
  
  public Header getHeader() {  
    return header;  
  }  
  
  public void setHeader(Header header) {  
    this.header = header;  
  }  
  
  public String getData() {  
    return data;  
  }  
  
  public void setData(String data) {  
    this.data = data;  
  }  
  
  public Message(Header header) {  
    this.header = header;  
  }  
  
  public Message(Header header, String data) {  
    this.header = header;  
    this.data = data;  
  }  
  
  public byte[] toByte() {  
    ByteArrayOutputStream out = new ByteArrayOutputStream();  
    out.write(MessageDecoder.PACKAGE_TAG);  
    out.write(header.getEncode());  
    out.write(header.getEncrypt());  
    out.write(header.getExtend1());  
    out.write(header.getExtend2());  
    byte[] bb = new byte[32];  
    byte[] bb2 = header.getSessionid().getBytes();  
    for (int i = 0; i < bb2.length; i++) {  
      bb[i] = bb2[i];  
    }  
  
    try {  
      out.write(bb);  
  
      byte[] bbb = data.getBytes("UTF-8");  
      out.write(intToBytes2(bbb.length));  
      out.write(intToBytes2(header.getCammand()));  
      out.write(bbb);  
      out.write('\n');  
    } catch (UnsupportedEncodingException e) {  
      // TODO Auto-generated catch block  
      e.printStackTrace();  
    } catch (IOException e) {  
      // TODO Auto-generated catch block  
      e.printStackTrace();  
    }  
    return out.toByteArray();  
  }  
  
  public static byte[] intToByte(int newint) {  
    byte[] intbyte = new byte[4];  
    intbyte[3] = (byte) ((newint >> 24) & 0xFF);  
    intbyte[2] = (byte) ((newint >> 16) & 0xFF);  
    intbyte[1] = (byte) ((newint >> 8) & 0xFF);  
    intbyte[0] = (byte) (newint & 0xFF);  
    return intbyte;  
  }  
  
  public static int bytesToInt(byte[] src, int offset) {  
    int value;  
    value = (int) ((src[offset] & 0xFF) | ((src[offset + 1] & 0xFF) << 8) | ((src[offset + 2] & 0xFF) << 16) | ((src[offset + 3] & 0xFF) << 24));  
    return value;  
  }  
  
  public static byte[] intToBytes2(int value) {  
    byte[] src = new byte[4];  
    src[0] = (byte) ((value >> 24) & 0xFF);  
    src[1] = (byte) ((value >> 16) & 0xFF);  
    src[2] = (byte) ((value >> 8) & 0xFF);  
    src[3] = (byte) (value & 0xFF);  
    return src;  
  }  
  
  public static void main(String[] args) {  
    ByteBuf heapBuffer = Unpooled.buffer(8);  
    System.out.println(heapBuffer);  
    ByteArrayOutputStream out = new ByteArrayOutputStream();  
    try {  
      out.write(intToBytes2(1));  
    } catch (IOException e) {  
      // TODO Auto-generated catch block  
      e.printStackTrace();  
    }  
    byte[] data = out.toByteArray();  
    heapBuffer.writeBytes(data);  
    System.out.println(heapBuffer);  
    int a = heapBuffer.readInt();  
    System.out.println(a);  
  }    
}  

解碼器

MessageDecoder.java

package com.test.netty.decoder; 
import io.netty.buffer.ByteBuf; 
import io.netty.channel.ChannelHandlerContext; 
import io.netty.handler.codec.ByteToMessageDecoder; 
import io.netty.handler.codec.CorruptedFrameException;  
import java.util.List;  
import com.test.netty.message.Header; 
import com.test.netty.message.Message; 
/** 
 * HeaderDecoder.java 
 * 
 * @author janehuang 
 * @version 1.0 
 */ 
public class MessageDecoder extends ByteToMessageDecoder { 
  /**包長度志頭**/ 
  public static final int HEAD_LENGHT = 45; 
  /**標(biāo)志頭**/ 
  public static final byte PACKAGE_TAG = 0x01; 
  @Override 
  protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception { 
    buffer.markReaderIndex(); 
    if (buffer.readableBytes() < HEAD_LENGHT) { 
      throw new CorruptedFrameException("包長度問題"); 
    } 
    byte tag = buffer.readByte(); 
    if (tag != PACKAGE_TAG) { 
      throw new CorruptedFrameException("標(biāo)志錯誤"); 
    } 
    byte encode = buffer.readByte(); 
    byte encrypt = buffer.readByte(); 
    byte extend1 = buffer.readByte(); 
    byte extend2 = buffer.readByte(); 
    byte sessionByte[] = new byte[32]; 
    buffer.readBytes(sessionByte); 
    String sessionid = new String(sessionByte,"UTF-8"); 
    int length = buffer.readInt(); 
    int cammand=buffer.readInt(); 
    Header header = new Header(tag,encode, encrypt, extend1, extend2, sessionid, length, cammand); 
    byte[] data=new byte[length]; 
    buffer.readBytes(data); 
    Message message = new Message(header,new String(data,"UTF-8")); 
    out.add(message); 
  } 
} 

編碼器

MessageEncoder.java

package com.test.netty.encoder; 
import com.test.netty.decoder.MessageDecoder; 
import com.test.netty.message.Header; 
import com.test.netty.message.Message;  
import io.netty.buffer.ByteBuf; 
import io.netty.channel.ChannelHandlerContext; 
import io.netty.handler.codec.MessageToByteEncoder;   
/** 
 * MessageEncoder.java 
 * 
 * @author janehuang 
 * @version 1.0 
 */ 
public class MessageEncoder extends MessageToByteEncoder<Message> {  
  @Override 
  protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception { 
      Header header = msg.getHeader(); 
      out.writeByte(MessageDecoder.PACKAGE_TAG); 
      out.writeByte(header.getEncode()); 
      out.writeByte(header.getEncrypt()); 
      out.writeByte(header.getExtend1()); 
      out.writeByte(header.getExtend2()); 
      out.writeBytes(header.getSessionid().getBytes()); 
      out.writeInt(header.getLength()); 
      out.writeInt(header.getCammand()); 
      out.writeBytes(msg.getData().getBytes("UTF-8")); 
  }  
} 

服務(wù)器

TimeServer.java

package com.test.netty.server; 
import org.springframework.stereotype.Component; 
import io.netty.bootstrap.ServerBootstrap; 
import io.netty.buffer.ByteBuf; 
import io.netty.buffer.Unpooled; 
import io.netty.channel.ChannelFuture; 
import io.netty.channel.ChannelInitializer; 
import io.netty.channel.ChannelOption; 
import io.netty.channel.EventLoopGroup; 
import io.netty.channel.nio.NioEventLoopGroup; 
import io.netty.channel.socket.SocketChannel; 
import io.netty.channel.socket.nio.NioServerSocketChannel; 
import io.netty.handler.codec.LineBasedFrameDecoder;  
import com.test.netty.decoder.MessageDecoder; 
import com.test.netty.encoder.MessageEncoder; 
import com.test.netty.handler.ServerHandler; 
/** 
 * ChatServer.java 
 * 
 * @author janehuang 
 * @version 1.0 
 */ 
@Component 
public class TimeServer {  
  private int port=88888; 
  public void run() throws InterruptedException { 
    EventLoopGroup bossGroup = new NioEventLoopGroup(); 
    EventLoopGroup workerGroup = new NioEventLoopGroup(); 
    ByteBuf heapBuffer = Unpooled.buffer(8); 
    heapBuffer.writeBytes("\r".getBytes()); 
    try { 
      ServerBootstrap b = new ServerBootstrap(); // (2) 
      b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) // (3) 
          .childHandler(new ChannelInitializer<SocketChannel>() { // (4) 
                @Override 
                public void initChannel(SocketChannel ch) throws Exception { 
                  ch.pipeline().addLast("encoder", new MessageEncoder()).addLast("decoder", new MessageDecoder()).addFirst(new LineBasedFrameDecoder(65535)) 
                      .addLast(new ServerHandler()); 
                } 
              }).option(ChannelOption.SO_BACKLOG, 1024) // (5) 
          .childOption(ChannelOption.SO_KEEPALIVE, true); // (6) 
      ChannelFuture f = b.bind(port).sync(); // (7) 
      f.channel().closeFuture().sync(); 
    } finally { 
      workerGroup.shutdownGracefully(); 
      bossGroup.shutdownGracefully(); 
    } 
  } 
   
  public void start(int port) throws InterruptedException{ 
   this.port=port; 
   this.run(); 
  }  
} 

處理器并分發(fā)

ServerHandler.java

package com.test.netty.handler;  
import io.netty.channel.ChannelHandlerAdapter; 
import io.netty.channel.ChannelHandlerContext;  
import com.test.netty.invote.ActionMapUtil; 
import com.test.netty.message.Header; 
import com.test.netty.message.Message; 
/** 
 * 
 * @author janehuang 
 * 
 */ 
public class ServerHandler extends ChannelHandlerAdapter { 

  @Override 
  public void channelActive(ChannelHandlerContext ctx) throws Exception { 
    String content="我收到連接"; 
    Header header=new Header((byte)0, (byte)1, (byte)1, (byte)1, (byte)0, "713f17ca614361fb257dc6741332caf2",content.getBytes("UTF-8").length, 1); 
    Message message=new Message(header,content); 
    ctx.writeAndFlush(message);      
  } 
 
  @Override 
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 
    cause.printStackTrace(); 
    ctx.close(); 
  } 
 
  @Override 
  public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 
     Message m = (Message) msg; // (1) 
      
    /* 請求分發(fā)*/ 
    ActionMapUtil.invote(header.getCammand(),ctx, m); 
  }      
} 

分發(fā)工具類

ActionMapUtil.java

package com.test.netty.invote; 
import java.lang.reflect.Method; 
import java.util.HashMap; 
import java.util.Map; 
public class ActionMapUtil { 
  private static Map<Integer, Action> map = new HashMap<Integer, Action>();  
  public static Object invote(Integer key, Object... args) throws Exception { 
    Action action = map.get(key); 
    if (action != null) { 
      Method method = action.getMethod(); 
      try { 
        return method.invoke(action.getObject(), args); 
      } catch (Exception e) { 
        throw e; 
      } 
    } 
    return null; 
  }  
  public static void put(Integer key, Action action) { 
    map.put(key, action); 
  }  
} 

為分發(fā)創(chuàng)建的對象

Action.java

package com.test.netty.invote;  
import java.lang.reflect.Method;  
public class Action {    
  private Method method; 
  private Object object;  
  public Method getMethod() { 
    return method; 
  } 
 
  public void setMethod(Method method) { 
    this.method = method; 
  } 
 
  public Object getObject() { 
    return object; 
  } 
 
  public void setObject(Object object) { 
    this.object = object; 
  } 
} 

自定義注解,類似springmvc 里面的@Controller

NettyController.java

package com.test.netty.core;  
import java.lang.annotation.Documented; 
import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target;  
import org.springframework.stereotype.Component;  
@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.TYPE) 
@Documented 
@Component 
public @interface NettyController { 
} 

類型spring mvc里面的@ReqestMapping

ActionMap.java

package com.test.netty.core; 
import java.lang.annotation.Documented; 
import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target;  
@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.METHOD) 
@Documented 
public @interface ActionMap { 
    int key();     
} 

加了這些注解是為了spring初始化bean后把這些對象存到容器,此bean需要在spring配置,spring bean 實例化后會調(diào)用

ActionBeanPostProcessor.java

package com.test.netty.core; 
import java.lang.reflect.Method; 
import org.springframework.beans.BeansException; 
import org.springframework.beans.factory.config.BeanPostProcessor; 
import com.test.netty.invote.Action; 
import com.test.netty.invote.ActionMapUtil; 
public class ActionBeanPostProcessor implements BeanPostProcessor { 
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 
    return bean; 
  } 
 
  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 
    Method[] methods=bean.getClass().getMethods(); 
    for (Method method : methods) { 
      ActionMap actionMap=method.getAnnotation(ActionMap.class); 
      if(actionMap!=null){ 
        Action action=new Action(); 
        action.setMethod(method); 
        action.setObject(bean); 
        ActionMapUtil.put(actionMap.key(), action); 
      } 
    } 
    return bean; 
  } 
} 

controller實例

UserController.java

package com.test.netty.controller;  
import io.netty.channel.ChannelHandlerContext;  
import org.springframework.beans.factory.annotation.Autowired; 
import com.test.model.UserModel; 
import com.test.netty.core.ActionMap; 
import com.test.netty.core.NettyController; 
import com.test.netty.message.Message; 
import com.test.service.UserService; 
 
@NettyController() 
public class UserAction { 

  @Autowired 
  private UserService userService; 
   
  @ActionMap(key=1) 
  public String login(ChannelHandlerContext ct,Message message){ 
    UserModel userModel=this.userService.findByMasterUserId(1000001); 
    System.out.println(String.format("用戶昵稱:%s;密碼%d;傳人內(nèi)容%s", userModel.getNickname(),userModel.getId(),message.getData())); 
    return userModel.getNickname(); 
  }  
} 

applicationContext.xml配置文件記得加入這個

<bean class="com.test.netty.core.ActionBeanPostProcessor"/> 

測試代碼

package test; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.support.ClassPathXmlApplicationContext; 
import com.test.netty.server.TimeServer; 
public class Test { 
  public static void main(String[] args) { 
     ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");  
     TimeServer timeServer= ac.getBean(TimeServer.class); 
     try { 
      timeServer.start(8888); 
    } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
    } 
  } 
} 

測試開關(guān)端

package test;  
import java.io.IOException; 
import java.io.OutputStream; 
import java.net.Socket; 
import java.util.Scanner; 
import com.test.netty.message.Header; 
import com.test.netty.message.Message;  
public class ClientTest { 
   public static void main(String[] args) { 
    try { 
      // 連接到服務(wù)器 
      Socket socket = new Socket("127.0.0.1", 8888);  
      try { 
        // 向服務(wù)器端發(fā)送信息的DataOutputStream 
        OutputStream out = socket.getOutputStream(); 
        // 裝飾標(biāo)準(zhǔn)輸入流,用于從控制臺輸入 
        Scanner scanner = new Scanner(System.in); 
        while (true) { 
          String send = scanner.nextLine(); 
          System.out.println("客戶端:" + send); 
          byte[] by = send.getBytes("UTF-8"); 
          Header header = new Header((byte) 1, (byte) 1, (byte) 1, (byte) 1, (byte) 1, "713f17ca614361fb257dc6741332caf2", by.length, 1); 
          Message message = new Message(header, send); 
          out.write(message.toByte()); 
          out.flush(); 
          // 把從控制臺得到的信息傳送給服務(wù)器 
          // out.writeUTF("客戶端:" + send); 
          // 讀取來自服務(wù)器的信息 
        } 
 
      } finally { 
        socket.close(); 
      } 
    } catch (IOException e) { 
      e.printStackTrace(); 
    } 
  } 
} 

測試結(jié)果,ok了

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • mybatis/mybatis-plus模糊查詢語句特殊字符轉(zhuǎn)義攔截器的實現(xiàn)

    mybatis/mybatis-plus模糊查詢語句特殊字符轉(zhuǎn)義攔截器的實現(xiàn)

    在開發(fā)中,我們通常會遇到這樣的情況。用戶在錄入信息是錄入了‘%’,而在查詢時無法精確匹配‘%’。究其原因,‘%’是MySQL的關(guān)鍵字,如果我們想要精確匹配‘%’,那么需要對其進行轉(zhuǎn)義,本文就詳細的介紹一下
    2021-11-11
  • Intellij?IDEA如何查看所有斷點

    Intellij?IDEA如何查看所有斷點

    這篇文章主要介紹了Intellij?IDEA如何查看所有斷點問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 詳解springboot接口如何優(yōu)雅的接收時間類型參數(shù)

    詳解springboot接口如何優(yōu)雅的接收時間類型參數(shù)

    這篇文章主要為大家詳細介紹了springboot的接口如何優(yōu)雅的接收時間類型參數(shù),文中為大家整理了三種常見的方法,希望對大家有一定的幫助
    2023-09-09
  • Maven 項目生成jar運行時提示“沒有主清單屬性”

    Maven 項目生成jar運行時提示“沒有主清單屬性”

    這篇文章主要介紹了Maven 項目生成jar運行時提示“沒有主清單屬性”,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • Mybatis中自定義實例化SqlSessionFactoryBean問題

    Mybatis中自定義實例化SqlSessionFactoryBean問題

    這篇文章主要介紹了Mybatis中自定義實例化SqlSessionFactoryBean問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 教你輕松制作java視頻播放器

    教你輕松制作java視頻播放器

    這篇文章主要為大家詳細介紹了如何編寫屬于自己的java視頻播放器,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • MyBatis-Plus動態(tài)表名的使用

    MyBatis-Plus動態(tài)表名的使用

    本文主要介紹了MyBatis-Plus動態(tài)表名的使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • SpringBoot整合weixin-java-pay實現(xiàn)微信小程序支付的示例代碼

    SpringBoot整合weixin-java-pay實現(xiàn)微信小程序支付的示例代碼

    微信小程序支付是常見的一種功能,本文主要介紹了SpringBoot整合weixin-java-pay實現(xiàn)微信小程序支付的示例代碼,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-05-05
  • Java定時調(diào)用.ktr文件的示例代碼(解決方案)

    Java定時調(diào)用.ktr文件的示例代碼(解決方案)

    這篇文章主要介紹了Java定時調(diào)用.ktr文件的示例代碼,本文給大家分享遇到問題及解決方法,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • Mybatis單個參數(shù)的if判斷報異常There is no getter for property named ''xxx'' in ''class java.lang.Integer''的解決方案

    Mybatis單個參數(shù)的if判斷報異常There is no getter for property named ''x

    今天小編就為大家分享一篇關(guān)于Mybatis單個參數(shù)的if判斷報異常There is no getter for property named 'xxx' in 'class java.lang.Integer'的解決方案,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12

最新評論

汕尾市| 西城区| 巴彦淖尔市| 南城县| 东辽县| 池州市| 古丈县| 浦城县| 英吉沙县| 平遥县| 太白县| 宜城市| 济宁市| 鹤山市| 读书| 湖南省| 永泰县| 益阳市| 海门市| 神农架林区| 寿光市| 田阳县| 淮阳县| 萨嘎县| 桓仁| 随州市| 岗巴县| 班戈县| 兴隆县| 赣州市| 安宁市| 德江县| 江山市| 合阳县| 读书| 花垣县| 镶黄旗| 泊头市| 兰考县| 宁安市| 霍城县|