1.第一个SpringMVC项目
1.需求
用户在页面发起请求,请求交给spring mvc控制器对象,并显示请求的处理结果(在页面显示欢迎语句)
2.实现步骤
- 新建web maven工程
加入依赖
- spring-webmvc依赖,间接把spring的依赖都加入到项目
jsp,servlet依赖
重点:在web.xml张注册springmvc框架的核心对象DispatcherServlet
- DispatcherServlet叫做中央调度器,是一个servlet,他的父类是继承HttpServlet
- DispatcherServlet页叫做前端页面控制器(front controller)
- DispatcherServlet负责接收用户提交的请求,调用其他的控制器对象,并把请求处理结果显示给用户
- 创建一个发起请求的页面 index.jsp
创建控制器类
- 在类的上面加入@Controller注解,创建对象,并放到springmvc容器中
- 在类的导航面要加入RequestMapping注解
- 创建一个作为结果的jsp,显示请求结果
创建springmvc配置文件(spring的配置文件一样)
- 声明组件扫描器,指定@Controller注解所在的包名
- 声明视图解析器,帮助处理试图的
2.SpringMVC请求处理流程
- 发起some请求
- tomcat(web.xml --url --pattern 知道 / 的请求发送给 DispatcherServlet
- DispatcherServlet(根据springmvc-servlet.xml配置知道 some 对应 MyController里的方法
- DispatcherServlet 把请求进行转发给MyController里的方法
- 框架执行 该方法后,把得到的ModelAndView 进行处理,转发到show.jsp
some请求---》DispatcherServlet --》MyController--》执行方法 --》返回ModelAndView
3.SpringMVC执行过程源代码分析
tomcat启动创建容器的过程
通过load - on -start标签指定的1,创建DispatcherServlet对象
DispatcherServlet 他的父类是继承 HttpServlet 的,他是一个Servlet,在被创建时,会执行 init()方法
在init()方法中会执行 getServletContext().setAttribute(ket,ctx)
上面创建容器的作用:创建@controller注解所在对象,创建MyController对象,这个对象放到springmvc容器中,容器是map
类似于 map.put("myController",myController对象);
执行servlet的service()
- protected void service(HttpServletRequest request,HttpServletResponse response)
- protected void doservice(HttpServletRequest request,HttpServletResponse response)
doDispatch(request,response){
调用MyController 的 .dosome()方法
}
4.配置视图解析器
/WEB-INF/下是受保护的
<!--帮助开发人员设置属兔文件路径配置-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--前缀:视图文件的路径-->
<property name="prefix" value="/WEB-INF/view/"/>
<!--后缀:视图文件的拓展名-->
<property name="suffix" value=".jsp"/>
</bean>
5.RequestMapping详解
可以放在方法上面
value是数组,可以有多个值
可以放到类上
value是所有请求地址公共部分,也叫模块名称,更快速的修改所属路径
http://localhost:8080/SpringMVC/test/some
http://localhost:8080/SpringMVC/test/other
可以将公用部分 /test/ 设置为value
请求映射
属性method,表示请求方式,他的值RequestMethod类枚举
get方式:RequestMethod.GET
post方式:RequestMethod.POST
6.处理器方法接收参数
- HttpServletRequest
- HttpServletResponse
HttpSession
request.getParameter("key");
请求中所带的参数
逐个接收
方法参数名与表单的name保持一致即接收
使用框架进行接收
- String name = request.getParameter("name");
- springmvc框架通过 DispatcherServlet 调用 MyController的方法
- 调用方法时,按名称对应,把接收的参数赋值给形参
5.post请求中文乱码问题,get无乱码
需要使用过滤器处理
过滤器可以自定义,也可以使用框架提供的CharacterEncodingFilter
在web.xml中做如下配置
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/* </url-pattern>
</filter-mapping>
6.通过对象传值
7.处理方法返回类型
- 返回ModelAndView:有数据和视图,对视图执行forward
返回String:表示视图,可以逻辑名称,也可以是完整路径
@RequestMapping(value = "/returnString-view") public String returnView(HttpServletRequest request,User user){ //可以手动添加数据到request到作用域 request.setAttribute("name",user.getName()); request.setAttribute("age",user.getAge()); //"show"为逻辑地址 return "show"; //完整视图路径,不可以用视图解析器 //return "/WEB-INF/view/show.jsp"; }
返回void:在处理ajax时,可以使用void。通过HttpServletResponse输出数据。响应Ajax请求
- jsckson依赖,高性能json处理
<!--jackson--> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.0</version> </dependency>
@RequestMapping(value = "/returnvoid-ajax") public void returnVoid(HttpServletResponse response, User user) throws IOException { System.out.println(user); //处理Ajax,使用json格式 //service调用完成 User u = new User(); u.setName(user.getName()); u.setAge(user.getAge()); //把结果转成json String json = ""; if(u!=null){ ObjectMapper om = new ObjectMapper(); json = om.writeValueAsString(u); System.out.println(json); } response.setContentType("application/json;charset=utf-8"); PrintWriter writer = response.getWriter(); writer.println(json); writer.flush();//刷新缓存 writer.close();//关闭 }
返回Object
步骤:
- 1.首先还是使用jsckson依赖,springmvc默认使用jackson
2.在springmvc配置文件中加入\<mvc:annotation-driv> 注解驱动
json = om.writeValueAsString(u);
3.在处理器方法上面加入@ResponseBody注解
response.setContentType("application/json;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.println(json);@ResponseBody @RequestMapping(value = "/returnuser-ajax") public User returnObject(String name,Integer age) throws IOException { User u = new User(); u.setName(name); u.setAge(age); return u; }
原理:springmvc返回值是个Object,可以转为json输出到浏览器,响应ajax的内部原理
\<mvc:annotation-driv> 注解驱动:功能是完成java对象到json,xml,text,二进制等数据格式的转换
\<mvc:annotation-driv>,再加入到springmvc配置文件后,会自动创建HttpMessageConverter的7个实现类对象,包括常用的StringHttpMessageConverter和MappingJackson2HttpMessageConverter(使用jackson工具库中的ObjectMapper转为json字符串
HttpMessageConverter接口:消息转换器,定义了java转为json,xml等方法,接口有很多实现类,这些实现类完成了转换
boolean canWrite(Class<?> var1, @Nullable MediaType var2); void write(T var1, @Nullable MediaType var2, HttpOutputMessage var3) throws IOException, HttpMessageNotWritableException;
- canWrite作用是检查处理器方法的返回值,能不能转为var2表示的数据类型,能就返回true
- write:把处理器方法的返回值对象,调用jackson中的ObjectMapper转为json字符串 json = om.writeValueAsString(u);
@ResponseBody注解
放在处理器方法上面,通过HttpServletRespsonse响应ajax
断点跟踪:
没有加入注解驱动标签<mvc:annotation-driven />时的状态
org.springframework.http.converter.ByteArrayHttpMessageConverter
org.springframework.http.converter.xml.SourceHttpMessageConverter
org.springframework.http.converter . support.AllEncompassingFormHttpMessageConverter加入注解驱动标签时\<mvc:annotation-driven/>的状态
org.springframework.http.converter.ByteArrayHttpMessageConverterorg.springframework.httpIconverter.ResourceHttpMessageConverter
org.springframework.http.converter.ResourceRegionHttpMessageConverterorg. springframework.http.converter.xml.SourceHttpMessageconverter
org. springframework.http.converter. support.AllEncompassingFormHttpNessageConverterorg. springframework.http.converter.xml.Jaxb2RootElementHttpNessageConverter
org. springframework.http.converter.json.MappingJackson2HttpMessageConverter
返回字符串
必须加ResponseBody,不然默认返回视图
@ResponseBody @RequestMapping(value = "/returnuser-ajax") public String returnObject(String name,Integer age) throws IOException { return "Hello World"; }
默认的字符集是 text/plain;charset=ISO-8859-1,导致中文乱码
解决方案:给RequestMapping增加一个属性produces,指定新的contextType
@ResponseBody @RequestMapping(value = "/returnuser-ajax",produces = "text/plain;charset=utf-8") public String returnObject(String name,Integer age) throws IOException { return "Hello World"; }
8.处理静态资源
第一种方法:在配置文件中添加以下
<mvc:annotation-driven/> <mvc:default-servlet-handler/>
第二种方法:配置文件中配置 mvcResource
<!--第二种处理静态资源的方式 mvc: resources 加入后框架会创建ResourceHttpRequestHandler这个处理器对象让这个对象处理静态资源的访问,不依赖tomcat服务器。 mapping:访问静态资源的uri地址,使用通配符**location :静态资源在你的项目中的目录位置。 images/**:表示 images/p1.jpg , images/user/logo.gif , images/onder/history/list. --> <mvc:resources mapping=" /images/**" location="/images/"/> <mvc:resources mapping=" /html/**"location="/htm1/"/> <mvc:resources mapping="/js/**"location="/js/"/>