SpringMVC简单学习记录

DispatcherServlet
  1. 是一个servlet,所以可以配置多个
  2. 配置在web.xml文件中,拦截匹配的请求,根据HandlerMapping接口的实现类的定义的规则分发到Controller处理
<web-app>  
    <servlet>  
        <servlet-name>example</servlet-name>  
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
        <init-param>  
	        <param-name>contextConfigLocation</param-name>  
	        <!--指明了配置文件的文件名,不使用默认配置文件名,而是用springMVC.xml配置文件-->
	        <param-value>classpath*:/springMVC.xml</param-value>  
        </init-param> 
        <!-- 启动顺序 -->
        <load-on-startup>1</load-on-startup>  
    </servlet>  
    <servlet-mapping>  
    	<!-- 可以有多个DispatcherServlet,通过名字来区分。
    	每个DispatcherServlet有自己的上想问对象,同时保存ServletContext中的Request对象-->
        <servlet-name>example</servlet-name>  
        <!--拦截所有.from结尾的请求-->
        <url-pattern>*.form</url-pattern>  
    </servlet-mapping>  
</web-app> 

< param-value>**.xml< /param-value> 可以使用多种写法

  1. 不写,使用默认值: /WEB-INF/< servlet-name>-servlet.xml
  2. < param-value>/WEB-INF/classes/springMVC.xml< /param-value>
  3. < param-value>classpath*:springMVC-mvc.xml< /param-value>
  4. 多个值用逗号分隔
WebApplicationContext
  • Spring会创建一个WebApplicationContext上下文,称为父上下文(父容器) ,保存在 ServletContext中
  • 可以使用Spring提供的工具类取出上下文对象:WebApplicationContextUtils.getWebApplicationContext(ServletContext);
  • 每个DispatcherServlet有一个自己的上下文对象(WebApplicationContext),称为子上下文(子容器),也保存在 ServletContext中
  • 可以使用工具类取出上下文对象:RequestContextUtils.getWebApplicationContext(request);
  • 也可以自己决定如何使用:
    • 方案一:
    1. 父上下文容器中保存数据源、服务层、DAO层、事物的Bean
    2. 子上下文容器中保存MVC相关的Action的Bean
    3. 事务控制在服务层
    4. 由于父上下文容器不能访问子上下文容器的内容,事物的Bean在父上下文容器中,无法访问子上下文容器的内容,就无法对自上下文容器中Action进行AOP
    • 方案二:
      只使用子上下文容器,不要父上下文容器。
      所以数据源、服务层、DAO层、事物的Bean。Action的Bean都放在子上下文容器中。使用注解事物
配置文件
<?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:tx="http://www.springframework.org/schema/tx"  
    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-3.0.xsd   
    http://www.springframework.org/schema/tx   
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd  
    http://www.springframework.org/schema/context  
    http://www.springframework.org/schema/context/spring-context-3.0.xsd  
    http://www.springframework.org/schema/mvc  
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">  
  
  
    <!-- 自动扫描的包名 -->  
    <context:component-scan base-package="com.app,com.core,JUnit4" ></context:component-scan>  
      
    <!-- 默认的注解映射的支持 -->  
    <mvc:annotation-driven />  
      
    <!-- 视图解释类 -->  
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
        <property name="prefix" value="/WEB-INF/jsp/"/>  
        <property name="suffix" value=".jsp"/><!--可为空,方便实现自已的依据扩展名来选择视图解释类的逻辑  -->  
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />  
    </bean>  
      
    <!-- 拦截器 -->  
    <mvc:interceptors>  
        <bean class="com.core.mvc.MyInteceptor" />  
    </mvc:interceptors>       
      
    <!-- 对静态资源文件的访问  方案一 (二选一) -->  
    <mvc:default-servlet-handler/>  
      
    <!-- 对静态资源文件的访问  方案二 (二选一)-->  
    <mvc:resources mapping="/images/**" location="/images/" cache-period="31556926"/>  
    <mvc:resources mapping="/js/**" location="/js/" cache-period="31556926"/>  
    <mvc:resources mapping="/css/**" location="/css/" cache-period="31556926"/>  
  
</beans>   
< context:component-scan/> 扫描指定的包中的类上的注解

