Java框架——SpringMVC(三)

SpringMVC的拦截器

拦截用户的请求,拦截时间在处理器映射器映射出要执行的处理器类,并且找到对应的处理器适配器,在适配器执行处理器之前拦截;
拦截器会和处理器绑定在一起,作为一个处理器执行链,返回给中央调度器
1.自定义拦截器需要实现HandlerInterceptor接口,重写其中3个方法:
preHandle方法在处理器执行前调用
		有一个boolean类型返回值,返回false时会拦截跳转处理器的请求执行到此处就不会向下执行
postHandle方法在处理器执行后调用
afterCompletion在中央调度器将数据返回浏览器之前的最后时刻调用
public class MyInterceptor implements HandlerInterceptor {
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
			//处理器执行之前调用拦截器的preHandle---------
		String attribute =(String) request.getSession().getAttribute("user");
		if("beijing".equals(attribute)) {
			return true ;
		}
		request.getRequestDispatcher("/fail.jsp").forward(request, response);
		return false;
		//返回false时会拦截跳转处理器的请求,执行到此处就不会向下执行
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		//处理器执行之后调用拦截器的postHandle--------
		System.out.println("postHandle---------");
		
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		//在中央调度器将数据返回浏览器之前的最后时刻调用
		System.out.println("afterCompletion---------");
		
	}

}
2.在springmvc中注册拦截器
当任意请求到达处理器前后都会经过这个拦截器的方法
<!-- 拦截器的注册 -->
<mvc:interceptors>
	<mvc:interceptor>
		<mvc:mapping path="/**"/><!-- 对所有多级路径进行拦截 -->
		<bean class="com.handlers.MyInterceptor"></bean>
	</mvc:interceptor>
</mvc:interceptors>
3.调用处理器方法测试
@Controller
@RequestMapping("/test")
public class MyController {
	@RequestMapping("/register.do")
	@ResponseBody
	public Object fun() {
		System.out.println("执行处理器方法");
		return 123.456;
	}
}
/*
执行顺序:
处理器执行之前拦截器的preHandle---------
执行处理器方法
处理器执行之后拦截器的postHandle---------
拦截器的afterCompletion---------
*/

多个拦截器

多个拦截器的注册
<!-- 多个拦截器的注册 -->
<mvc:interceptors>
	<mvc:interceptor>
		<mvc:mapping path="/**"/>
		<bean class="com.handlers.OneInterceptor"></bean>
	</mvc:interceptor>
	<mvc:interceptor>
		<mvc:mapping path="/**"/>
		<bean class="com.handlers.TwoInterceptor"></bean>
	</mvc:interceptor>
</mvc:interceptors>
多个拦截器的执行顺序
OneInterceptor处理器执行之前拦截器的preHandle---------
TwoInterceptor处理器执行之前拦截器的preHandle---------
执行处理器方法
TwoInterceptor处理器执行之后拦截器的postHandle---------
OneInterceptor处理器执行之后拦截器的postHandle---------
TwoInterceptor拦截器的afterCompletion---------
OneInterceptor拦截器的afterCompletion---------
如果OneInterceptor的preHandle方法返回false,则后面都不会执行

拦截器的afterCompletion与preHandle方法

preHandle方法执行后(即返回值为true),那afterCompletion就一定会执行,无论后续的拦截器是否放行请求
preHandle方法未执行或者返回值为false,那afterCompletion都不会执行

权限拦截

只有登录的用户的请求才能进入处理器进行业务处理,在拦截器的方法中设置权限拦截	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		String requestURI = request.getRequestURI();//获取请求中URI
		if(!requestURI.contains("/login")){
		//如果不是去登录的请求就判断用户是否登录,是否有资格访问
			String username = (String) request.getSession().getAttribute("USER_SESSION");
			if(null == username){
			//session中没有用户数据直接跳转登录页面
				response.sendRedirect(request.getContextPath() + "/login.do");
				return false;
			}
		}
		return true;
		
	}
