-
准备环境:
搭建Web项目、拷贝依赖的jar
1)添加Spring的核心包
com.springsource.org.apache.commons.logging-1.1.1.jar
spring-core-4.x.x.RELEASE.jar
spring-beans-4.x.x.RELEASE.jar
spring-context-4.x.x.RELEASE.jar
spring-expression-4.x.x.RELEASE.jar2)添加SpringMVC的核心包
spring-web-4.x.x.RELEASE.jar spring 对web项目的支持。
spring-webmvc-4.x.x.RELEASE.jar spring mvc核心包。
开发步骤:
①:配置前端控制器:DispatcherServlet
②:配置处理器映射器:BeanNameUrlHandlerMapping
③:配置处理器适配器:SimpleControllerHandlerAdapter
④:配置视图解析器:InternalResourceViewResolver
⑤:开发和配置处理器:HelloController(处理请求的对象)
------------------------------------------------------------------
查看DispatcherServlet.properties文件(包含了SpringMVC的默认的配置)
xml里<load-on-startup>表示启动时创建前端控制器->启动spring容器->加载配置文件解析成对象放在内存->默认去/web-inf/mvc-servlet.mxl去找,一般放在resource里,要引入->定义Controller实现 mvc.xml里交给容器管理并,命名空间路径供外界访问 -
SpringMVC流程:
01、用户发送出请求到前端控制器DispatcherServlet。
02、DispatcherServlet收到请求调用HandlerMapping(处理器映射器)。
03、HandlerMapping找到具体的处理器(可查找xml配置或注解配置),生成处理器对象及处理器拦截器(如果有),再一起返回给DispatcherServlet。
04、DispatcherServlet调用HandlerAdapter(处理器适配器)。
05、HandlerAdapter经过适配调用具体的处理器(Handler/Controller)。
06、Controller执行完成返回ModelAndView对象。
07、HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet。
08、DispatcherServlet将ModelAndView传给ViewReslover(视图解析器)。
09、ViewReslover解析后返回具体View(视图)。
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、DispatcherServlet响应用户。 -
涉及组件分析:
1、前端控制器DispatcherServlet(不需要程序员开发),由框架提供,在web.xml中配置。
作用:接收请求,响应结果,相当于请求分发器,中央处理器。2、处理器映射器HandlerMapping(不需要程序员开发),由框架提供。
作用:根据请求的url查找Handler(处理器/Controller),可以通过XML和注解方式来映射。3、处理器适配器HandlerAdapter(不需要程序员开发),由框架提供。
作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler。4、处理器Handler(也称之为Controller,需要工程师开发)
注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler。
作用:接受用户请求信息,调用业务方法处理请求,也称之为后端控制器。5、视图解析器ViewResolver(不需要程序员开发),由框架提供
作用:进行视图解析,把逻辑视图名解析成真正的物理视图。
SpringMVC框架支持多种View视图技术,包括:默认jstlView、freemarkerView、pdfView等。6、视图View(需要工程师开发)
作用:把数据展现给用户的页面
View是一个接口,实现类支持不同的View技术(jsp、freemarker、pdf等) -
我们这样的配置有这样一个问题:
在Web根路径添加index.html,然后不能访问,原因是什么呢?
为什么此时在配置前端控制器的URL模式(<url-pattern>)写成 / 就不行呢?原因:
Tomcat中处理静态资源访问的servlet(default)的映射路径为/.
在启动项目的时候,在Tomcat中的web.xml是先加载的,项目的web.xml是后加载的,如果配置了相同的映射路径,后面的会覆盖前者.
也就是说,SpringMVC中的DispatcherServlet的映射路径覆盖了Tomcat默认对静态资源的处理的路径。
如果SpringMVC要配置为/,那么就得设置Dispatcherservlet对静态资源进行支持。解决方案:需要在SpringMVC的配置文件中添加对静态资源的访问
<mvc:default-servlet-handler/>
-----------------------------------------------------------------------------------------
<mvc:default-servlet-handler/> 将在 SpringMVC 上下文中定义一个 DefaultServletHttpRequestHandler,它会对进入 DispatcherServlet 的请求进行筛查,如果发现是没有经过映射的请求,就将该请求交由 Tomcat默认的 Servlet 处理,如果不是静态资源的请求,才由 DispatcherServlet 继续处理
-----------------------------------------------------------------------------------------
/和/*的区别:
/ 会匹配url请求/index等 ,也会匹配静态资源*.js,*.html等, 不会匹配*.jsp文件。
/* 会匹配url请求/index等 ,也会匹配静态资源*.js,*.html等, 会匹配*.jsp文件。如果使用,JSP直接响应,没有渲染. -
Java EE应用程序分为三层:
表现层(Web) @Controller
业务逻辑层(Service) @Service
数据持久层(DAO/Mapper) @Resposotory其他组件使用通用注解 @Component
---------------------------------------------------------------------
注意:
1):四者的功能一模一样,仅仅只是被贴的组件类型不同.
2):作用,就是把被贴的类交给Spring管理,如下.
<bean id=”类简单名字,首字母小写” class=”类的全限定名称”/>
3):开启IoC注解扫描:<context:component-scan base-package="com._520it._02_anno"/> -
处理器适配器和处理器映射器:
---------------------------------------------------------------------------------------------
在spring3.1之前使用:
注解映射器:org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
注解适配器:org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter在spring3.1之后使用:
注解映射器:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
注解适配器:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter -
SpringMVC注解的解析器:
<mvc:annotation-driver>:
会自动注册RequestMappingHandlerMapping、RequestMappingHandlerAdapter、ExceptionHandlerExceptionResolver三个bean。
除此之外,还支持:
支持使用 ConversionService实例对表单参数进行类型转换.
支持使用 @NumberFormat、@DateTimeFormat注解完成数据格式化操作.
支持使用 @Valid注解对JavaBean实例进行JSR303验证.
支持使用 @RequestBody和@ResponseBody注解读写JSON. -
@RequestMapping注解: 设置Controller方法的访问URL,不能重名.
一:URL路径映射
二:窄化请求映射
三:请求方法限定:
@RequestMapping(value="/list",method=RequestMethod.POST)
--------------------------- -
情况二:返回ModelAndView类型和共享数据.
Controller方法中定义ModelAndView对象并返回,对象中设置model数据、指定view。
---------------------------------------------------------------
@RequestMapping("/test2")
public ModelAndView test2() {
ModelAndView mv = new ModelAndView();
mv.setViewName("/WEB-INF/views/response/response.jsp");
mv.addObject("msg","SpringMVC");
mv.addObject("你好,小码哥");//此时key就是默认为数据类型 (全小写) string,相同key,后面覆盖前面的.
return mv;
} -
情况三:返回String类型和共享数据(使用广泛).
1):返回值为String,此时默认视图的地址:前缀+逻辑视图名+后缀
2):redirect方式相当于“response.sendRedirect()”,转发后浏览器的地址栏变为重定向后的地址,不共享之前请求的数据。
3):forward方式相当于“request.getRequestDispatcher().forward(request,response)”,转发后浏览器地址栏还是原来的地址,共享之前请求中的数据。 -
情况四:返回对象类型和共享数据(把当前请求的url作为逻辑视图名称).
-
情况二:简单类型参数和RequestParam注解(使用比较多).
一:如何请求参数和Controller方法的形参同名. 可以直接接收.
二:如何请求参数和Controller方法的形参不同名. 使用@RequestParam注解贴在形参前,设置对应的请求参数名称. -
情况三:对象传参,能够自动把请求参数封装到声明在形参上的对象中,此时请求参数必须和对象的属性同名(使用比较多).
@RequestMapping("/test4")
public ModelAndView test4(User u){
System.out.println(u);
return null;
}
----------------------------------------------------------------------
@ModelAttribute作用如下:
1、设置请求参数绑定到Model对象中并传到视图页面的key名.
2、将方法返回值或请求参数绑定到Model对象中并传到视图页面,设置key名.
----------------------------------------------------------------------
@RequestMapping("/test4")
public String test4(@ModelAttribute("myUser") User u){
System.out.println(u);
return "request/request";
}
----------------------------------------------------------------------
request.jsp:
你好:${myUser}<br/> -
情况四:数组和List集合类型参数.
接收数组类型参数:
@RequestMapping("/test5")
public String test5(Long[] ids){
System.out.println(Arrays.asList(ids));
return null;
}
浏览器请求URL:/request/test5.do?ids=1&ids=2&ids=3
------------------------------------------------------------------------------------------------------------------
接收List类型参数:
不能直接获取,只能通过对象封装List集合. 类似3
@Getter@Setter
public class User {
private List<Long> ids= new ArrayList<Long>();
}
---------------------------------------------------------
@RequestMapping("/test6")
public String test6(User u){
System.out.println(u);
return null;
}
浏览器请求URL:/request/test6.do?ids[0]=1&ids[1]=2&ids[2]=3 -
情况六:RESTful是一种软件架构风格,严格上说是一种编码风格,其充分利用 HTTP 协议本身语义从而提供了一组设计原则和约束条件。
主要用于客户端和服务器交互类的软件,该风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
在后台,RequestMapping标签后,可以用{参数名}方式传参,同时需要在形参前加注解@PathVarable,前台的请求地址为localhost:8080/delete/3
@RequestMapping("/delete/{id}") 多个参数需映射
public ModelAndView value4(@PathVariable("id")Long id){
System.out.println("delete");
System.out.println(id);
return null;
} -
在页面使用了中文,出现乱码怎么解决?
以前编码是不是都是我们自己写,request.setCharacterEncoding("utf-8");
既然是重复的代码,更倾向于抽取抽取,SringMVC已经做了这样的工作了.
在web.xml中配置符编码过滤器: -
SpringMVC框架默认支持的JSON库jackson.
jackson-annotations-2.5.0.jar
jackson-core-2.5.0.jar
jackson-databind-2.5.0.jar
------------------------------------------------
@RequestBody注解用于读取HTTP请求的内容(JSON格式字符串),转换为Java对象。
@ResponseBody注解用于将Controller的方法返回的对象,转换为JSON字符串。
@RestController注解 = @Controller注解 + @ResponseBody注解
------------------------------------------------
1.加入支持JSON的包.
2.在方法上加上@ResponseBody注解
------------------------------------------------
如果HTTP请求类型和数据格式是JSON(contentType=application/json;charset=utf-8),此时必须使用@RequestBody贴在Controller方法参数上。
如果HTTP请求的数据格式是key-value就不需要使用@RequestBody。 -
浏览器传递String的时间格式到Controller中转换为Date类型:
方式一:在对象字段或Controller形参上添加上@DateTimeFormat(pattern="yyyy-MM-dd")
@RequestMapping("/test8")
public ModelAndView test8(@DateTimeFormat(pattern = "yyyy-MM-dd") Date d) {
System.out.println("d = [" + d + "]");
return null;
}
方式二:在Controller类中加入以下代码.
@InitBinder
public void initBinderDateType(WebDataBinder binder){
SimpleDateFormat sdf = new SimpleDateFormat();
sdf.applyPattern("yyyy-MM-dd");
binder.registerCustomEditor(java.util.Date.class,new CustomDateEditor(sdf,true));
}
@RequestMapping("/test9")
public ModelAndView test9(Date d) {
System.out.println("d = [" + d + "]");
return null;
}
方式三:使用@ControllerAdvice注解,该类必须处于能被Spring扫描到的包中.
@ControllerAdvice
public class DateFormatControllerAdvice {
@InitBinder
public void initBinderDateType(WebDataBinder binder){
SimpleDateFormat sdf = new SimpleDateFormat();
sdf.applyPattern("yyyy-MM-dd");
binder.registerCustomEditor(java.util.Date.class,new CustomDateEditor(sdf,true));
}
} -
如果以JSON数据返回数据到前台,如果返回数据中含有日期的字段,Spring自动的解析成毫秒值.
方式一:在需要解析的字段上添加注解 @JsonFormat(pattern = "yyyy-MM-dd-HH:mm:ss",timezone = "GMT+8")
方式二:修改配置文件. -
SpringMVC的文件上传操作:
需要导入fileupload依赖包io的包
com.springsource.org.apache.commons.fileupload-1.2.0.jar
com.springsource.org.apache.commons.io-1.4.0.jar
配置文件上传解析器:bean的名字是固定的
使用Spring表达式 #{1024*1024}
上传文件保存到项目upload文件夹
MVC是用Files.copy()方法
注意servlet是用FileItem.write()(要先获取upload的磁盘路径) -
Spring MVC 的拦截器类似于Servlet 开发中的过滤器Filter,用于对Controller进行预处理和后处理。
使用SpringMVC拦截器步骤:
1)定义拦截器类,实现接口 org.springframework.web.servlet.HandlerInterceptor
HandlerInterceptorAdapter是HandlerInterceptor的实现类,自定义的拦截器类继承它
2)在applicationContext.xml中配置拦截器拦截器方法的执行时机:
1):preHandle:控制器方法执行之前执行,返回结果为true表示放行,如果返回为false,表示拦截(可以做权限拦截,登录检查拦截).
2):postHandle:控制器方法执行后,视图渲染之前执行(可以加入统一的响应信息).
3):afterCompletion:视图渲染之后执行(处理Controller异常信息,记录操作日志,清理资源等) -
每个过程都单独处理异常,系统的代码耦合度高,工作量大且不好统一,维护的工作量也很大。
Spring MVC处理异常有3种方式:
(1)使用Spring MVC提供的简单异常处理器SimpleMappingExceptionResolver;
(2)实现Spring的异常处理接口HandlerExceptionResolver 自定义自己的异常处理器;
(3)使用@ExceptionHandler注解实现异常处理;
-----------------------------------------------------------------------------
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- 定义默认的异常处理页面,当该异常类型的注册时使用 -->
<property name="defaultErrorView" value="common/error"/>
<!-- 定义异常处理页面用来获取异常信息的变量名,默认名为exception -->
<property name="exceptionAttribute" value="ex"/>
<!-- 定义需要特殊处理的异常,用类名或完全路径名作为key,异常也页名作为值 -->
<property name="exceptionMappings">
<value>
com._520it.wms.web.exception.SecurityException=common/nopermission
<!-- 这里还可以继续扩展不同异常类型的异常处理 -->
</value>
</property>
</bean>