spring mvc+mybatis笔记(二)

spring MVC部分

 

一、处理请求的流程

 

1、  首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;

2、  DispatcherServlet——>HandlerMapping,DispatcherServlet 接收到请求后, 将根据请求信息(包括 URL、 HTTP 方法、请求头、请求参数、 Cookie 等)及 HandlerMapping 的配置找到处理请求的处理器(Handler).可将 HandlerMapping 看成路由控制器,将 Handler 看成目标主机;

3、  DispatcherServlet——>HandlerAdapter,通过 HandlerAdapter 对 Handler 进行封装,再以统一的适配器接口调用 Handler从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;

4、  HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView对象(包含模型数据、逻辑视图名);

5、  ModelAndView的逻辑视图名——> ViewResolver, ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;

6、  View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;

7、返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。

 

二、相关注解说明

@Controller:声明控制器

@Service: 声明Service组

@Repository: 声明Dao组件

@Component:泛指组件(不推荐)

@RequestMapping:将URL映射到整个类或特定的方法上

consumes-指定处理请求的提交内容类型Content-Type,例如 application/json,text/html。
produces-指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回。
value-指定请求的实际地址,指定的地址可以是URI Template 模式。
params-指定request中必须包含某些参数值是,才让该方法处理。
headers-指定request中必须包含某些指定的header值,才能让该方法处理请求。
method-指定请求方式,枚举类RequestMethod。

