SpringMVC 入门教程
前言
首先我们需要了解一下什么是 MVC (Model View Controller),是模型(Model)- 视图(View)- 控制器(Controller)
这种模式用于应用程序的分层开发。
- Model(模型) - 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器。
- View(视图) - 视图代表模型包含的数据的可视化。
- Controller(控制器) - 控制器作用于模型和视图上。它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开。
Spring架构图
用户发送请求SpringMVC处理流程:
- 用户发出请求到中央处理器。
- 中央处理收到请求调用处理器映射器。
- 处理器映射器根据URL找到对应的HandlerExecutionChain,生成处理对象(Handler)和处理器拦截器(HandlerIntercepter)返回到中央处理器。
- 中央处理器通过处理器适配器找到对应的处理器。
- 处理器适配器调用对应的处理器控制器,让其执行。
- 控制器返回ModelAndView到处理器适配器。
- 处理器适配器返回ModelAndView到中央控制器。
- 中央控制器将ModelAndView传递给视图解析器。
- 视图解析器解析ModelAndView返回View到中央控制器。
- 中央控制器渲染视图。
- 中央控制器响应用户。
组件说明:
- DispatcherServlet 前端控制器
用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性。 - HandlerMapping 处理器映射器
HandlerMapping负责根据用户请求找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。 - Handler 处理器
Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。 - HandlAdapter 处理器适配器
通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。 - ViewResolver 视图解析器
ViewResolver负责将处理结果生成View视图,ViewResolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。 springmvc框架提供了很多的View视图类型,包括:jstlView、freemarkerView、pdfView等。
说明:在springmvc的各个组件中,处理器映射器、处理器适配器、视图解析器称为springmvc的三大组件。需要用户开发的组件有handler、view
创建一个SpringMVC的项目
所需要的步骤:
1. 导入Jar包
2. 配置前端控制器
3. 编写SpringMVC配置文件
4. 配置处理器映射器
5. 配置处理器适配器
6. 配置视图解析器
7. 后端控制器开发
8. 后端控制器配置
9. 视图开发
1.导入Jar包
一个SpringMVC项目需要导入的Jar包
commons-logging-x.x.x.jar
jstl-x.x.jar
spring-aop-x.x.x.RELEASE.jar
spring-aspects-x.x.x.RELEASE.jar
spring-beans-x.x.x.RELEASE.jar
spring-context-x.x.x.RELEASE.jar
spring-context-support–x.x.x.RELEASE.jar
spring-core–x.x.x.RELEASE.jar
spring-expression-x.x.x.RELEASE.jar
spring-jdbc-x.x.x.RELEASE.jar
spring-jms-x.x.x.RELEASE.jar
spring-messaging-x.x.x.RELEASE.jar
spring-tx-x.x.x.RELEASE.jar
spring-web-x.x.x.RELEASE.jar
spring-webmvc-x.x.x.RELEASE.jar
2.配置前端控制器DispatcherServlet
在 /web/WEB-INF/web.xml 中进行配置
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!-- 要加载的配置文件 -->
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!-- tomcat启动时自动创建servlet,数字越小优先级越高(>0) -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!-- 要处理的请求地址映射 -->
<url-pattern>*.action</url-pattern>
</servlet-mapping>
注意事项:
如果要拦截全部 需要注意
1)/* 之类的肯定不能写,因为访问啥都出错
2)/ 的形式访问静态资源会出错
如果想要拦截全部 使用 / 那么我们可以另外配置
<!-- 定义专门用于处理静态资源的Servlet,Tomcat给提供了 -->
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 然后对静态资源根据文件格式进行映射 -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.png</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.js</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.css</url-pattern>
</servlet-mapping>
编写SpringMVC配置文件
注意在这里我们编写的文件名称要和在web.xml中配置的文件名相同
springmvc.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd ">
</beans>
4. 配置处理器映射器
处理器映射器分为 注解式处理器和非注解处理器
非注解处理器映射器:
- BeanNameUrlHandlerMapping 将Bean的Name属性作为url进行查找 需要在配置Handel的时候指定Bean的name属性。
<!-- 根据bean的name进行查找Handler 将action的url配置在bean的name中 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!-- 注意bean的name属性的后缀名要符合web.xml中的url-pattern的映射规则 -->
<bean name="/d1.action" class="com.baidu.controller.DoController"></bean>
缺点:我们每编写一个Handel (Controller)的时候都要进行配置一个bean
- SimpleUrlHandlerMapping 通过内部参数去配置请求的 url 和 handler 之间的映射关系。
<!-- 根据bean的id进行查找Handler 通过mappings属性将bean的id和url进行统一映射-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<!-- key写url 括号中间编写bean的ID-->
<prop key="/d1.action">doController</prop>
</props>
</property>
</bean>
<!-- 定义Handel -->
<bean id="doController" class="com.baidu.controller.DoController"></bean>
缺点:我们每编写一个Handel 也需要去编写映射关系
- ControllerClassNameHandlerMapping 根据Handler的名字映射,它将URL请求映射到配置中提到的控制器的名称。
该类使用Controller名称,并将它们转换为小写。
<!-- 根据Handler的名字映射,它将URL请求映射到配置中提到的控制器的名称。该类使用Controller名称,并将它们转换为小写 -->
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
<!-- 举例子 这个Handler 的映射地址就是 docontroller* -->
<bean class="com.baidu.controller.DoController"></bean>
注解处理器映射器:
<!-- 注解类映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
也可以通过mvc:annotation-driven</mvc:annotation-driven>进行简写,它会自动去注册处理器映射器
详细:springmvc使用mvc:annotation-driven自动加载RequestMappingHandlerMapping和RequestMappingHandlerAdapter,可用在springmvc.xml配置文件中使用mvc:annotation-driven替代注解处理器和适配器的配置。
<mvc:annotation-driven></mvc:annotation-driven>
注意:
使用了注解处理器映射器我们需要进行扫描
<!-- 将Controller进行扫描找出所有带有@Controller注解的Handel -->
<context:component-scan base-package="com.baidu.controller"></context:component-scan>
使用context:component-scan元素启动“包扫描”功能,base-package是值是包的路径。意思就是,启动了报扫描功能,将com.myz.controller这个包下以及子包下的所有类扫描一遍,将标记有@Controller、@Service、@repository、@Component等注解的类注入到IOC容器中,作为Spring的Bean来管理。
Java类中我们需要在类上加@Controller注解
@Controller
@RequestMapping("/d1")
public class DoController {
@RequestMapping("/test.action")
public String test(){
return "index";
}
}
在DoController中 我们暂时用到了@Controller、@RequestMapping注解
那么这些注解都是什么意思呢?
@Controller
表示将当前普通类变成控制器类
@RequestMappring
表示把地址映射到类上或者方法上,如果在类上使用那么访问方法时需要将类上注解的地址也写上
比如上面例子中 如果想访问 test方法 路径需要 http://主机名:端口号/项目名/d1/test.action
5. 配置处理器适配器
处理器适配器 HandlerAdapter:作用是根据映射器找到的处理器 Handler 信息,按照特定的规则去执行相关的处理器 Handler。
处理器适配器有两种配置方式:非注解方式、注解方式
非注解方式:
- SimpleControllerHandlerAdapter
配置文件中
<!--这款适配器要求我们编写的 Handler 实现 Controller 接口-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
Controller代码需要实现Controller接口
public class DoController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException,IOException {
//逻辑代码
ModelAndView mv = new ModelAndView();
mv.addObject("参数A","参数A的值");
mv.setViewName("设置View的名字");
return mv;
}
}
- HttpRequestHandlerAdapter
<!--这款适配器要求我们编写的 Handler 实现 HttpRequestHandler 接口--><bean
class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"></bean>
Controller代码需要实现HttpRequestHandler接口
public class DoController implements HttpRequestHandler {
@Override
public void handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException,IOException {
//逻辑代码
}
}
需要注意的是 配置它需要的处理器映射器需要 使用 SimpleUrlHandlerMapping
<!-- 根据bean的id进行查找Handler 通过mappings属性将bean的id和url进行统一映射-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<!-- key写url 括号中间编写bean的ID-->
<prop key="/d1.action">doController</prop>
</props>
</property>
</bean>
<!-- 定义Handel -->
<bean id="doController" class="com.baidu.controller.DoController"></bean>
注解处理器适配器:
使用注解方式前置条件就是 需要扫包
<context:component-scan
base-package="com.baidu.controller"></context:component-scan>
然后在Handler(Controller)上编写 @Controller
第一种方式
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
第二种方式
<mvc:annotation-driven></mvc:annotation-driven>
6. 配置视图解析器
视图解析器的作用:
当 DispatcherServlet将ModelAndView传递给视图解析器的时候,将ModelAndView数据填充到相应的视图中,然后返回一个带有数据的视图给DispatcherServlet.
分类有两种:面向单一视图类型的、面向多视图类型的
面向单一视图类型的ViewResolve (UrlBasedViewResolver)
解释:使用该类别的ViewResolver,我们不需要为它们配置具体的视图名到具体View的映射关系。通常只要指定一下视图模板所在的位置,这些ViewResolver就会按照逻辑视图名,抓取相应的模板文件、构造对应的View实例并返回。之所有又将它们称之为面向单一视图类型的ViewResolver,是因为该类别中,每个具体的ViewResolver实现都只负责一种View类型的映射,ViewResolver与View之间的关系是一比一。
该类型包含InternalResourceViewResolver,FreeMarkerViewResolver,XsltViewResolver这3个实现类。
面向多视图类型的ViewResolve
解释:使用面向单一视图类型的ViewResolver,我们不需要指定明确的逻辑视图名与具体视图之间的映射关系,对应的ViewResolver将自动到指定位置匹配自己所管辖的那种视图模板,并构造具体的View实例。面向多视图类型的ViewResolver则不然。使用面向多视图类型的ViewResolver,我们需要通过某种配置方式明确指定逻辑视图名与具体视图之间的映射关系,这可能带来配置上的烦琐。不过,好处是,面向多视图类型的ViewResolver可以顾及多种视图类型的映射管理。如果你的逻辑视图名想要映射到InternalResourceView,那么面向多视图类型的ViewResolver可以做到。如果你的逻辑视图名想要映射到VelocityView,那么,面向多视图类型的ViewResolver也可以做到。相对于只支持单一视图类型映射的情况,面向多视图类型的ViewResolver更加灵活。
该类型包含ResourceBundleViewResolver、XmlViewResolver,BeanNameViewResolver这3个实现类。
在这里我们先把这些罗列出来后续在补充:
AbstractCachingViewResolver
这是一个抽象类,这种视图解析器会把它曾经解析过的视图保存起来,然后每次要解析视图的时候先从缓存里面找,如果找到了对应的视图就直接返回,如果没有就创建一个新的视图对象,然后把它放到一个用于缓存的map中,接着再把新建的视图返回。使用这种视图缓存的方式可以把解析视图的性能问题降到最低。
UrlBasedViewResolver
它是对ViewResolver的一种简单实现,而且继承了AbstractCachingViewResolver,主要就是提供的一种拼接URL的方式来解析视图,它可以让我们通过prefix属性指定一个指定的前缀,通过suffix属性指定一个指定的后缀,然后把返回的逻辑视图名称加上指定的前缀和后缀就是指定的视图URL了
XmlViewResolver
它继承自AbstractCachingViewResolver抽象类,所以它也是支持视图缓存的。XmlViewResolver需要给定一个xml配置文件,该文件将使用和Spring的bean工厂配置文件一样的DTD定义,所以其实该文件就是用来定义视图的bean对象的。在该文件中定义的每一个视图的bean对象都给定一个名字,然后XmlViewResolver将根据Controller处理器方法返回的逻辑视图名称到XmlViewResolver指定的配置文件中寻找对应名称的视图bean用于处理视图。
BeanNameViewResolver
这个视图解析器跟XmlViewResolver有点类似,也是通过把返回的逻辑视图名称去匹配定义好的视图bean对象。
InternalResourceViewResolver
它是URLBasedViewResolver的子类,所以URLBasedViewResolver支持的特性它都支持。在实际应用中InternalResourceViewResolver也是使用的最广泛的一个视图解析器。InternalResourceViewResolver会把返回的视图名称都解析为InternalResourceView对象,InternalResourceView会把Controller处理器方法返回的模型属性都存放到对应的request属性中,然后通过RequestDispatcher在服务器端把请求forword重定向到目标URL。
ResourceBundleViewResolver
它和XmlViewResolver一样,也是继承自AbstractCachingViewResolver,但是它缓存的不是视图,这个会在后面有说到。和XmlViewResolver一样它也需要有一个配置文件来定义逻辑视图名称和真正的View对象的对应关系,不同的是ResourceBundleViewResolver的配置文件是一个属性文件,而且必须是放在classpath路径下面的,默认情况下这个配置文件是在classpath根目录下的views.properties文件,如果不使用默认值的话,则可以通过属性baseName或baseNames来指定。
FreeMarkerViewResolver
它是UrlBasedViewResolver的子类。FreeMarkerViewResolver会把Controller处理方法返回的逻辑视图解析为FreeMarkerView。
我们使用的是InternalResourceViewResolver
<!-- ViewResolver -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
这个配置就像是我们使用url拼接
通过prefix加上你的view在哪里,return时返回的是view的名字suffix是文件的结尾是什么。
7. 后端控制器开发
在这里我们使用注解方式进行开发,前面我们在写处理器适配器时已经将非注解方式如何进行配置和编写Controller做出了说明,那么我们开始编写后端的控制器。
@Controller
@RequestMapping("/d1")
public class DoController {
@RequestMapping("test.action")
public ModelAndView test(){
ModelAndView mv = new ModelAndView();
mv.addObject("参数A","参数A");
mv.addObject("参数B","参数B");
mv.addObject("参数C","参数C");
mv.setViewName("设置要去的View");
return mv;
}
}
以上代码我们创建了个ModelAndView 在里面设置携带了 参数A,参数B,参数C,设置了要去的View视图
在这里我们详细的解释以上Handler(Controller)注解开发的基础。
@RequestMappring:通过这个注解我们可以定义 不同的处理器映射规则。
- URL路径映射:@RequestMapping(value="/item")或@RequestMapping("/item)value的值是数组,可以将多个url映射到同一个方法
- 窄化请求映射:在Class上添加@RequestMappring用于指定请求的前缀,限制这个类下的方法请求url必须以这个请求的前缀开头
- 请求方式的限定:在@RequestMappring中可以使用method 来指定可以使用哪些方式来访问,多种使用 , 隔开。
举例:@RequestMappring("/test.action",method = RequestMethod.GET)
如果我们使用了其他方式进行访问 比如 POST 那么就会提示:HTTP Status 405 - Request method ‘POST’ not supported
@controller 的方法返回值
- 返回ModelAndView
返回类型是ModelAndView,那么我们可以使用ModelAndView中的 addObject 为其附加传递回去的数据,
使用 setViewName 来为其指定 返回的View的名字(视图解析器会去找到对应的View并带上传递回去的数据返回给DispatchServlet)- 返回Void
默认会经过视图管理器处理,返回的视图名称为方法名。
也可以在参数列表上写上 HttpServletRequest,HttpServletResponse 来进行跳转(这里的参数绑定待会会详细介绍)。
这个返回Void在Spring中是不推荐使用的- 返回字符串
两种情况:
1.返回逻辑视图的名称
2.Redirect 重定向 (地址栏变化 不带有Request,Response) 具体使用:“redirect:地址”
3.forward 转发 (地址栏不变,带有Request,Response)具体使用:“forward:地址”
参数绑定
- 默认支持的参数类型
- HttpServletRequest
- HttpServletResponse
- HttpSession
- Model(ModelMap和Model)是一样的 可以通过Model中的addAttribute来绑定数据
- @RequestParam
value属性:在绑定单个数据时 如果没有指定@RequestParam中的value数据 那么传递过来的参数名就必须与参数列表中的参数名相同,且必须传递。
required属性:如果不传递这个参数需要指定required属性为false,默认为true必须传递。
defaultValue属性:默认值,如果在url中没有传递这个参数那么就会使用这个默认值。- 绑定自定义参数
举例子时间参数Date类型
- propertyEditor
WebDataBinder: 在Controller中使用@InitBinder 注解
//注册属性编辑器(字符串转换为日期)只对当前handler有效
@InitBinder
public void initBinder(WebDataBinder binder) throws Exception {
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));
}
WebBindingInitializer:多个Controller都使用相同的属性编辑器,可以实现PropertyEditorRegistrar接口,并注入webBindingInitializer中
编写CustomPropertyEditor.java类
public class CustomPropertyEditor implements PropertyEditorRegistrar {
@Override
public void registerCustomEditors(PropertyEditorRegistry propertyEditorRegistry) {
propertyEditorRegistry.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd HH-mm-ss"),true));
}
}
在SpringMVC的配置文件中进行配置(注册属性编辑器、自定义一个WebBinder、注册适配器)
<!--注册属性编辑器-->
<bean id="customPropertyEditor" class="com.baidu.propertyeditor.CustomPropertyEditor"></bean>
<!--自定义WebBinder-->
<bean id="bindingInitializer" class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="propertyEditorRegistrars">
<list>
<ref bean="customPropertyEditor"/>
</list>
</property>
</bean>
<!--注解适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="webBindingInitializer" ref="bindingInitializer"></property>
</bean>
- Converter(常用)
自定义一个Converter
编写一个自定义Converter类 在这里我们以Date为例
public class MyConverter implements Converter<String, Date> {
@Override
public Date convert(String s) {
try {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
return simpleDateFormat.parse(s);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
接下来我们编写SpringMVC的配置文件。
第一种方式(不常用):
<!-- 配置convertor -->
<bean id="conversionServiceFactoryBean"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.baidu.converter.MyConverter"></bean>
</list>
</property>
</bean>
<!-- 配置 customBinder-->
<bean id="customBinder"
class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="conversionService" ref="conversionServiceFactoryBean"></property>
</bean>
<!-- 配置RequestMappingHandlerAdapter -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="webBindingInitializer" ref="customBinder"></property>
</bean>
第二种方式 (常用):
<mvc:annotation-driven conversion-service="conversionServiceFactoryBean"></mvc:annotation-driven>
<!-- 配置convertor -->
<bean id="conversionServiceFactoryBean" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.baidu.converter.MyConverter"></bean>
</list>
</property>
</bean>
- Pojo自定义对象
- 简单的Pojo(属性均为自定义类型):传递时只要参数名称和Pojo的属性名一样就可以自动装配。
- Pojo中有Pojo:传递时 Pojo中Pojo的属性名加点需要绑定的属性名。
@ModelAttribute
- 如果是注释到方法上,那么在执行这个Controller中任何方法之前都会执行一次被注释的方法。
如果这个被注释的方法有返回值,那么之前执行的Controller中的方法就会得到这个返回值,如果没有在参数列表写出,那么会经历 隐式转换 成为Model。注意不要瞎转换。
使出传说中的权限控制:
首先写一个类 然后 就是不在类上写@Controller 然后编写带有@ModelAttributer 的方法,然后让你的Handler继承这个类,然后在Handler中使用,使用方法:在方法中也写上了@ModelAttribute并且指定名称,那么这个方法就会在执行前调用异常那个类中的方法。
数组:可以直接传递 在 参数列表写出类型 这里我用Object[]来代替 在前台传递方式 参数名[数组下标]来传递
比如:文本框等单个数据的
在比如:复选框多个数据的
List:指定名称 和数组一样加 [下标] 来传递。
Map:指定名称 通过参数名[‘key’] 来传递。
- 上传图片
- 导入Jar包
commont ( fileUpload,和io )包- 在SpringMVC中配置解析器
<!-- 文件上传 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设置上传文件的最大尺寸为5MB -->
<property name="maxUploadSize">
<value>5242880</value>
</property>
</bean>
- 编写Handler代码
@Controller
@RequestMapping("/d1")
public class DoController {
@RequestMapping("/upload")
public String picUpload(MultipartFile pictureFile)throws Exception {
//原始文件名称
String pictureFile_name = pictureFile.getOriginalFilename();
//新文件名称
String newFileName = UUID.randomUUID().toString() + pictureFile_name.substring(pictureFile_name.lastIndexOf("."));
//上传图片
File uploadPic = new File("指定路径/" + newFileName);
if (!uploadPic.exists()) {
//如果uploadPic没有的话创建这个文件
uploadPic.createNewFile();
}
//向磁盘写文件
pictureFile.transferTo(uploadPic);
return "要去的视图名称";
}
}
- 多个图片文件上传
在Handler方法中参数列表里接收MultipartFile[] 需要注意的是 在前端页面 name属性要一样
8. 后端控制器配置
在前面我们在写处理器映射器时已经将非注解方式如何进行配置Controller做出了说明。
我们需要根据使用的什么映射器来决定我们怎么编写配置文件中的bean。
9. 视图开发
前端页面 搞后台的到底搞什么前段啊 当然是选择 略咯!!!!
异常处理器
系统中异常包括两类:预期异常和运行时异常RuntimeException前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试通过手段减少运行时异常的发生。
在SpringMVC中 我们可以把异常一路 throw 到 DispatchServlet 然后异常通过异常处理器来处理。
那么我们编写异常处理器需要准备什么呢?
- 自定义异常处理器(HandlerExceptionResolver)
首先我们需要编写一个自定义异常处理器 然后 实现 HandlerExceptionResolver 接口。
public class MyExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
ModelAndView mv = new ModelAndView();
if (e instanceof IOException){
//如果这个异常是Io异常那么就把异常信息存入mv
mv.addObject("error",e.getMessage());
}
mv.setViewName("要去的错误页面");
return mv;
}
}
- 异常处理器配置
在SpringMVC的核心配置文件中注册这个ExceptionResolver
<bean class="com.baidu.exceptionresolver.MyExceptionResolver"></bean>
JSON 数据交互
- @RequestBody
作用:用于读取http请求的内容,通过SpringMVC提供的HttpMessageConverter接口将读到的内容转换为json、xml等格式的数据并绑定到controller方法的参数上。 - @ResponseBody
作用:该注解用于将Controller的方法返回的对象,通过HttpMessageConverter接口转换为指定格式的数据如:json,xml等,通过Response响应给客户端
请求和相应Json
- 准备Jar包
Springmvc默认用MappingJacksonHttpMessageConverter对json数据进行转换,需要加入jackson的包。
jackson-annotations-x.x.x.jar
jackson-core-x.x.x.jar
jackson-databind-x.x.x.jar - 配置转换器
<!--注解适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
</list>
</property>
</bean>
注意:如果使用<mvc:annotation-driven /> 则不用定义上边的内容
3. 编写Handler
@Controller
@RequestMapping("/d1")
public class DoController {
@RequestMapping("/test.action")
public List<Test> queryAll(@RequestBody Test test){
return new List<Test>();
}
}
- 编写前端页面
function test(){
var test={name:"list",id:15};
$.ajax({
url:"${pageContext.request.contextPath}/d1/test.action",
type:"post",
contentType:"application/json;charset=UTF-8",
data:JSON.stringify(test),
dataType:"json",
success:function(obj){
console.log(obj.name);
}
})
}
拦截器
Spring Web MVC 的处理器拦截器类似于Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。
实现拦截效果步骤:
- 编写自定义拦截器类实现HandlerInterceptor接口
public class MyHandlerceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
//执行Controller中方法之前执行,如果返回的是false 那么就不执行Controller中的方法,如果为true那么就放行
//三个参数 分别为: Request,Response 和 当前SpringMVC请求的对象
return false;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
//请求已经到达Controller中的方法,但是还没有返回View视图时执行
//四个参数 分别为:Request,Response 当前SpringMVC请求的对象 和 方法中返回的ModelAndView
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
//请求已经到达Controller中的方法,并且执行完毕
//四个参数 分别为:Request,Response 当前SpringMVC请求的对象 和 方法中返回的异常
}
}
- 拦截配置
有两种配置方式
第一种 针对某些Controller进行拦截
<bean
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="doController"/>
</list>
</property>
</bean>
<bean id="doController" class="com.baidu.controller.DoController"/>
第二种 针对所有Controller进行拦截
<!--拦截器 -->
<mvc:interceptors>
<!--多个拦截器,顺序执行 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/js/*.js"/>//配置哪些路径是不拦截的
<bean class="com.baidu.interceptor.MyHandlerceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
OK就先到这吧!