Spring基础篇

Spring基础

spring容器是什么?

用于管理对象的

如何启动spring容器?

1.导包
2.添加配置文件 这个配置文件用于告诉spring容器创建哪些对象

如何创建对象?(如何让容器帮我们创建对象?).
方式一:使用无参构造器(重点)
第一步:给类添加无参构造器.
第二步:在配置文件中配置bean元素.
第三步:调用容器的getBean方法来获得对象.

方式二:使用静态工厂方法(使用较少)
调用这个类的静态方法来创建对象.

方式三:使用实例工厂方法来创建对象(使用较少)
调用对象的实例方法来创建对象.
创建对象的三种方式配置

作用域

默认情况下,容器对于某个Bean只会创建一个实例.
作用域

生命周期

容器不仅可以帮我们创建对象,还可以初始化,调用,销毁等,管理对象的生命周期.
初始化方法:使用init-method属性指定初始化方法
spring容器在创建对象之后会立即调用对象的初始化方法.

销毁方法:使用destroy-method属性指定销毁方法
在容器关闭之前会销毁对象,销毁对象就会调用对象的销毁方法,只有作用域为单例时,才会执行销毁方法.

package scope;

public class MessageBean {
	public MessageBean() {
		System.out.println("MessageBean()");
	}
	
	public void init() {
		System.out.println("init()");
	}
	
	public void sendMessage() {
		System.out.println("sendMessage");
	}
	
	public void destroy() {
		System.out.println("destroy()");
	}
}

生命周期

关于spring容器的延迟加载(了解)

spring容器启动后,会将所有作用域为单例的bean对象创建好,但是前提条件是该bean的配置为单例,而不为prototype
如果我们不想要容器启动后就加载单例对象,那么使用lazy-init属性

IOC(Inversion of Controll)控制反转

什么是IOC?
对象之间的依赖关系由容器来建立.

DI(Dependency Injection)是什么?
容器通过调用对象提供的set方法,或者构造器来建立依赖关系.
注:IOC是目标,DI是手段。

set方式注入

第一步:提供相应的set方法.

package ioc;

public class A {
	
	private IB b;
	
	public void setB(IB b) {
		System.out.println("setB()");
		this.b=b;
	}
	
	public A() {
		System.out.println("A()");
	}
	
	public void excute() {
		System.out.println("excute()");
		b.f1();
	}
}

第二步:配置property元素.
在这里插入图片描述

构造器方式注入

第一步:添加相应的构造器.

package ioc2;

public class A {
	
	private B b;
	
	public A() {
		System.out.println("A()");
	}
	
	
	
	public A(B b) {
		System.out.println("A(B)");
		this.b = b;
	}



	public void excute() {
		System.out.println("excute()");
		b.f1();
	}
}

第二步:配置constructor-arg元素.
构造器注入配置

自动装配

什么是自动装配?
指的是spring容器,依据某种规则,自动建立对象之间的依赖关系.
a.默认情况下,容器不会自动装配.
b.可以通过指定autowire属性来告诉容器进行自动装配(容器仍然要通过set注入或者构造器注入来完成依赖关系的建立).

autowire有三个值:①byName,根据属性名来找,然后调用set注入,所以配置的时候id就是属性名,不能错,如果错则注入null.
②byType,根据属性的类型来找,然后调用set注入,但是可能会出现一个类型对应多个bean的出现,会报错.
③constructor:和bytype类似,根据属性的类型来找,但是调用构造器注入,使用得比较少.

注入基本类型的值

value属性

注入集合类型的值

支持4中类型的集合:List,Set,Map,properties

引用的方式注入集合的值

方式配置bean,再按照对象的方式注入.