@Controller 声明Action组件
@Service 声明Service组件 @Service(“myMovieLister”)
@Repository 声明Dao组件
@Component 泛指组件, 当不好归类时.
@RequestMapping("/menu") 请求映射
@Resource 用于注入,( j2ee提供的 ) 默认按名称装配,@Resource(name=“beanName”)
@Autowired 用于注入,(srping提供的) 默认按类型装配
@Transactional( rollbackFor={Exception.class}) 事务管理
@ResponseBody
@Scope(“prototype”) 设定bean的作用域

访问静态的文件

方案一:激活tomcat的defaultServlet来处理静态文件

<servlet-mapping>    
    <servlet-name>default</servlet-name>  
    <url-pattern>*.jpg</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>

要写在DispatcherServlet的前面, 让 defaultServlet先拦截请求

方案二:

<!-- 对静态资源文件的访问 -->     
<mvc:resources mapping="/images/**" location="/images/" /> 
  • /images/**映射到ResourceHttpRequestHandler进行处理,
  • location指定静态资源的位置.可以是web application根目录下、jar包里面,这样可以把静态资源压缩到jar包中。
  • cache-period 可以使得静态资源进行web cache

方案三:使用mvc:default-servlet-handler/

<mvc:default-servlet-handler/>
请求映射到具体的Action方法

基于注解映射,DefaultAnnotationHandlerMapping

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">

如果配置了< mvc:annotation-driven />会自动注册,不用在写上边这个bean。
并在action类上使用注解:
@Controller
@RequestMapping("/user")

Spring拦截器

org.springframework.web.servlet.HandlerInterceptor接口,

org.springframework.web.servlet.handler.HandlerInterceptorAdapter适配器,

  1. Action之前执行:
    public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler);

  2. 生成视图之前执行
    public void postHandle(HttpServletRequest request,HttpServletResponse response, Object handler,ModelAndView modelAndView);

  3. 最后执行,可用于释放资源
    public void afterCompletion(HttpServletRequest request,HttpServletResponse response, Object handler, Exception ex)

分别实现预处理、后处理(调用了Service并返回ModelAndView,但未进行页面渲染)、返回处理(已经渲染了页面)
在preHandle中,可以进行编码、安全控制等处理;
在postHandle中,有机会修改ModelAndView;
在afterCompletion中,可以根据ex是否为null判断是否发生了异常,进行日志记录。
参数中的Object handler是下一个拦截器

使用拦截器

定义一个拦截器,实现Handlerlnterceptor接口

public class MyInteceptor implements HandlerInterceptor {     
      
}  

Spring MVC并没有总的拦截器,不能对所有的请求进行前后拦截

在spring MVC的配置文件中配置有三种方法:
方案一,拦截所有ur

<mvc:interceptors>   
    <bean class="com.app.mvc.MyInteceptor" />   
</mvc:interceptors>

方案二, 拦截匹配的URL。

<mvc:interceptors >     
  <mvc:interceptor>     
        <mvc:mapping path="/user/*" /> <!-- /user/*  -->     
        <bean class="com.mvc.MyInteceptor"></bean>     
    </mvc:interceptor>     
</mvc:interceptors>  

方案三,HandlerMappint上的拦截器。


<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
 <property name="interceptors">        
     <list>        
         <bean class="com.mvc.MyInteceptor"></bean>       
     </list>        
 </property>        
</bean>  

如果使用了< mvc:annotation-driven />, 它会自动注册DefaultAnnotationHandlerMapping 与AnnotationMethodHandlerAdapter 这两个bean,所以就没有机会再给它注入interceptors属性,就无法指定拦截器。

可以通过人工配置上面的两个Bean,不使用 < mvc:annotation-driven />,就可以 给interceptors属性 注入拦截器了。

全局异常处理

第一种:在springMVC配置文件中

<!-- 总错误处理-->  
<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">  
	<!--defaultErrorView默认异常提示页面,如果抛出的异常在exceptionMappings中没有对应的映射,则默认使用此提示`在这里插入代码片`页面-->
    <property name="defaultErrorView">     
        <value>/error/error</value>  
    </property>  
    <!--默认异常发生时,HttpServletResponse的返回m值是500
    <property name="defaultStatusCode">     
        <value>500</value>  
    </property>      
    <!--指定特定异常返回特定视图-->
	<property name="exceptionMappings">
  	    <props>
  	    	<!-- 表示当抛出NumberFormatException的时候就返回名叫number的视图-->
	        <prop key="NumberFormatException">number</prop>
	        <prop key="NullPointerException">null</prop>
	    </props>
    </property>     
    <!--发生特定异常时返回值-->
    <property name="statusCodes"><!-- 定义在发生异常时视图跟返回码的相应关系 -->
	    <props>
	        <!-- 表示在发生NumberFormatException时返回视图number,然后这里定义发生异常时视图number相应的HttpServletResponse的返回码是500 -->
	        <prop key="number">500</prop>
	        <prop key="null">503</prop>
	    </props>
    </property>
</bean> 

第二种:在代码中
实现HandlerExceptionResolver接口

/*
@ControllerAdvice定义全局异常处理类
*/
@ControllerAdvice
public class GlobalExceptionHandler {
	// @ExceptionHandler(Exception.class)声明异常处理方法,并只处理Exception类型及其子类  的异常
	// @ResponseBody处理结果不走视图解析器,如果不写,返回指定视图
    @ExceptionHandler(Exception.class)
    @ResponseBody
    String handleException(){
        return "error";
    }
    /*
	如果@ExceptionHandler未指明处理异常类型,可将要处理的类型写在参数里
	@ExceptionHandler()
    @ResponseBody
    String handleException(Exception e){
        return "Exception Deal! " + e.getMessage();
    }
	*/
}
异常记录到日志中

