还不会SpringBoot项目模块分层?来这手把手教你
前言缘由
经常看到网上很多优秀的开源项目中,代码简洁,模块分层完美。反观自己代码层级混乱,,却不知如何整理分层。此文手把手教你一步一步创建模块,左手右手一个慢动作。结合本人实际开发及个人项目中分层思路的分享,大神请勿喷。主要目标熟练掌握SpringBoot项目分层思路,丝滑拆分模块熟悉代码层级依赖,规范化管理模块分布手把手实战学习,理论实践相结合试用人群对于Springboot熟悉但是不知道合理分层小白有自己分层思路可以互相分享学习水图
下图反面教材,传统单体应用,结构臃肿
下图分层截选自本人的一个小项目,模块清晰,分工明确
我们要实现的小栗子的分层
正文1.IDEA新建项目
起名第一步,一个好名字,说不定是个好的开始
假如我们的项目是个聊天相关的项目,英文对应chat,所以定义项目名为chat-boot,其他的以此效仿
点击New->project
选择Maven项目,并选择合适JDK版本,点击Next
录入项目名称,并填写GAV坐标,点击Finish
删除无用文件及目录,如src目录和*.iml文件
删除后项目目录
修改pom.xml中依赖,增加spring-boot-starter-parent org.springframework.boot spring-boot-starter-parent 2.3.1.RELEASE 复制代码
2.创建子模块-dependencies(依赖层)
右击项目chat-boot,new ->Moudle新建模块chat-boot-dependencies
选择对应Module SDK版本,本人选择jdk1.8
填写子模块名 chat-boot-dependencies,然后检查对应GAV,点击Finish
生成子模块chat-boot-dependencies如下图
删除chat-boot-dependencies下无用文件及目录,如src目录,删除无用目录如下
完善chat-boot-dependencies下pom.xml依赖, 常用依赖放入,作为依赖主体,以下是本狗常用依赖,可酌情选择;记得把packaging改为pom<?xml version="1.0" encoding="UTF-8"?> chat-boot net.javadog.chat 1.0-SNAPSHOT 4.0.0 chat-dependencies pom 8 8 UTF-8 UTF-8 8.0.17 1.1.21 3.4.1 1.2.75 5.5.8 1.18.12 4.2.0 2.9.2 2.9.2 2.0.4 4.4.5.B 1.3.2 3.2.0 com.baomidou mybatis-plus-boot-starter ${mybatis-plus.version} mysql mysql-connector-java ${mysql-connector-java.version} com.alibaba druid ${druid.version} com.alibaba fastjson ${fastjson.version} cn.hutool hutool-all ${hutool.version} org.projectlombok lombok ${lombok.versin} io.springfox springfox-swagger2 ${springfox-swagger2.version} io.springfox springfox-swagger-ui ${springfox-swagger-ui.version} com.github.xiaoymin knife4j-spring-boot-starter ${knife4j.version} cn.afterturn easypoi-base ${easypoi.version} com.github.binarywang weixin-java-miniapp ${weixin.version} org.apache.shiro shiro-spring ${shiro.version} com.auth0 java-jwt ${jwt.version} 复制代码重点
此处用的标签是 dependencyManagement,
dependencyManagement只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。3.创建子模块-main(主启动层)
右击项目chat-boot,new ->Moudle新建模块chat-boot-main
选择对应Module SDK版本,本狗选择jdk1.8,点击Next
填写子模块名 chat-boot-main,然后检查对应GAV,点击Finish
生成子模块chat-boot-main如下图
完善chat-boot-main模块下pom.xml中依赖引入必要依赖完善profiles标签中环境相关配置build标签中插件<?xml version="1.0" encoding="UTF-8"?> chat-boot net.javadog.chat 1.0-SNAPSHOT 4.0.0 chat-boot-main 8 8 net.javadog.chat chat-boot-dependencies 1.0-SNAPSHOT pom import org.springframework.boot spring-boot-starter-web org.projectlombok lombok io.springfox springfox-swagger2 io.springfox springfox-swagger-ui com.github.xiaoymin knife4j-spring-boot-starter chat org.springframework.boot spring-boot-maven-plugin repackage true src/main/webapp false src/main/resources true src/main/java **/*.xml local local true dev dev prod prod 复制代码重点配置引入依赖chat-boot-dependencies,用作此模块依赖引入 net.javadog.chat chat-boot-dependencies 1.0-SNAPSHOT pom import 复制代码配置build标签用于完善插件plugins,其中包含maven-compiler-plugin和maven-resources-plugin org.apache.maven.plugins maven-compiler-plugin 3.1 ${java.version} org.apache.maven.plugins maven-resources-plugin 2.6 @ false src/main/webapp false src/main/resources true src/main/java **/*.xml 复制代码配置profiles环境变量标签,用于方便打包切换,本狗设置了 local、dev、prod三种环境 local local true dev dev prod prod 复制代码
操作可在IDEA右上角方便切换环境
切记一定主动Reload一下Maven依赖 切记一定主动Reload一下Maven依赖 切记一定主动Reload一下Maven依赖
在chat-boot-main模块中加入启动类,在src/main/java下右键New=>Java Class
录入启动类名ChatApplication
完善ChatApplication启动类代码package net.javadog.chat; import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.Environment; import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.net.InetAddress; import java.net.UnknownHostException; /** * @author: hdx * @Date: 2023-01-28 11:24 * @version: 1.0 **/ @SpringBootApplication @ServletComponentScan @Slf4j @EnableSwagger2 @EnableKnife4j public class ChatApplication { public static void main(String[] args) throws UnknownHostException { // 启动类 ConfigurableApplicationContext application = SpringApplication.run(ChatApplication.class, args); // 打印基础信息 info(application); } static void info(ConfigurableApplicationContext application) throws UnknownHostException { Environment env = application.getEnvironment(); String ip = InetAddress.getLocalHost().getHostAddress(); String port = env.getProperty("server.port"); String active = env.getProperty("spring.profiles.active"); String contextPath = env.getProperty("server.servlet.context-path"); if (contextPath == null) { contextPath = ""; } log.info(" ---------------------------------------------------------- " + "欢迎访问 https://blog.javadog.net " + "示例程序【" + active + "】环境已启动! 地址如下: " + "Local: http://localhost:" + port + contextPath + " " + "External: http://" + ip + ":" + port + contextPath + " " + "Swagger文档: http://" + ip + ":" + port + contextPath + "/doc.html " + "----------------------------------------------------------"); } } 复制代码
配置application.yml文件
application.yml#============================# # server 配置 #============================# server: port: 82 max-http-header-size: 10240 servlet: context-path: /chat/v1 #============================# # spring 配置 #============================# spring: application: # 应用名 name: chat profiles: active: @spring.active@ servlet: multipart: max-request-size: 100MB max-file-size: 100MB jackson: time-zone: GMT+8 date-format: yyyy-MM-dd HH:mm:ss.SSS locale: zh_CN serialization: # 格式化输出 indent_output: false main: allow-circular-references: true #解决swagger版本路径不兼容问题 mvc: pathmatch: matching-strategy: ant_path_matcher #============================# # mybatisplus 配置 #============================# mybatis-plus: mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true cache-enabled: true lazy-loading-enabled: true multiple-result-sets-enabled: true log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl global-config: banner: false db-config: id-type: assign_id table-underline: true enable-sql-runner: true #数据库类型 db-type: MYSQL configuration-properties: prefix: #如果数据库为postgresql,则需要配置为blobType: BINARY blobType: BLOB #如果数据库为oracle或mssql,则需要配置为boolValue: 1 boolValue: true #============================# # logging 配置 #============================# logging: level: root: info file: path: /root/javadog/chat/logs/${spring.application.name}/ name: ${spring.application.name} logback: rollingpolicy: max-history: 7 max-file-size: 10MB #============================# # file 配置 #============================# file: # 静态附件前缀 static-prefix: attach # 上传的文件对外暴露的访问路径 access-path-pattern: /${file.static-prefix}/** # 文件上传目录 upload-folder: /root/javadog/chat/ # 文件上传最大 max-post-size: 10 复制代码
application-local.yml#服务配置 server: port: 8001 max-http-header-size: 10240 # Mysql数据库 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/chat-boot?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=CONVERT_TO_NULL&useSSL=false&serverTimezone=CTT&nullCatalogMeansCurrent=true username: root password: root redis: host: localhost port: 6379 password: 复制代码
application-dev.yml#服务配置 server: port: 7001 max-http-header-size: 10240 # mybatisplus 配置 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 复制代码
application-prod.yml#服务配置 server: port: 8005 复制代码
顺便加一下logback-spring.xml 日志文件<?xml version="1.0" encoding="UTF-8" ?> ${application.name} ${CONSOLE_LOG_PATTERN} ${logging.path}/info/${application.name}-info.log ${logging.path}/info/${application.name}-info.%d{yyyy-MM-dd}.%i.log ${logging.file.max-size} ${logging.file.max-history} true ${FILE_LOG_PATTERN} warn ACCEPT DENY ${logging.path}/warn/${application.name}-warn.log ${logging.path}$/warn/${application.name}-warn.%d{yyyy-MM-dd}.%i.log ${logging.file.max-size} ${logging.file.max-history} ${FILE_LOG_PATTERN} error ACCEPT DENY ${logging.path}/error/${application.name}-error.log ${logging.path}/error/${application.name}-error.%d{yyyy-MM-dd}.%i.log ${logging.file.max-size} ${logging.file.max-history} ${FILE_LOG_PATTERN} 复制代码
启动一下项目试试,启动如下证明成功。如果报错少依赖请再拉一下Maven依赖!!!
4.创建子模块-module(模块层)
右击项目chat-boot,new ->Moudle新建模块chat-boot-module
填写子模块名 chat-boot-module,然后检查对应GAV,点击Finish
生成子模块chat-boot-module如下图
删除chat-boot-module下无用文件及目录,如src目录,删除无用目录如下
自此外部大框架初步搭建成功
完善chat-boot-module下pom.xml依赖,如lombok,web等必要依赖<?xml version="1.0" encoding="UTF-8"?> chat-boot net.javadog.chat 1.0-SNAPSHOT 4.0.0 chat-boot-module pom chat-boot-common chat-boot-controller chat-boot-dao chat-boot-dto chat-boot-entity chat-boot-service 8 8 net.javadog.chat chat-boot-dependencies ${project.parent.version} pom import org.springframework.boot spring-boot-starter-web com.github.binarywang weixin-java-miniapp org.projectlombok lombok cn.hutool hutool-all io.springfox springfox-swagger2 io.springfox springfox-swagger-ui com.github.xiaoymin knife4j-spring-boot-starter org.apache.shiro shiro-spring com.auth0 java-jwt com.baomidou mybatis-plus-boot-starter mysql mysql-connector-java 复制代码
一定要重新拉取依赖! 一定要重新拉取依赖! 一定要重新拉取依赖!
5.创建chat-boot-module模块下对应功能分层
目前本狗分为如下6层common-共通层controller-控制器层dao-数据持久层dto-数据传输对象层entity-实体层service-业务逻辑层
依次按照上述添加模块方式进行新增子模块,本狗如下示例一个,其余都如法炮制
右击项目chat-boot-module,new ->Moudle新建模块chat-boot-common
一定看清楚父模块是否正确 一定看清楚父模块是否正确 一定看清楚父模块是否正确
确认父级模块后,点击Finish,生成chat-boot-common模块
依次按照上述方法,新建其他模块
chat-boot-controller模块
chat-boot-dao模块
chat-boot-dto模块
chat-boot-entity模块
chat-boot-service模块
总体模块雏形基本完成
6.实际流程填充模拟正常前端请求到后台服务调用过程,进行实际代码补充
在chat-boot-entity下新建实体类User,在src/main/java下右键New=>Java Class,录入包名及类名
package net.javadog.chat.entity; import lombok.Data; /** * @author: hdx * @Date: 2023-01-28 14:26 * @version: 1.0 **/ @Data public class User { private Long id; private String username; private String idCard; } 复制代码
在chat-boot-dto下新建目request和response,分别代表请求传输对象和返回传输对象,并分别在目录下创建UserRequest.java和UserResponse.java
package net.javadog.chat.request; import lombok.Data; /** * @author: hdx * @Date: 2023-01-28 14:59 * @version: 1.0 **/ @Data public class UserRequest { private Long id; private String username; } 复制代码package net.javadog.chat.response; import lombok.Data; /** * @author: hdx * @Date: 2023-01-28 14:59 * @version: 1.0 **/ @Data public class UserResponse { private Long id; private String username; } 复制代码
在chat-boot-dao下修改chat-boot-dao模块下修改pom.xml文件依赖,引入chat-boot-entity;并增对应UserMapper.javapackage net.javadog.chat.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import net.javadog.chat.entity.User; /** * 用户mapper * * @author: hdx * @Date: 2023-01-10 11:43 * @version: 1.0 **/ public interface UserMapper extends BaseMapper { } 复制代码<?xml version="1.0" encoding="UTF-8"?> chat-boot-module net.javadog.chat 1.0-SNAPSHOT 4.0.0 chat-boot-dao 8 8 net.javadog.chat chat-boot-entity ${project.parent.version} 复制代码
在chat-boot-service下新建目录service和impl,并在对应目录下新建UserService.java和UserServiceImpl.java,并修改chat-boot-service模块下修改pom.xml文件依赖,引入chat-boot-dto,chat-boot-dao
package net.javadog.chat.service; import com.baomidou.mybatisplus.extension.service.IService; import net.javadog.chat.entity.User; /** * 用户接口 * * @author: hdx * @Date: 2023-01-10 11:53 * @version: 1.0 **/ public interface UserService extends IService { } 复制代码package net.javadog.chat.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import net.javadog.chat.entity.User; import net.javadog.chat.mapper.UserMapper; import net.javadog.chat.service.UserService; import org.springframework.stereotype.Service; /** * 用户接口实现类 * * @author: hdx * @Date: 2023-01-10 11:55 * @version: 1.0 **/ @Service public class UserServiceImpl extends ServiceImpl implements UserService { } 复制代码<?xml version="1.0" encoding="UTF-8"?> chat-boot-module net.javadog.chat 1.0-SNAPSHOT 4.0.0 chat-boot-service 8 8 net.javadog.chat chat-boot-dao ${project.parent.version} net.javadog.chat chat-boot-dto ${project.parent.version} 复制代码
在chat-boot-controller创建UserController.java,并修改chat-boot-controller模块下修改pom.xml文件依赖,引入chat-boot-dto,chat-boot-service
package net.javadog.chat.controller; import cn.hutool.core.bean.BeanUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import net.javadog.chat.entity.User; import net.javadog.chat.request.UserRequest; import net.javadog.chat.response.UserResponse; import net.javadog.chat.service.UserService; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; /** * 用户控制器 * * @author: hdx * @Date: 2022-12-07 15:48 * @version: 1.0 **/ @Api(tags = "用户控制器") @RestController @RequestMapping("/user") public class UserController { @Resource private UserService userService; @ApiOperation(value = "用户详情", notes = "用户详情") @GetMapping public UserResponse detail(UserRequest userRequest){ UserResponse userResponse = new UserResponse(); User user = userService.getById(userRequest.getId()); BeanUtil.copyProperties(user, userResponse); return userResponse; } } 复制代码
重要补充 1.切记修改chat-boot-main下的pom.xml依赖,将chat-boot-controller模块加入 2.切记修改chat-boot-main下的pom.xml依赖,将chat-boot-dao模块加入 3.切记修改启动类ChatApplication中加入@MapperScan注解
<?xml version="1.0" encoding="UTF-8"?> chat-boot net.javadog.chat 1.0-SNAPSHOT 4.0.0 chat-boot-main 8 8 net.javadog.chat chat-boot-dependencies 1.0-SNAPSHOT pom import org.springframework.boot spring-boot-starter-web org.projectlombok lombok io.springfox springfox-swagger2 io.springfox springfox-swagger-ui com.github.xiaoymin knife4j-spring-boot-starter net.javadog.chat chat-boot-controller ${project.parent.version} net.javadog.chat chat-boot-dao ${project.parent.version} org.apache.maven.plugins maven-compiler-plugin 3.1 ${java.version} org.apache.maven.plugins maven-resources-plugin 2.6 @ false src/main/webapp false src/main/resources true src/main/java **/*.xml local local true dev dev prod prod 复制代码
package net.javadog.chat; import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; import lombok.extern.slf4j.Slf4j; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.Environment; import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.net.InetAddress; import java.net.UnknownHostException; /** * @author: hdx * @Date: 2023-01-28 11:24 * @version: 1.0 **/ @SpringBootApplication @ServletComponentScan @Slf4j @EnableSwagger2 @EnableKnife4j @MapperScan(basePackages = {"net.javadog.chat.mapper"}) public class ChatApplication { public static void main(String[] args) throws UnknownHostException { // 启动类 ConfigurableApplicationContext application = SpringApplication.run(ChatApplication.class, args); // 打印基础信息 info(application); } static void info(ConfigurableApplicationContext application) throws UnknownHostException { Environment env = application.getEnvironment(); String ip = InetAddress.getLocalHost().getHostAddress(); String port = env.getProperty("server.port"); String active = env.getProperty("spring.profiles.active"); String contextPath = env.getProperty("server.servlet.context-path"); if (contextPath == null) { contextPath = ""; } log.info(" ---------------------------------------------------------- " + "欢迎访问 https://blog.javadog.net " + "示例程序【" + active + "】环境已启动! 地址如下: " + "Local: http://localhost:" + port + contextPath + " " + "External: http://" + ip + ":" + port + contextPath + " " + "Swagger文档: http://" + ip + ":" + port + contextPath + "/doc.html " + "----------------------------------------------------------"); } } 复制代码7.示例DB更新模拟正常前端请求到后台服务调用过程,进行实际代码补充
DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` bigint(20) NOT NULL COMMENT "id", `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT "用户名", `id_card` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT "身份证", PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of user -- ---------------------------- INSERT INTO `user` VALUES (1, "JavaDog", "123123"); 复制代码8.访问测试
浏览器访问http://localhost:8001/chat/v1/user?id=1
测试成功如下图所示
总结
以上示例只是简单示范分层思路,其中代码逻辑实现方式有很多种,大家选取适用自己就好,希望自己的思路能对大家有帮助
如遇缺少依赖情况,一定要重新拉取依赖!
长鸿高科2022年前三季度净利润1。86亿元同比增长15。26中证智能财讯长鸿高科(605008)10月29日披露2022年第三季度报告。2022年前三季度,公司实现营业总收入20。42亿元,同比增长56。32归母净利润1。86亿元,同比增长
秋季学期开始执行!湖南省义务教育课程实施办法发布日前,为全面落实立德树人根本任务,进一步深化课程改革,根据教育部义务教育课程方案(2022年版),湖南省教育厅研究制定了湖南省义务教育课程实施办法(2022年版)(以下简称办法),
走进秋天柳笛又是秋风爽,又是雁南飞,又是丹桂飘香时,又是一度秋。当感知到秋的爽凉,酷暑留在身上的汗渍已经枯干,身上一脉喜悦的舒坦。秋来了!在万物苍天的无声无息中,在天高气爽的舒目畅怀中,悄
秋之恋。难忘秋天的你秋天的你临风而立眺海远望,难忘秋天的你。秋风拂面,蜇痛了我夜夜的相思,是否也像海平面泛起的浪花一样撩拨起你内心的情感?眼前的梧桐在风雨中摇曳,是不是遮挡了伊人清眸的眼帘?透过夜空,
都说饱暖思淫欲,却不知它的下半句更加现实人生感悟相信大家都很清楚,我们生活在这个世界上。免不了为了生存,而想方设法去赚钱养家糊口。但是当一个人吃喝都不愁的时候,那他就有了别的玩乐的心思。这就是所谓的饱暖思淫欲。这个淫欲,
坐着轨道交通游重庆2号线沿线吃喝玩乐攻略重庆轨道交通2号线(ChongqingRailTransitLine2),是中国西部地区第一条城市轨道交通线路,也是中国第一条跨座式单轨线路,识别色为森林绿。2号线连接了重庆多处网
双11相机怎么选?佳能尼康降价,索尼不动声色,富士走高端路线双11又到了,今年你打算买相机吗?不买的话,那也可以看看价格变化。而如果想买的话,还不一定有货。确实,现在相机市场就是这个样子,不是那么给力,甚至有点躺平的味道。在这种温和的竞争下
5部心痒痒女性向尺度欧美剧!爱欲交织满足所有幻想高颜值霸道总裁校园18禁忌5部意味深长的女性向片单!亢奋以青少年校园为背景,绝对是今年讨论度最高的大尺度美剧。剧情充满18禁,内容大胆煽情又迷幻,同时探讨青少年Z世代的黑暗面。性爱
50岁以后,减少贪欲和欲望,这些方面会越来越好人生,历经磨难和沧桑,会经历很多,收获很多,个人也会改变很多。但是,有些东西,比如发展的规律,事物的本质,是无法改变的。年轻的时候,我身体强壮,精力充沛,身体健康,但缺乏与人交往的
苏州大闸蟹季,阳澄湖吃喝玩乐住全攻略又到了蟹蟹你,金秋的季节,如果你对阳澄湖的全部印象,还仅仅是大闸蟹的话,那可就太浪费了这一次出行,在这儿玩上两天恐怕都不过瘾呢,我已经为各位做好攻略了!住我这次住的是苏州阳澄半岛英
一个越有能力的人,越不动声色作者闻秋声原创文章,抄袭必究01引言生活,就像是波涛粼粼的湖面,我们总以为只有自己的生活在坎坷奔腾。其实,每个人的生活都充满了考验和风雨,只是有些人将自己的人生,蒙上了纱,在不动声
刚刚,贾乃亮道歉!相关视频紧急下架中国基金报安曼为趣店代言而被推上风口浪尖的贾乃亮,终于发声了26日下午,继傅首尔之后,贾乃亮也在发文回应与趣店合作问题,称发现问题,第一时间已与趣店解约,也没有后续的任何合作。据了
暴君隋炀帝杨广的历史功绩隋炀帝是中国历史上一个颇具争议性的帝王。长期以来,人们大多从其荒淫暴虐的角度审视其对历史造成的影响,而对于他的历史贡献则鲜有提及。他统一全国后,创立了科举制改革了赋税制度开凿了大运
公安部公布唐山烧烤打人案进展,中央出手相信案件很快会水落石出7月25日,公安部介绍公安机关推进更高水平平安中国建设成果。公安部回应唐山烧烤打人事件,唐山烧烤打人事件引发社会广泛关注,公安部高度重视,第一时间派出专案组应从全国抽调专家赴一线指
挪威的兵役制度,美女们被强制兵役7女兵!一直是关注度最高的群体。女人的美丽有许多种,除了外貌,还可以以另一种方式展现给世人巾帼不让须眉!在美国,有世界上最多的女兵30万。虽然它喜欢南征北战,但是女兵的汗马功劳不能被
全国文化中心再添金名片光明日报记者董城张景华韩业庭文化是一个国家一个民族的灵魂,文化兴国运兴,文化强民族强。7月25日至26日,北京文化论坛举办。作为全国文化中心的北京,由此再添一张金名片。作为一座有着
开幕司东书法作品展隆重开幕时令总是眷顾对艺术有追求的人。正值火红的七月,由沭阳县书法家协会江苏今世缘酒业股份有限公司主办,江苏存真堂文化传播有限公司沭阳大酒店承办的吾悦书怀司东书法作品展7月22日下午在沭阳
胡闹的阿根廷!可以娶亲姐妹,自由决定自己的性别,还曾败北国足阿根廷是一个位于南美洲东南部的国家,同时也是南美洲的第三大经济体。虽然只是发展中国家,但阿根廷国内的自然资源非常丰富,产业市场也比较多元,综合国力还是非常强劲的。然而阿根廷当地的法
赖士葆佩洛西访台两岸更紧张只有民进党得利美国众议院议长佩洛西传出8月可能访台,中国表达强烈不满,要美国后果自负。中国国民党民意代表赖士葆今日向香港中评社表示,佩洛西这一趟让两岸紧张,美国就可以继续军售,二方面也是暗助民进
烂片预测迷航昆仑墟的预告分析鞍灭曾经在文章中说过,自己在豆瓣上的预测至今都一直保持了百分之百的准确率,还没有错过一次。今天就再公开预测一次,不再藏着掖着了。预测一下明天就要开播的天下霸唱的作品,迷航昆仑墟。鞍
土俄伊叙都对结果很满意,联手要将美军赶走,考验拜登的时候到了近日,俄罗斯土耳其伊朗联合召开的阿斯塔纳进程国家首脑会议在伊朗首都德黑兰举行。俄土伊三国的领导人发表了联合声明,可以说是条条直击美国的要害。三国一致反对美国持续非法掠夺叙利亚石油等
乌情报头子去中东访问的是普京替身,看他下飞机的动作,就懂了众所周知,前阵子普京去了一趟中东,在德黑兰与土耳其伊朗总统,就叙利亚问题以及其他相关合作进行了商谈。当时普京一下飞机,就引起了世界的关注,特别是其身边的安保队伍,可谓规模庞大。据称