<bean id="s1" class="com.zxyy.value.SpelBean">
		<property name="name" value="#{vb1.name}"/>
		<property name="city" value="#{vb1.city[0]}"/>
		<property name="score" value="#{vb1.score.english}"/>
		<property name="pageSize" value="#{config.pageSize}"/>
	</bean>
	
	<bean id="vb1" class="com.zxyy.value.ValueBean">
		<property name="name" value="zxyy"/>
		<property name="age" value="30"/>
		<property name="city">
			<list>
				<value>北京</value>
				<value>上海</value>
				<value>广州</value>
				<value>深圳</value>
			</list>
		</property>
		<property name="interest">
			<set>
				<value>唱歌</value>
				<value>跳舞</value>
				<value>运动</value>
				<value>运动</value>
			</set>
		</property>
		<property name="score">
			<map>
				<entry key="math" value="90"/>
				<entry key="chinese" value="20"/>
				<entry key="english" value="3"/>
			</map>
		</property>
		<property name="db">
			<props>
				<prop key="username">zxyy</prop>
				<prop key="password">1234</prop>
			</props>
		</property>
	</bean>
	
	<!-- 将集合的值配置成一个对象 -->
	<util:list id="cityBean">
		<value>北京</value>
		<value>上海</value>
		<value>武汉</value>
	</util:list>
	
	<util:set id="interestBean">
		<value>唱歌</value>
		<value>打球</value>
		<value>跳舞</value>
	</util:set>
	
	<util:map id="scoreBean">
		<entry key="math" value="20"/>
		<entry key="chinese" value="3"/>
		<entry key="english" value="2"/>
	</util:map>
	
	<util:properties id="propBean">
		<prop key="username">zx</prop>
		<prop key="password">12</prop>
	</util:properties>
	<!-- 将集合对象当成一个bean注入 -->
	<bean id="vb2" class="com.zxyy.value.ValueBean">
		<property name="city" ref="cityBean"/>
		<property name="interest" ref="interestBean"/>
		<property name="score" ref="scoreBean"/>
		<property name="db" ref="propBean"/>
	</bean>
	
	<!-- spring容器会读取properties文件
		并将读取的数据封装在Properties对象中,我们可以使用容器的getBean方法来获取文件中的信息
		
		配置如下:
		location=classpath:(...)
	 -->
	 <util:properties id="config" location="classpath:config.properties" />
	 

使用spring表达式

使用spring表达式的目的就是为了读取其他bean的值.

注解

如果按照上述方法配置bean,那么XML文件会越写越大,越写越复杂,这和我们的目的不一致,所以就有了使用注解简化配置.
(1)组件扫描
什么是组件扫描?
spring容器在启动之后,会扫描指定的包及其子包下面的所有的类,如果该类前面有特定的注解,则spring容器就会管理该bean.
(2)如何添加组件扫描
第一步:在类前添加注解.
第二步:在配置文件中添加组件扫描 <context:component-scan base-package="".

依赖注入相关的注解

@Autowired和@Qualifier

a.该注解支持set方式的注入和构造器方式的注入.
b.当采用set方式注入时,可以将@Autowired注解写在set方法前面,如果不使用@Qualifier,容器就会按照byType的方式注入,
有可能出错,所以就配合使用@Qualifier注解来明确指出要注入的bean的id.
注意:也可以将这两个注解直接添加到属性前,更可以不用写set方法.
c.当采用构造器方式注入时,可以直接将这两个注解添加到对应的构造器方法上即可.

@Resource

a.该注解只支持set方式注入.
b.可以将该注解添加到set方法前,使用name属性指定要注入的bean的id,如果不指定就将按照byType的方式注入.
注意:也可以将该注解添加到属性前.

注解的方式使用spring表达式

@Value注解

a.可以使用该注解来注入基本类型的值.
b.也可以使用该注解来使用spring表达式.
c.该注解可以添加到属性前,也可以添加到属性对应的set方法前.

springMVC

springmvc是什么

是一个MVC框架,用来简化基于MVC架构的web应用开发

五大组件

①DispatcherServlet(核心):接受请求,依据HandlerMapping的配置调用相应的模型来处理.
②HandlerMapping:包含了请求路径与模型的对应关系.
③Controller:负责处理业务逻辑.
④ModelAndView:封装处理结果(处理结果除了数据之外还可能有视图名).
⑤ViewResolver:DispatcherServlet依据ViewResolver的解析调用真正的视图对象来生成相应的页面.

五大组件的关系

a.DispatcherServlet收到请求,依据HandlerMapping的配置,调用相应的Controller.
b.Controller将处理结果封装成ModelAndView对象,返回给DispatcherServlet.
c.DispatcherServlet根据ViewResolver的解析,调用相应的视图对象来生成相应的页面.

编程步骤
第一步:导包.
第二步:添加spring配置文件.
第三步:配置DispatcherServlet.
第四步:写Controller,实现Controller接口.
第五步:配置HandlerMapping.

使用注解来开发基于springMVC的web应用

step1:导包
step2:添加spring配置文件
step3:配置dispatcherServlet
step4: 写Controller
step5: 写jsp
step6:在spring配置文件中,添加如下配置:
a.配置组件扫描
b.添加注解扫描
c.配置视图解析器
基本配置