在log4j配置文件中添加:

log4j.logger.org.springframework.web.servlet.handler.SimpleMappingExceptionResolver=WARN

在异常处理的配置增加

<property name="warnLogCategory">    
        <value>org.springframework.web.servlet.handler.SimpleMappingExceptionResolver</value>  
    </property>

记录的这个异常级别是warn。

转发与重定向

可以通过redirect/forward:url方式转到另一个Action进行连续的处理。

可以通过redirect:url 防止表单重复提交 。

写法如下:

  • return “forward:/order/add”;

  • return “redirect:/index.jsp”

带参数重定向–RedirectAttributes

保存或修改后,为了防止用户刷新浏览器(F5)导致表单重复提交,一般在保存或修改操作之后会redirect到一个结果页面

public String save(@ModelAttribute("group") Group group, RedirectAttributes redirectAttributes) {   
    accountManager.saveGroup(group);   
	// RedirectAttributes  提示信息只出现一次
    redirectAttributes.addFlashAttribute("message", "操作成功");   
    return "redirect:/account/group/";   
} 
取得Spring管理的bean

在配置文件中:

<!-- 用于持有ApplicationContext,可以使用SpringContextHolder.getBean('xxxx')的静态方法得到spring bean对象 -->  
<bean class="com.xxxxx.SpringContextHolder" lazy-init="false" />  

springMVC.xml配置文件示例

<?xml version="1.0" encoding="UTF-8"?>

-<beans xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans">

<!-- 自动扫描包,可以写多个 -->
<context:component-scan base-package="com.xxx,com.xxx.session,com.xxx.xxx"/>
<!-- 多视图处理器 -->
<bean class="com.xxx.core.web.MixedViewResolver">
	<property name="resolvers">
		<map>
			<entry key="jsp">
				<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
					<property name="prefix" value="/WEB-INF/jsp/"/>
					<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
				</bean>
			</entry>
			<entry key="ftl">
				<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
					<property name="cache" value="true"/>
					<property name="contentType" value="text/html;charset=UTF-8"/>
					<!-- 宏命令的支持 -->
					<property name="exposeSpringMacroHelpers" value="true"/>
					<property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"/>
					<property name="requestContextAttribute" value="rc"/>
				</bean>
			</entry>
		</map>
	</property>
</bean>

<!-- freemarker config -->
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer" id="freeMarkerConfigurer">
	<property name="templateLoaderPath" value="/WEB-INF/ftl/"/>
	<property name="freemarkerSettings">
		<props>
			<prop key="template_update_delay">5</prop>
			<prop key="default_encoding">UTF-8</prop>
			<prop key="locale">zh_CN</prop>
		</props>
	</property>