在处理器对于登录成功用户将登录信息放入session中
	@RequestMapping(value = "/login.do",method = RequestMethod.GET)
	//get方式的请求直接去登录页面
	public String login(){
		return "login";
	}
	@RequestMapping(value = "/login.do",method = RequestMethod.POST)
	//post方式的请求验证通过后将数据添加到session中
	public String login(String username
			,HttpSession httpSession){
		httpSession.setAttribute("USER_SESSION", username);
		return "redirect:welcome";
	}

SpringMVC执行流程

浏览器发出请求达到中央调度器,中央调度器首先判断是否是multipart请求(处理文件上传的请求)
无论是否都会交给处理器映射器(找到对应的处理器,和拦截器一起封装为一个处理器执行链)
如何找到对应的处理器?就是将所有的处理器映射器放入一个集合,然后遍历
根据请求找到对应处理器映射器,再找到处理器,将处理器和拦截器封装为处理器执行链.

将处理器执行链返回中央调度器,中央调度器根据处理器找到对应的处理器适配器
将所有的处理器适配放入一个集合在遍历,与处理器匹配,找到对应的处理器适配器
再拿处理器适配器去调用处理器(处理器执行前会调用拦截器的preHandle方法)

处理器返回ModelAndView(处理器执行前会调用拦截器的postHandle方法)
适配器直接将这个ModelAndView返回给中央调度器,中央调度器拿到ModelAndView将之给了视图解析器
视图解析器将之渲染(调用View对象的render方法,传入数据,View对象自己完成渲染,将这个对象封装为response对象响应给浏览器)
之后调用拦截器的afterCompletion方法

视图解析器:将ModelAndView的数据解析,将逻辑视图转换为物理视图,将物理视图返回给中央调度器,此时物理视图已经是一个View对象
中央调度器再调用View对象(实质是一个模板),将数据填充到View中,形成一个真正的View对象,
将这个对象封装为response响应给浏览器,渲染就是将数据进行填充

Spring+SpringMVC+Mybatis整合

使用SSM整合完成简单的用户注册
一,配置式开发:
1.导入相关jar包
2.配置web.xml
	a.Spring配置文件的位置
	b.ServletContext的监听器
	c.SpringMVC的字符编码过滤器
	d.SpringMVC的中央调度器
<!-- Spring:指定Spring配置文件的位置及名称 -->
<context-param>
	<param-name>contextConfigLocation</param-name>
	<!-- 这个值是ContextLoaderListener类的父类的属性,Servlet标签也需要 -->
	<param-value>classpath:resources/spring-*.xml</param-value>
	<!-- Spring配置文件的位置是resources包下以spring-开头,xml结尾的文件 -->
</context-param>
<!-- Spring:注册ServletContext监听器 -->
<listener>
	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
3.form表单提交数据
<form action="${pageContext.request.contextPath}/test/register.do" method="POST">
	姓名:<input type="text" name="name"/>
	年龄:<input type="text" name="age"/>
	<input type="submit" value="注册"/>
</form>
4.处理器
配置式需要实现Controller接口,在处理器中调用Service
public class StudentController implements Controller {
	private IStudentService service;//使用spring完成注入需要set方法
	public void setService(IStudentService service) {
		this.service = service;
	}
	@Override
	public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String name = request.getParameter("name");
		Integer age = Integer.valueOf(request.getParameter("age"));
		Student student = new Student(name,age);
		service.addStudent(student);
		return null;
	}
}
其中处理器的注册和service属性的注入需要在SpringMVC中配置
	<!-- 处理器的id值是请求的路径 -->
	<bean id="/test/register.do" class="com.handles.StudentController">
		<property name="service" ref="studentService"></property>
		<!-- name属性值为处理器中service参数名 
			ref为service实现类的bean标签的id值			
	-->
	</bean>