如何读取请求参数值?

有三种方式:
1.通过请求对象,request.
2.通过@RequestParam注解.
3.使用javaBean封装请求参数值:
step1:写一个javabean,这个类应该有一些属性,属性名称跟请求参数名一样并提供get,set方法.
step2:将该javabean作为方法的形参.

向页面传值

1.使用request
将数据绑定到request上,然后转发到某个jsp。
注:springmvc默认使用转发.
2.使用ModelAndView
将数据封装到ModelAndView里,然后将该对象作为方法的返回值
3.使用ModelMap
将对象作为方法的形参,将数据绑定到ModelMap对象中
4.使用session

重定向

如果方法的返回值是String

在重定向地址前添加“redirect:”

如果方法的返回值是ModelAndView

RedirectView rv = new RedirectView("toIndex.do);
return new ModelAndView(rv);

案例:

package controller;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;

/**
 * 如何使用注解写一个处理器
 * 1.不用实现Controller接口
 * 2.可以在处理器中,添加多个方法,每个方法可以处理一种类型的请求
 * 3.方法名不作要求,返回类型可以是ModelAndView,也可以是String
 * 4.使用@Controller,将该处理器纳入容器进行管理(也就是说在spring的配置文件中不用再配置该处理器了)
 * 5.使用@RequestMapping,告诉前端控制器(DispatcherServlet),请求路径与处理方法的对应关系。
 * 		spring配置文件不用再配置handlerMapping了。
 * @author zxyy
 *
 */
@Controller
@RequestMapping("/login")
public class HelloController {
	@RequestMapping("/hello.do")
	public String hello() {
		System.out.println("hello()");
		return "hello";
	}
	
	@RequestMapping("/toLogin.do")
	public String toLogin() {
		System.out.println("toLogin()");
		return "login";
	}
	
	@RequestMapping("/login.do")
	//读取请求参数值得第一种方式,通过request对象
	public String login1(HttpServletRequest req) {
		System.out.println("login1()");
		String admin = req.getParameter("adminCode");
		String password = req.getParameter("password");
		System.out.println("adminCode = "+admin+", pwd = "+password);
		return "index";
	}
	
	@RequestMapping("login2.do")
	//读取请求的第二种方式:使用注解
	public String login2(String adminCode,
			@RequestParam("password")String pwd) {
		System.out.println("login2()");
		System.out.println("adminCode = "+adminCode+", pwd = "+pwd);
		return "index";
	}
	
	//读取请求参数值得第三种方式:将请求参数封装成Javabean的方式
	@RequestMapping("login3.do")
	public String login3(AdminParam ap) {
		System.out.println("login3()");
		System.out.println("adminCode = " +ap.getAdminCode()+
				", password = "+ap.getPassword());
		return "index";
	}
	
	@RequestMapping("login4.do")
	//向页面传值的第一种方式,使用request
	public String login4(AdminParam ap,HttpServletRequest req) {
		System.out.println("login4()");
		String adminCode = req.getParameter("adminCode");
		String password = req.getParameter("password");
		//将数据和request绑定在一起
		req.setAttribute("adminCode", adminCode);
		req.setAttribute("password", password);
		//springmvc默认使用转发
		return "index";
	}
	
	@RequestMapping("login5.do")
	//向页面传值的第二种方式,使用ModelAndView对象
	public ModelAndView login5(AdminParam ap) {
		System.out.println("login5()");
		String adminCode = ap.getAdminCode();
		String password = ap.getPassword();
		System.out.println("adminCode = "+adminCode+", password = "+password);
		Map<String,Object> data = new HashMap<String,Object>();
		data.put("adminCode", adminCode);
		data.put("password", password);
		//构造ModelAndView对象
		ModelAndView mav = new ModelAndView("index",data);
		return mav;
	}
	
	//向页面传值的第三种方式,使用ModelMap
	@RequestMapping("login6.do")
	public String login6(AdminParam ap,ModelMap mm) {
		System.out.println("login6()");
		String adminCode = ap.getAdminCode();
		String password = ap.getPassword();
		System.out.println("adminCode = "+adminCode+", password = "+password);
		mm.addAttribute("adminCode", adminCode);
		mm.addAttribute("password", password);
		return "index";
	}
	
	//向页面传值的第四种方式
	@RequestMapping("login7.do")
	public String login7(AdminParam ap,HttpSession session) {
		String adminCode = ap.getAdminCode();
		String password = ap.getPassword();
		System.out.println("adminCode = "+adminCode+", password = "+password);
		session.setAttribute("adminCode", adminCode);
		session.setAttribute("password", password);
		return "index";
	}
	
	//重定向:1.如果返回值是String类型
	@RequestMapping("/login8.do")
	public String login8() {
		System.out.println("login8()");
		return "redirect:toIndex.do";
	}
	
	@RequestMapping("/toIndex.do")
	public String toIndex() {
		System.out.println("toIndex()");
		return "index";
	}
	//重定向:如果返回值是ModelAndView
	@RequestMapping("/login9.do")
	public ModelAndView login9() {
		System.out.println("login9()");
		RedirectView rv = new RedirectView("toIndex.do");
		return new ModelAndView(rv);
	}
}

`

系统分层

表示层:数据展现和控制逻辑

业务层:业务逻辑的处理

持久层:数据访问逻辑

a.上一层通过接口调用下一层提供的服务,比如业务层调用持久层。
b.下一层代码发生改变,上一层无须作出改变。方便代码维护。

案例

登录案例逻辑:
登录逻辑

编码问题:使用过滤器

为什么会有乱码?

表单提交时,浏览器会对中文进行编码,编码方式是按照表单所在页面的编码,比如使用utf-8方式。但是服务器端默认使用ISO-8859-1解码,所以会产生乱码。

如何解决呢?

springMVC帮我们提供了一个过滤器,CharacterEncodingFilter.
我们只需要配置该过滤器即可。
注意:
a.表单提交采用post方式.
b.客户端的编码要和过滤器的编码一样。
在这里插入图片描述

拦截器

什么是拦截器?

spring提供的一个特殊的组件,当DispatcherServlet收到请求,如果有拦截器,先调用拦截器,然后调用相应的处理器处理请求。

注意:过滤器属于Servlet规范,而拦截器属于spring框架。

如何写一个拦截器?

step1:写一个java类,实现HandlerInteceptor接口。

package interceptors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class SomeInterceptor implements HandlerInterceptor{

	/*
	 * DispatcherServlet收到请求之后,会先调用preHandle方法,如果该方法返回值是true,
	*       则继续向后调用,如果返回值是false,则不再向后调用。
	*  handler:描述处理器方法的对象
	 * @see org.springframework.web.servlet.HandlerInterceptor#preHandle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object)
	 */
	public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler)
			throws Exception {
		System.out.println("preHandle()");
		return true;
	}
	
	/*
	 * 处理器的方法已经处理完毕,正准备将处理结果(ModelAndView对象)返回给DispatcherServlet之前
	 * 执行postHandle方法,可以在该方法里面修改处理结果。
	 * @see org.springframework.web.servlet.HandlerInterceptor#postHandle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, org.springframework.web.servlet.ModelAndView)
	 */
	public void postHandle(HttpServletRequest req, HttpServletResponse res, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("postHandle()");
		
	}
	
	/*
	 * 最后执行的方法
	 * 注意:只有当preHandle方法返回值为true时,该方法才会执行
	 * ex是处理器抛出的异常,可以写一个拦截器,用来处理这些异常。
	 * @see org.springframework.web.servlet.HandlerInterceptor#afterCompletion(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object, java.lang.Exception)
	 */
	public void afterCompletion(HttpServletRequest req, HttpServletResponse res, Object handler, Exception ex)
			throws Exception {
		System.out.println("afterCompletion()");
		
	}

}

step2:实现具体的拦截处理逻辑,比如session验证。

step3:配置拦截器。

配置拦截器

异常的处理

可以将异常抛给spring,由spring来处理这些异常。

具体有两种方式:

方式一:使用简单异常处理器:

step1:配置简单异常处理器。

简单异常处理器
step2:添加异常处理页面。

方式二: 使用@ExceptionHandler注解

step1:在处理器类中,添加一个异常处理方法,该方法必须加上@ExceptionHandler注解。

@ExceptionHandler
	//这是一个异常处理方法
	//ex是其他方法抛出的异常
	public String exHandle(Exception ex,HttpServletRequest req) {
		System.out.println("exHandle()");
		//依据异常的不同类型,进行相应的处理
		if(ex instanceof NumberFormatException) {
			req.setAttribute("errorMsg", "请输入正确的数字");
			return "error1";
		}else if(ex instanceof StringIndexOutOfBoundsException) {
			req.setAttribute("errorMsg", "请输入正确的下标");
			return "error1";
		}else {
			return "system_error";
		}
	}

step2:添加处理页面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值