@Transactional:事务管理(参考:http://www.cnblogs.com/caoyc/p/5632963.html)

事物传播行为介绍:
  @Transactional(propagation=Propagation.REQUIRED) :如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
  @Transactional(propagation=Propagation.NOT_SUPPORTED) :容器不为这个方法开启事务
  @Transactional(propagation=Propagation.REQUIRES_NEW) :不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
  @Transactional(propagation=Propagation.MANDATORY) :必须在一个已有的事务中执行,否则抛出异常
  @Transactional(propagation=Propagation.NEVER) :必须在一个没有的事务中执行,否则抛出异常
  @Transactional(propagation=Propagation.SUPPORTS) :如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.

事务隔离级别:
       @Transactional(isolation = Isolation.DEFAULT):使用数据库默认的隔离级别(默认情况下)
  @Transactional(isolation = Isolation.READ_UNCOMMITTED):读取未提交数据(会出现脏读, 不可重复读) 基本不使用
  @Transactional(isolation = Isolation.READ_COMMITTED):读取已提交数据(会出现不可重复读和幻读)
  @Transactional(isolation = Isolation.REPEATABLE_READ):可重复读(会出现幻读)
  @Transactional(isolation = Isolation.SERIALIZABLE):串行化
大多数数据库的默认隔离级别为: Read Commited,如Sql Server , Oracle.

少数数据库默认的隔离级别为Repeatable Read, 如MySQL InnoDB存储引擎

  • 读未提交:read uncommitted :事物A和事物B,事物A未提交的数据,事物B可以读取到
  • 读已提交:read committed:事物A和事物B,事物A提交的数据,事物B才能读取到
  • 可重复读:repeatable read:事务A和事务B,事务A提交之后的数据,事务B读取不到,事务B是可重复读取数据
  • 串行化:serializable:事务A和事务B,事务A在操作数据库时,事务B只能排队等待

脏读 : 一个事务读取到另一事务未提交的更新数据
不可重复读 : 在同一事务中, 多次读取同一数据返回的结果有所不同, 换句话说, 
后续读取可以读到另一事务已提交的更新数据. 相反, "可重复读"在同一事务中多次
读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事务已提交的更新数据
幻读 : 一个事务读到另一个事务已提交的insert数据

@Resource:  用于注入,( j2ee提供的 ) 默认按名称装配,找不到再按照类型

@Autowired: 用于注入, 默认按类型装配

@PathVariable:注解方法参数并将其绑定到URI模板变量的值。例如:

 

        @ResponseBody
	@RequestMapping(value="load_{name}",produces="application/json;charset=UTF-8")
	public String loadAddress(@PathVariable("name") String name, HttpServletRequest request,HttpServletResponse response) {
		String id = request.getParameter("id");
		UsrAddress add = addressService.loadPrimaryAddress(Long.valueOf(id), 1L);
		System.out.println(name);
		return JSON.toJSONString(add);
	}

@RequestParam:将请求的参数绑定到方法中的参数上。其实即使不配置该参数,注解也会默认使用该参数

@RequestBody:用于content type为json格式请求,可以将请求的json内容,转为javabean。例如:

 

        @ResponseBody
	@RequestMapping(value="test",produces="application/json;charset=UTF-8")
	public String test(@RequestBody UsrAddress add,HttpServletRequest request,HttpServletResponse response) {
		 System.out.println(add.getProvince());
		 return JSON.toJSONString(add);
	}

@ResponseBody:返回的数据不是页面,而是其他文本格式的数据时(如json、xml等)。注意与RequestBody的区别,RequestBody是用于请求数据是json/xml。
@RequestHeader:可以把Request请求header部分的值绑定到方法的参数上。例如:

        @ResponseBody
	@RequestMapping(value="test",produces="application/json;charset=UTF-8")
	public String test(@RequestHeader("Accept-Encoding") String encoding,HttpServletRequest request,HttpServletResponse response) {
		 System.out.println(encoding);
		 return "";
	}

@CookieValue:可以把请求中关于cookie的值绑定到方法的参数上
@SessionAttributes:把数据存储到session中。例如:

@Controller
@RequestMapping(value = "/address")
@SessionAttributes("address")
public class AddressController {
	@Resource
	private IAddressService addressService;
	 
	@RequestMapping(value="test")
	public String test(ModelMap map) {
		UsrAddress  address=new UsrAddress();
		address.setProvince("02");
		map.put("address", address);		
		 return "success";
	}
}

 

@ModelAttribute:可以作用在方法或方法参数上,当它作用在方法上时,该Controller的所有方法在调用前,先执行此@ModelAttribute注解的方法;当作用在方法参数上时,会把请求的参数,赋值到javabean对象,另外还可以从session中取值。例如:

 

        @ResponseBody
	@RequestMapping(value="test1",produces="application/json;charset=UTF-8")
	public String test1(@ModelAttribute("address") UsrAddress  address,HttpServletRequest request,HttpServletResponse response) {
		 System.out.println(address.getProvince());
		 return JSON.toJSONString(address);
	}

三、拦截器

1、继承HandlerInterceptorAdapter,重写需要的方法:

preHandle:该方法将在Controller处理之前进行调用

postHandle:在Controller的方法调用之后,DispatcherServlet进行视图的渲染之前执行,可以修改ModelAndView(preHandle方法的返回值为true时才会执行)

afterCompletion:方法将在整个请求完成之后,也就是DispatcherServlet渲染了视图执行,主要作用是用于清理资源(preHandle方法的返回值为true时才会执行)

afterConcurrentHandlingStarted():这个方法会在Controller方法异步执行时开始执行, 而Interceptor的postHandle方法则是需要等到Controller的异步执行完才能执行。

注:有多个拦截器满足时,先要执行全部拦截器的preHandle,再执行全部拦截器的postHandle,最后执行全部的afterCompletion。执行单个preHandle顺序是按照配置拦截器的先后,执行postHandle和afterCompletion顺序跟配置相反。

2.配置spring-mvc.xml

<mvc:interceptors>  
    <!-- 使用bean定义一个Interceptor,直接定义在mvc:interceptors根下面的Interceptor将拦截所有的请求 -->  
    <bean class="com.lzj.test.interceptor.AllInterceptor"/>  
    <mvc:interceptor>  
        <mvc:mapping path="/address/test1.do"/>  
        <!-- 定义在mvc:interceptor下面的表示是对特定的请求才进行拦截的 -->  
        <bean class="com.lzj.test.interceptor.Interceptor1"/>  
    </mvc:interceptor>  
</mvc:interceptors> 

3.过滤器和拦截器的区别

拦截器是基于Java的反射机制的,而过滤器是基于函数回调。
拦截器不依赖与servlet容器,归spring管理可以使用spring的资源;过滤器依赖与servlet容器
拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用
拦截器更灵活可以多次被调用,而过滤器只能在容器初始化时被调用一次

 

四、容器启动初始化

1.实现spring接口 ApplicationListener<ContextRefreshedEvent>,重写onApplicationEvent方法,实现自己的初始化逻辑

2.spring 配置文件定义bean

<bean class="com.lzj.test.listener.InitListener"/>

五、文件上传

1.spring配置文件定义CommonsMultipartResolver

 

<bean id="multipartResolver"  
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">  
        <!-- 默认编码 -->
        <property name="defaultEncoding" value="utf-8" />  
        <!-- 文件大小最大值 -->
        <property name="maxUploadSize" value="10485760000" />  
        <!-- 内存中的最大值 -->
        <property name="maxInMemorySize" value="40960" />  
    </bean> 

2.Controller代码

 

 

@RequestMapping("springUpload")
	public String springUpload(HttpServletRequest request) {
		try {
			long startTime = System.currentTimeMillis();
			// 将当前上下文初始化给 CommonsMutipartResolver (多部分解析器)
			CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(
					request.getSession().getServletContext());
			// 检查form中是否有enctype="multipart/form-data"
			if (multipartResolver.isMultipart(request)) {
				// 将request变成多部分request
				MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
				// 获取multiRequest 中所有的文件名
				Iterator iter = multiRequest.getFileNames();
				while (iter.hasNext()) {
					// 一次遍历所有文件
					MultipartFile file = multiRequest.getFile(iter.next().toString());
					if (file != null) {
						String path = "D:/"	+ file.getOriginalFilename();
						// 上传
						file.transferTo(new File(path));
					}
				}
			}
			long endTime = System.currentTimeMillis();
			System.out.println("运行时间:" + String.valueOf(endTime - startTime) + "ms");
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "success";
	}

3.jsp页面

 

 

<form name="Form" action="springUpload.do" method="post"  enctype="multipart/form-data">
<h1>使用spring mvc提供的类的方法上传文件</h1>
<input type="file" name="file">
<input type="submit" value="upload"/>
</form>

六、其他

1.Controller跳转其他Controller

return的String为“redirect:/xx/xx.do”

 

 

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值