5.创建servlce及其实现类
//在实现类中调用Dao
public class StudentServiceImpl implements IStudentService {
	private IStudentDao dao;
	public void setDao(IStudentDao dao) {
		this.dao = dao;
	}
	@Override
	public void addStudent(Student student) {
		dao.insertStudent(student);		
	}
}
service实体类的注册和dao属性的注入
spring-service.xml
<bean id="studentService" class="com.service.IStudentServiceImpl">
<!-- private IStudentDao dao;  前两个字母大写,ref的值就是类名,前1个字母大写就是类名首字母小写-->
		<property name="dao" ref="IStudentDao"></property>
	</bean>
6.在dao层创建接口操作数据库,需要对应的xml文件
public interface IStudentDao {
	void insertStudent(Student student);
}
<mapper namespace="com.dao.IStudentDao">
	<!-- namespace为接口全类名,id值为方法名 -->
	<insert id="insertStudent" >
		insert into student (name,age) values(#{name},#{age})
	</insert>			 
</mapper>
在mybatis.xml中注册接口文件位置
<mappers>
	<package name="com.dao" />
</mappers>
spring-mybatis.xml中配置sqlSessionFactory
<!-- 注册SqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
	<property name="configLocation" value="classpath:resources/mybatis.xml"></property>
	<property name="dataSource" ref="dataSource"></property>
	<!-- dataSource数据源在spring-db.xml中注册 -->
</bean>
<!-- 注册Dao的代理对象 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
	<property name="basePackage" value="com.dao"></property>
</bean>
操作数据库还需要事务管理的配置文件spring-tx.xml
	<!-- 注册事务管理器 -->
	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 注册事务通知 -->
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="add*" isolation="DEFAULT" propagation="REQUIRED" />
		</tx:attributes>
	</tx:advice>
	<!-- AOP配置 -->
	<aop:config>
		<aop:pointcut expression="execution(* *..service.*.*(..))"
			id="studentPointcut" /><!-- 指定切入点 ,id值任意-->
		<aop:advisor advice-ref="txAdvice" pointcut-ref="studentPointcut"/><!-- 指定通知,将通知织入哪一个切入点 -->
	</aop:config>
整合无法运行原因分析:
1.spring的jar包版本号不一致导致版本冲突
2.辅助jar包过低无法匹配Spring的jar包
3.c3p0-0.9.1.2.jar数据源的版本太低
注意c3p0-0.9.5.2.jar需要配合依赖包mchange-commons-java-0.2.11使用

二,全注解式开发
1.springmvc不需要实现Controller
直接在处理器上加注解@Controller表示这是一个处理器类
service属性的注册使用@Autowired或者@Qualifier()等完成注入
@Controller
@RequestMapping("/test")
public class StudentController  {
	//@Autowired 
	@Qualifier("studentService")//值为@Service注解中的值
	//@Resource(name="studentService") 三种方式任选一个
	private IStudentService service;
需要在spring-service配置文件中自动完成service的注册
使用的时候直接使用类名首字母小写表示这个bean 
如果是自定义bean的名称需要在service类中@Service("studentService")注解中定义bean名称
<!--注意:不能与SpringMVC的组件扫描器的扫描路径重复,会出错-->
<context:component-scan base-package="com.service"/>
在service实现类上添加注解@Service("studentService")表示这是一个service类并定义bean名称
默认的事务注解@Transactional
@Service("studentService")
public class IStudentServiceImpl implements IStudentService {
	@Resource(name="IStudentDao")
	private IStudentDao dao;
	public void setDao(IStudentDao dao) {
		this.dao = dao;
	}
	@Override
	@Transactional //事务注解,有默认配置
	public void addStudent(Student student) {
		dao.insertStudent(student);
		
	}
使用事务注解需要事务注解驱动
<!--事务注解配置文件,需要事务管理器和事务注解驱动
 --> 
	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 注册事务注解驱动 -->
	<tx:annotation-driven transaction-manager="transactionManager"/>
mybatis的注解,为了开发效率,mybatis可以只需要配置式就可以
mybatis的注解式就是删除SQL映射文件,在方法上添加注解和SQL语句,其他都不用修改
public interface IStudentDao {
	@Insert("insert into student (name,age) values(#{name},#{age})")
	void insertStudent(Student student);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值