模拟一次论坛添加评论对该评论过滤敏感词并且转发到显示评论页面的请求。
下面是具体代码:
<!--web.xml-->
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<servlet>
<servlet-name>followMe</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:followMe.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>followMe</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Servlet配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd">
<context:component-scan base-package="com.excelib"/>
<!-- 添加注解驱动 -->
<mvc:annotation-driven/>
<mvc:view-resolvers>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/views/jsp/"
p:suffix=".jsp"/>
</mvc:view-resolvers>
</beans>
Controller代码:
/**
* Created by lizhaoz on 2016/3/27.
*/
@Controller
@SessionAttributes("articleId")
public class FollowMeController {
private final String[] sensitiveWords=new String[]{"k1","s2"};
@ModelAttribute("comment")
public String replaceSensitiveWords(String comment) throws IOException{
if (comment!=null){
System.out.println("原始comment: "+comment);
for (String sw :sensitiveWords) {
comment=comment.replaceAll(sw,"");
}
System.out.println("去除敏感词comment:"+comment);
}
return comment;
}
@RequestMapping(value = {"/articles/{articleId}/comment"})
public String doComment(@PathVariable String articleId,RedirectAttributes attributes,Model model) throws Exception{
System.out.println(model.asMap().get("comment"));
attributes.addFlashAttribute("comment",model.asMap().get("comment"));
System.out.println(articleId);
model.addAttribute("articleId", articleId);
//保存评论内容
return "redirect:/showArticle";
}
@RequestMapping(value = {"/showArticle"},method = {RequestMethod.GET})
public String showArticle(Model model,SessionStatus sessionStatus){
String articleId= (String) model.asMap().get("articleId");
model.addAttribute("atricleTitle",articleId+"号文章标题");
model.addAttribute("article",articleId+"号文章内容");
sessionStatus.setComplete();
return "article";
}
}
jsp文件略,具体参考github。
这里我们使用如下的请求建立连接:
localhost:8080/articles/67/comment?comment=好s2赞k1梦s2龙
具体过程
1)请求发送到服务器后,服务器程序就会分配给一个Socket线程来跟它连接,创建出request,response,交给对应的Servlet进行处理,这样请求就从Servlet容器传递到了Servlet。
2)在Servlet中请求首先会被HttpServlet处理,在HttpServlet的service方法中将ServletRequest和ServletResponse转换为HttpServletRequest和HttpServletResponse,并调用转换为Request和Response的service方法。
3。接下来请求到了SpringMVC,在SPringMVC中首先由FrameWorkServlet的service进行处理,在这里service方法会将请求交给HttpServlet方法的service方法去处理。
4。在HttpServlet的service方法中会根据请求类型将请求传递到doGet或者doPost方法。
5。doGet方法在FramworkServlet中,它又传递了processRequest方法,然后再processRequest进行一些设置处理。
6.DispatcherServlet的doService方法将webApplicationContext,localResolver,themeResolver,themeSource,outputFlashMap和flashMapManager设置到request的属性中,然后将请求传递到了doDispatch方法中。
7。首先检查是不是上传请求,然后调用getHandler方法获取到Handler。
8。getHandler方法获取Handler的过程会遍历容器中所有的HandlerMapping,在我们这里mvc:annotation-driven 标签配置的HandlerMapping是RequestMappingHandlerMapping和BeanNameUrlHandlerMapping,在用RequestMappingHandlerMapping匹配的时候我们请求会和其初始化时读取到的路径相匹配,然后根据这个条件找到定义的处理器方法doComment。
9。找到处理器后调用RequestMappingInfoHandlerMapping里的handleMatch方法会将匹配到的Patter和articleId这个PathVariable设置到到request的属性中。
10找到Handler后返回DispatcherServlet的doDispatch方法中,然后调用getHandlerAdapter方法根据Handler查找HandlerAdapter也就是根据工具找使用工具的人。查找方式是遍历所有的HandlerAdapter,分别调用他们的support()方法进行 检查,检查的方法通常是看Handler的类型是否支持。
11。DispatcherServlet的doDispatch方法中检查到是Get请求,然后检查是否可以使用缓存,然后调用拦截器的preHandler方法,这里没有拦截器。
12。RequestMappingHandlerAdapter首先在其父类的handle方法中直接将请求传递到了它的handleInternal方法,hanleInternal方法首先调用getSessionAttributesHandler初始化本处理器对应的SessionAttributesHandler,并判断出注释有@SessionAttributes,进而调用checkAndPrepare方法禁止了Response的缓存,然后将请求传递给invokeHandleMethod方法。
13.RequestMappingHandlerAdapter的invokeHandleMethod方法首先创建了WebDataBinder-Factory和ModelFactory,ServletInvocableHandlerMethod,ModelFactory创建过程中会找到定义的注释了@ModelAttribute的reoplaceSensitiveWords方法。
14.接着创建ModelAndViewContainer,并调用ModelFactory的initModel方法给Model设置参数,这里会调用了定义的replaceSensitiveWords方法,调用前会使用RequestParamMethodArgumentResolver解析出”comment”参数的值,然后去除敏感词,ModelFactory将其使用@ModelAttribute注释中的”comment”作为name,去除敏感词后的评论内容作为value设置到Model中。
15。接下来调用ServletInvocableHandlerMethod的invokeAndHandler方法实际执行处理。首先在父类InvocableHandlerMethod的invokeForRequest方法中调用了getMethodArgumentVlaues方法解析参数.不同的参数使用不同的参数解析器。
16调用doInvoke方法处理请求,这里实际调用了我们编写的doComment方法,其中将”comment” 设置到RedirectAttributes中,通过FlashMap传递,将”articleId”设置到Model中。
17。接下来处理返回值因为返回的是String,所以使用的是ViewNameMethodReturnValueHandler,它首先将返回值
return "redirect:/showArticle";
设置到mavContainer的view里,然后将mavContainer中的redirect标志redirectModelScenario设置为了true,这样ServletInvocableHandlerMethod就处理完了,接着请求返回RequestMappingHandlerAdapter。
18ReqiestMappingHandler调用getModelAndView方法对返回值进一步处理,首先使用ModelFactory的updateModel方法处理@SessionAttributes(“articleId”),将其中的”articleId”参数从Model中取出并使用sessionAttributesHandler保存。然后使用mavContainer中的model和view创建ModelAndView;最后检查到Model是RedirectAttributes,把之前保存到RedirectAtributes中的”comment”参数设置到outputFlashMap,这样RequestMappingHandlerAdapter的处理就完成了,请求返回DispatcherServlet中。
19。DispatcherServlet在doDispatch方法中首先检查返回的view是否为空,如果为空查找默认View。
20执行拦截器后面的方法
21对异常的处理。
22。渲染页面,这里是转发。
23。回复原来的LocaleContext和RequestAttributes,最后返回给Servlet容器。
代码地址:
https://github.com/lzggsimida123/SpringMVCAnay