</bean>

<!-- 日志拦截器-->
<bean class="com.xxx.core.web.LogNDCInteceptor" id="logNDCInteceptor"/>
<!-- 权限拦截器-->
<bean class="com.xxx.userplatform.mvc.MyPermissionsInteceptor" id="myPermissionsInteceptor"/>
<!-- RequestHelper拦截器-->
<bean class="com.xxx.core.web.MyRequestHelperInteceptor" id="myRequestHelperInteceptor"/>
<!-- 用户信息拦截器-->
<bean class="com.xxx.userplatform.mvc.MyUserInfoInteceptor" id="myUserInfoInteceptor"/>
<!-- 注解请求映射 -->
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
	<property name="interceptors">
		<list>
			<!-- 日志拦截器 -->
			<ref bean="logNDCInteceptor"/>
			<!-- RequestHelper拦截器-->
			<ref bean="myRequestHelperInteceptor"/>
			<!-- 权限拦截器-->
			<ref bean="myPermissionsInteceptor"/>
			<!-- 用户信息拦截器-->
			<ref bean="myUserInfoInteceptor"/>
		</list>
	</property>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
	<property name="messageConverters">
		<list>
			<ref bean="byteArray_hmc"/>
			<ref bean="string_hmc"/>
			<ref bean="resource_hmc"/>
			<ref bean="source_hmc"/>
			<ref bean="xmlAwareForm_hmc"/>
			<ref bean="jaxb2RootElement_hmc"/>
			<ref bean="jackson_hmc"/>
		</list>
	</property>
</bean>
<!-- 处理.. -->
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" id="byteArray_hmc"/>
<!-- 处理.. -->
<bean class="org.springframework.http.converter.StringHttpMessageConverter" id="string_hmc"/>
<!-- 处理.. -->
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter" id="resource_hmc"/>
<!-- 处理.. -->
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter" id="source_hmc"/>
<!-- 处理.. -->
<bean class="org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter" id="xmlAwareForm_hmc"/>
<!-- 处理.. -->
<bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter" id="jaxb2RootElement_hmc"/>
<!-- 处理json-->
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" id="jackson_hmc"/>


<!-- 总错误处理-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" id="exceptionResolver">
	<property name="exceptionMappings">
		<props>
		<!-- 上传文件大于最大尺寸后转向出错页面 -->
		<prop key="org.springframework.web.multipart.MaxUploadSizeExceededException"> redirect:/uploadError.jsp </prop>
		</props>
	</property>

	<property name="defaultErrorView">
		<value>forward:/error.jsp</value>
	</property>

	<property name="defaultStatusCode">
		<value>200</value>
	</property>

	<property name="warnLogCategory">
		<value>org.springframework.web.servlet.handler.SimpleMappingExceptionResolver
		</value>
	</property>
</bean>

<!-- 允许对静态资源文件的访问 -->
<mvc:default-servlet-handler/>

<!-- 数据源 ,DBCP连接池-->
<bean class="org.apache.commons.dbcp.BasicDataSource" id="dataSource" destroy-method="close">
	<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
	<property name="url" value="jdbc:oracle:thin:@192.168.3.141:1521:xxx"/>
	<property name="username" value="xxxdb"/>
	<property name="password" value="xxxdb"/>
	<property name="initialSize" value="2"/>
	<property name="maxActive" value="10"/>
	<property name="maxIdle" value="10"/>
	<property name="maxWait" value="1000"/>
	<property name="poolPreparedStatements" value="true"/>
</bean>

<!-- JNDI数据源 
	<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> 
		<property name="jndiName">
			 <value>jdbc/xxx</value> 
		 </property> 
	</bean> 
-->


<!-- JDBC模板 -->
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
	<property name="dataSource" ref="dataSource"/>
</bean>

<!-- 事务管理器 -->
<bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
	<property name="dataSource" ref="dataSource"/>
</bean>

<!-- 用注解来实现事务管理 -->
<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"/>

<!-- 用于持有ApplicationContext,可以使用SpringContextHolder.getBean('xxxx')的静态方法得到spring bean对象 -->
<bean class="com.xxxxx.SpringContextHolder" lazy-init="false"/></beans>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值