根节点没有字符,到最末节点拼起来才是敏感字符,做一个标记在最后。
过滤符号
/*
* 过滤敏感词
* 参数:待过滤的文本, 返回过滤后的文本
* */
public String filter(String text){
// 参数空值判断
if(StringUtils.isBlank(text)){
return null;
}
//依赖三个指针去过滤
TrieNode tempNode=rootNode; //指针一
int begin=0; //指针二
int position=0; //指针三
//变量记录最后的结果,变长
StringBuilder sb=new StringBuilder();
// 利用指针三做条件
while (begin<text.length()){
if(position<text.length()){
//得到指针三的字符
char c = text.charAt(position);
//跳过符号(跳过敏感词汇里面有符号)
if(isSymbol(c)){
//若指针一属于根节点,将此符号计入结果,让指针2向下走
if(tempNode==rootNode){
begin++;
sb.append(c);
}
//无论符号在开头或中间,指针3都向下走一步
position++;
//跳过符号下面的业务就不用处理了,到此为止
continue;
}
//字符不是符号,检查下级节点
//去下级节点
tempNode = tempNode.getSubNode(c);
//当下级没有节点,即以begin开头的字符串不是敏感词,将其添加到结果中
if(tempNode==null){
sb.append(text.charAt(begin));
//指针2后移,且指针3与其保持一致
begin++;
position=begin;
//重新指向根节点
tempNode=rootNode;
}else if(tempNode.isKeywordEnd()){//当当前节点是最后
//发现敏感词,将beagin~position字符串替换掉
sb.append(REPLACEMENT);
//position下移,并且指针2与其保持一致
position++;
begin=position;
//重新指向根节点
tempNode=rootNode;
}else {
//检查下一个字符
if(position<text.length()-1){
position++;
}
}
}
}
//将最后一批字符计入结果
sb.append(text.substring(begin));
return sb.toString();
}
/*
* 判断是否为符号
* */
public boolean isSymbol(Character c){
//利用工具,判断字符是不是普通的字符(abc。。),东亚文字范围中、日、韩文(0x2E80~0x9FFF)
return !CharUtils.isAsciiAlphanumeric(c) && (c<0x2E80 || c>0x9FFF);
}
异步请求:当前页面不刷新,去访问服务器,返回结果提炼数据对网页进行局部刷新(提示,更改样式等)
完成前后端交互,data服务器返回的数据
插入帖子,从数据层开始。业务层保存帖子,同时过滤敏感词汇
数据:查看帖子方法
不可重复读是对一条数据,幻读是对多个数据行数
编程式事务
处理楼数显示,要考虑要分页,起始行+循环次数
复用前端代码:
未读消息和共几条会话。
0:未读 ,1:已读, 2:删除。 会话id(查询会话列表,将两个发送方和接收方id拼起来,将小的id放前面,大的放后面)
数据层:建立实体类
dao层:接口Messagemapper
五个方法:
1,查询这一页的方法(查询当前用户会话列表,针对每个会话只返回一条最新的私信)
2、查询总行数的方法
3、4 :点进去是详情的查询一页的方法及总行数的方法
5:查未读消息数量(查某个用户会话总的未读消息和查询用户与另外一个用户的未读消息数量)
from_id=1表示系统通知
业务层
直接调用mapper实现即可
异步请求
当mybatis参数为集合时,用foreach循环
//修改消息状态(将未读变成已读)
int updateMessage(List<Integer> ids,int status);
<update id="updateMessage" >
update message set status=#{status}
where id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
foreach>
update>
(修改私信的状态为2)
业务层方法
dao
异步请求js
@ModelAttributr:给model绑定统一的参数,给所有的controller用
@DataBinder:页面向服务器传参自动的参数转换,例将page转为Page类
@ControllerAdvice(annotations = Controller.class) //只有带有Controller注解的会被异常处理
public class ExceptionAdvice {
private static final Logger logger= LoggerFactory.getLogger(ExceptionAdvice.class);
@ExceptionHandler(Exception.class)
public void handleException(Exception e, HttpServletRequest request, HttpServletResponse response) throws IOException {
//记录日志
logger.error("服务器异常:"+e.getMessage());
for (StackTraceElement element : e.getStackTrace()) {
//每一个对象记录了一条错误信息
logger.error(element.toString());
}
//给浏览器一个响应,浏览器访问服务器可能希望返回页面,或者是异步请求希望返回json
//需要判断请求是普通请求还是异步请求
String xRequestedWith = request.getHeader("x-requested-with");
//返回值等于xml,表示为异步请求(异步希望返回xml,普通希望返回http)
if("XMLHttpRequest".equals(xRequestedWith)){
//设置格式为字符串自己转为json
response.setContentType("application/plain;charset=utf-8");
PrintWriter writer=response.getWriter();
writer.write(CommunityUtil.getJSIONString(1,"服务器异常!"));
}else{
//普通请求,重定向到错误页面
response.sendRedirect(request.getContextPath()+"/error");
}
}
}
控制器通知是控制器发生异常时记录日志,拦截器是针对controller控制层的,两个都不合适,
需求:对所有的service记日志。
记录日志是系统需求(业务方法和系统需求不要耦合在一起,以后修改系统需求时不方便)
没有接口时(service业务层)需要CGLib代理
@Around:是在方法前后都进行织入
需要有参数:连接点(代表程序织入的部位)。
@AfterThrowing:是在抛异常之后
@AfterReturning:是在方法返回之后
记录日志:用户(ip)XXX在某时刻使用了XX方法
用工具类获取用户ip