注:【网页版】右上方的悬浮框( 有目录索引 )
CREATE TABLE `user_comment` (
`comment_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '评论序列号',
`comment_article_id` bigint(32) NOT NULL COMMENT '被评论的文章 id',
`comment_date` date NOT NULL COMMENT '发表评论 时间',
`comment_content` varchar(300) COLLATE utf8_unicode_ci NOT NULL COMMENT '发表评论 内容',
`comment_writer_id` bigint(32) NOT NULL COMMENT '发表评论作者 id',
`comment_writer_nickname` varchar(50) COLLATE utf8_unicode_ci NOT NULL COMMENT '发表评论作者 昵称',
PRIMARY KEY (`comment_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
Spring Cloud Discovery - Eureka Server
@EnableEurekaServer
# yml 配置信息
server:
port: 7776
eureka:
client:
service-url:
defaultZone: http://localhost:7776/eureka # 注册中心的地址
register-with-eureka: false # 是否把当前项目注册到中心
fetch-registry: false # 是否在注册中心检索此项目
Spring Cloud Discovery - Eureka Discovery Client
此外,还有 ssm 三个依赖@EnableEurekaClient
# yml 配置信息
server:
port: 8090
spring:
datasource:
url: jdbc:mysql:///bug?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
password: root
username: root
hikari: # 连接池 [译:光]
maximum-pool-size: 200
minimum-idle: 10
jackson:
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
default-property-inclusion: non_null # ajax 去 null 值
application:
name: provider # 注册到注册中心的名称
eureka:
client:
service-url:
defaultZone: http://localhost:7776/eureka # 注册中心的位置
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.debj.provider.entity
configuration:
call-setters-on-nulls: true # mybatis null 值不会封装至 map 中
map-underscore-to-camel-case: true # 匹配驼峰命名规则的实体类字段
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 输出 sql 日志
生成文件,记得加注解
<dependency>
<groupId>org.mybatis.generatorgroupId>
<artifactId>mybatis-generator-coreartifactId>
<version>1.3.7version>
dependency>
<plugin>
<groupId>org.mybatis.generatorgroupId>
<artifactId>mybatis-generator-maven-pluginartifactId>
<version>1.3.2version>
<configuration>
<overwrite>trueoverwrite>
<configurationFile>src/main/resources/mbg.xmlconfigurationFile>
configuration>
plugin>
resources 下 mbg.xml
<generatorConfiguration>
<classPathEntry location="D:\_ruanJian\Jar\mysql-connector-java-5.1.47\mysql-connector-java-5.1.47.jar"/>
<context id="DB2Tables" targetRuntime="MyBatis3">
<plugin type="org.mybatis.generator.plugins.ToStringPlugin" />
<commentGenerator>
<property name="suppressDate" value="true"/>
<property name="suppressAllComments" value="true" />
commentGenerator>
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql:///bug"
userId="root"
password="root">
jdbcConnection>
<javaTypeResolver >
<property name="forceBigDecimals" value="false" />
javaTypeResolver>
<javaModelGenerator
targetPackage="com.debj.provider.entity"
targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
javaModelGenerator>
<sqlMapGenerator
targetPackage="mapper"
targetProject=".\src\main\resources">
<property name="enableSubPackages" value="true" />
sqlMapGenerator>
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.debj.provider.dao"
targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
javaClientGenerator>
<table tableName="user_comment" domainObjectName="UserComment"/>
context>
generatorConfiguration>
@SpringBootTest
class ProviderApplicationTests {
@Resource
private UserCommentMapper userCommentMapper;
@Test
void contextLoads() {
UserComment userComment = new UserComment();
for(int i=0;i<20;i++){
userComment.setCommentArticleId(333L);
userComment.setCommentDate(new Date());
userComment.setCommentContent(UUID.randomUUID().toString());
userComment.setCommentWriterId(520L);
userComment.setCommentWriterNickname("spiderMan");
userCommentMapper.insertSelective(userComment);
}
}
}
@RestController
@CrossOrigin
@RequestMapping(value = "/userComment")
public class UserCommentController {
@Resource
private UserCommentService service;
@GetMapping(value = "/getAll")
public Map getAllInfo(){
return service.getAllInfo();
}
@PostMapping(value = "addOne")
public Map addOneInfo(
@RequestParam Map map){
System.out.println(map);
return service.addOneInfo(map);
}
}
public interface UserCommentService {
Map getAllInfo();
Map addOneInfo(Map map);
}
@Service
@Transactional
public class UserCommentServiceImpl implements UserCommentService {
@Resource
private UserCommentMapper mapper;
// 返回 Map
Map<String,Object> returnMap = new HashMap<>();
@Override
public Map getAllInfo() {
returnMap.put("data",mapper.selectByExample(null));
returnMap.put("code","100");
return returnMap;
}
@Override
public Map addOneInfo(Map map) {
UserComment userComment = new UserComment();
userComment.setCommentArticleId(Long.parseLong((String) map.get("commentArticleId")));
userComment.setCommentDate(new Date());
userComment.setCommentContent((String) map.get("commentContent"));
userComment.setCommentWriterId(Long.parseLong((String) map.get("commentWriterId")));
userComment.setCommentWriterNickname((String) map.get("commentWriterNickname"));
if(mapper.insertSelective(userComment)==1){
returnMap.put("info","添加成功");
returnMap.put("code","100");
} else {
returnMap.put("info","添加失败");
returnMap.put("code","200");
}
return returnMap;
}
}
Spring Cloud Discovery - Eureka Discovery Client
、Spring Cloud Routing - OpenFeign
此外,还有 spring web
依赖@EnableEurekaClient
、@EnableFeignClients
server:
port: 8080
spring:
application:
name: consumer
eureka:
client:
service-url:
defaultZone: http://localhost:7776/eureka # 注册中心的地址
@FeignClient(value = "provider",fallback = FeignUserCommentServiceImpl.class)
public interface FeignUserCommentService {
@GetMapping(value = "/userComment/getAll")
public Map getAllInfo();
@PostMapping(value = "/userComment/addOne")
public Map addOneInfo(
@RequestParam Map map);
}
@Component
public class FeignUserCommentServiceImpl implements FeignUserCommentService {
@Override
public Map getAllInfo() {
return null;
}
@Override
public Map addOneInfo(Map map) {
return null;
}
}
@RestController
@CrossOrigin
@RequestMapping(value = "/userComment")
public class UserCommentController {
@Resource
private LocalService service;
@GetMapping(value = "/getAll")
public Map getAllInfo(){
return service.getAllInfo();
}
@PostMapping(value = "addOne")
public Map addOneInfo(
@RequestParam Map map){
System.out.println(map);
return service.addOneInfo(map);
}
}
public interface LocalService {
Map getAllInfo();
Map addOneInfo(Map map);
}
@Service
public class LocalServiceImpl implements LocalService {
@Resource
private FeignUserCommentService feignUserCommentService;
@Override
public Map getAllInfo() {
return feignUserCommentService.getAllInfo();
}
@Override
public Map addOneInfo(Map map) {
return feignUserCommentService.addOneInfo(map);
}
}
Spring Cloud Discovery - Eureka Discovery Client
、Spring Cloud Routing - Zuul [Maintenance]
@EnableEurekaClient
、@EnableZuulProxy
server:
port: 8070
zuul:
routes:
consumer: /consumer/**
eureka:
client:
service-url:
defaultZone: http://localhost:7779/eureka
spring:
application:
name: gateway
public class MyFilter extends ZuulFilter {
private String[] split;
{
FileReader fileReader = null;
try {
fileReader = new FileReader(ResourceUtils.getFile("classpath:words.txt"));
StringBuffer stringBuffer = new StringBuffer();
char[] chars = new char[1024];
int len = -1;
while((len = fileReader.read(chars))!=-1){
stringBuffer.append(chars);
}
split = stringBuffer.toString().split(",");
System.out.println(Arrays.asList(split).toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileReader != null) {
fileReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private String filterWord(String param){
// 对输入的文本进行过滤 自定义方法
for(String word:split){
if(param.indexOf(word)!=-1){
// 有敏感词需要过滤
StringBuffer newWord= new StringBuffer();
for(int i=0;i<word.length();i++){
newWord.append("*");
}
param=param.replaceAll(word,newWord.toString());
}
}
return param;
}
public static void main(String[] args) { // 测试
System.out.println(new MyFilter().filterWord("你是个沙雕沙雕的草泥马草泥马-沙雕沙雕的草泥马草泥马a!"));
}
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
// 先获取请求参数的 map 集合,获取当前的请求上下文环境
RequestContext context = RequestContext.getCurrentContext();
// 获得 request
HttpServletRequest request = context.getRequest();
// 获得所有的请求参数组成的 Map
Map<String, String[]> parameterMap = request.getParameterMap();
if(parameterMap==null){
return null;
}
// 构造新的过滤后的参数 Map
HashMap<String, List<String>> newParamsMap = new HashMap<>();
// 新建保存参数值的 list
List<String> newValueList = null;
// 遍历参数的 key,获得第一个参数值
for (String key : parameterMap.keySet()){
System.out.println("key:"+key);
// 循环遍历每个键,对应的值
for(String value: parameterMap.get(key)){
newValueList = new ArrayList<String>();
System.out.println(key+",键对应的值有其:"+value);
if(key.equals("commentContent")){
newValueList.add(filterWord(value));
} else {
newValueList.add(value);
}
}
newParamsMap.put(key,newValueList);
}
// 重新设置查询参数
context.setRequestQueryParams(newParamsMap);
return null;
}
}
// 启动类,配置 Bean
@Bean
public MyFilter getMyFilter(){
return new MyFilter();
}
// words.txt 示例文本
// 沙雕,草泥马,多余文本
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Templatetitle>
<link href="bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="css/index.css" />
<script src="bootstrap-3.3.7-dist/js/jquery-1.12.4.min.js">script>
<script src="bootstrap-3.3.7-dist/js/bootstrap.min.js">script>
<script src="bootstrap-3.3.7-dist/js/vue.js">script>
head>
<body>
<div id="app">
<div class="container col-xs-6 col-xs-offset-3">
<div class="row text-center" style="margin: 50px auto;">
<button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
添加新评论
button>
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×span>button>
<h4 class="modal-title" id="myModalLabel">Modal titleh4>
div>
<div class="modal-body">
<form id="addOneInfoForm" @submit.prevent="addOneInfo">
<p><input type="hidden" placeholder="" v-model="addOneInfoData.commentArticleId" >p>
<p class="text-left">
<textarea placeholder="评论内容" style="resize: none;" cols="50" rows="4" v-model="addOneInfoData.commentContent">
textarea> ∅ 评论内容
p>
<p><input type="hidden" placeholder="" v-model="addOneInfoData.commentWriterId" />p>
<p><input type="hidden" placeholder="" v-model="addOneInfoData.commentWriterNickname" />p>
form>
div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Closebutton>
<button type="submit" form="addOneInfoForm" class="btn btn-primary">Save changesbutton>
div>
div>
div>
div>
div>
<div class="row">
<ul id="pl">
<li v-for="item,index in listInfoData.data" :class="index%2==0?'Gray':''" style="height: 50px;">
<span>{{item.commentContent}}span>
<span class="spanRight">{{item.commentWriterNickname}}span>
<br />
<span class="spanRight">{{item.commentDate}}span>
li>
ul>
div>
div>
div>
<script src="js/index.js">script>
body>
html>
var vue = new Vue({
el:"#app",
data:{
listInfoData:{},
addOneInfoData:{
"commentArticleId":"333",
"commentWriterId":"520",
"commentWriterNickname":"spiderMan",
"commentContent":""
}
},
methods:{
getAllInfo:function(){
$.get("http://localhost:8066/consumer/userComment/getAll",function(res){
vue.listInfoData=res;
})
},
addOneInfo:function(){
$.post("http://localhost:8066/consumer/userComment/addOne",vue.addOneInfoData,function(res){
vue.getAllInfo();
$("#myModal").modal("hide");
alert(res.info)
})
}
},
mounted:function(){
this.getAllInfo();
}
})
.spanRight{
display: inline-block;
position: relative;
float: right;
}
.Gray{
background-color: darkseagreen;
}