Spring面试题

一、Spring常用注解

    @Configuration 把一个类作为一个IoC容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean

    @Scope 注册 作用域

    @Lazy(true) 表示延迟初始化

    @Service 用于标注业务层组件

    @Controller 用于标注控制层组件

    @Repository 用于标注数据访问组件,即DAO组件

    @Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

    @Scope用于指定scope作用域的(用在类上)

    @PostConstructor 用于指定初始化方法(用在方法上)

    @PreDestroy 用于指定销毁方法(用在方法上)

    @Resource 默认按名称装配,当找不到名称匹配的bean时,才会按照类型装配。

    @DependsOn 定义Bean初始化及销毁时的顺序

    @Primary 自动装配时,如果出现多个Bean的候选者,被注解为@Primary的Bean将作为首选者,否则将抛出异常

    @Autowired 默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。(@AutoWired @Qqualifier("personDaoBean"))

    @Async 异步方法调用

   @ComponentScan 自动扫描包路径下面的所有@Controller、@Service、@Repository、@Component的类

二、SpringMVC配置拦截器

1.自定义拦截器,实现HandlerInterceptor接口。

public class AuthInterceptor extends HandlerInterceptorAdapter {

	/**
	* 进入Handler方法之前执行
	* 用于身份认证、身份授权
	* 比如身份认证,如果认证没有通过,表示当前用户没有登录,需要此方法拦截不再向下执行
	*/
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		return true;
	}

	/**
	* 执行完Handler完成执行此方法
	* 应用场景:统一异常处理,统一日志处理
	*/
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		
	}

	/**
	* 进入Handler方法之后,返回modelAndView之前执行
	* 应用场景从modelAndView出发,将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图
	*/
	@Override
	public void postHandle(HttpServletRequest request,HttpServletResponse,Object handler,ModelAndView modelAndView) throws Exception {
	
	}
}

2.mvc配置文件中指定拦截器Bean

applicationContext-mvc.cml:

<mvc:interceptors>  
    <!-- 国际化操作拦截器 如果采用基于(请求/Session/Cookie)则必需配置 --> 
	<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />  
	<!-- 如果不定义 mvc:mapping path 将拦截所有的URL请求 -->
	<bean class="com.fescotech.common.base.interceptor.AuthInterceptor"></bean>
</mvc:interceptors>

三、如何处理异常?

Spring提供了多种方式将异常转为响应:

  • 特定的Spring异常将会自动映射为指定的HTTP状态码;
  • 异常上添加@ResponseStatus注解,从而将其映射为某个HTTP状态码;
  • 在方法上可以添加@ExceptionHandler注解,使其用来处理异常

3.1将异常映射为HTTP状态码

在默认情况下,Spring会将自身的一些异常自动转换为合适的状态码。

Spring异常

HTTP状态码
BindException400-Bad Request
ConversionNotSupportException500-Interal Server Error
HttpMediaTypeNotAcceptableException406-Not Acceptable
HttpMediaTypeNotSupportdException415-Unsupported Media Type
HttpMessageNotReadableException400-Bad Request
HttpMessageNotWritableException500-Internal Server Error
HttpRequestMethodNotSupportedException405-Method Not Allowed
MethodArgumentNotValidException400-Bad Request
MissingServletRequestParameterException400-Bad Request
MissingServletRequestPartException400-Bad Request
NoSuchRequestHandlingMethodException404-Not Found
TypeMismatchException400-Bad Request

上表的异常一般回由Spring自身抛出,作为DispatcherServlet处理过程中或执行校验时出现问题的结果。

以上异常为内置的映射结果,对于应用出现的问题无能为力。此时需要Spring提供的@ResponseStatus注解,将异常映射为HTTP状态码。

3.2 @ResponseStatus注解将异常映射为HTTP状态码

以下为Controller代码示例,方法中抛出一个自定义异常SpittleNotFoundExeption

@RequestMapping(value="/{spittleId}",method=RequestMethod.GET)
public String spittle(@PathVariable("spittleId") long spittleId,Model model){
    Spittle spittle = spittleRepository.findOne(spittleId);
    if(spittle == null){
        //抛出自定义异常
        throw new SpittleNotFoundException();
    }
    model.addAttribute(spittle);
    return "spittle";
}

创建一个自定义的非检查型异常,继承RuntimeException,类上加注解@ResponseStatus。该注解的两个属性:value是被映射成的HTTP状态码,reason是自定义的异常出现原因。

package spittr.web;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(value=HttpStatus.NOT_FOUND,reason="Spittle Not Found")
public class SpittleNotFoundException extends RuntimeException{
    //自定义逻辑
}

如此的话,当控制器抛出SpittleNotFoundException异常时,响应会具有404状态码,原因是“Spittle Not Found”。

3.3编写异常处理的方法

上面提到的两种处理情况,都是将项目中的异常转为HTTP错误。如果我们想在响应中还包含所产生的错误的时候,就需要按照处理请求的方式来处理异常。

下面是我们直接在方法中处理异常的方法,先捕获到DuplicateException异常,然后在处理逻辑中将响应转至duplicate路径。

@RequestMapping(method=RequestMethod.POST)
public String saveSpittle(SpittleForm form,Model model){
    try{
        spittleRepository.save(new Spittle(null,form.getMessage(),new Date(),form.getLongitude(),form.getLatitude()));
        return "redirect:/spittles";
    }catch(DuplicateSpittleException e){
        return "error/duplicate";
    }
}

这个方法没有问题,但是我想让这个方法更简单,让saveSpittle()方法只关注正确的路径,让其他方法去处理异常。

把异常方法处理逻辑去掉:

@RequestMapping(method=RequestMethod.POST)
public String saveSpittle(SpittleForm form,Model model){
    spittleRepository.save(new Spittle(null,form.getMessage(),new Date(),form.getLongitude(),form.getLatitude()));
    return "redirect:/spittles";
}

再在Controller中添加一个新方法,处理抛出的DuplicateException:

@ExceptionHandler(DuplicateException.class)
public String handleDuplicateSpittle(){
    return "error/duplicate";
}

在handleDuplicateException方法上添加ExceptionHandler注解,当抛出DuplicateException异常时,将会委托这个方法来处理。

ExceptionHandler标注的方法,能处理同一个控制器中所有处理器方法抛出的异常。

所以SpittleController中所有处理器方法抛出的DuplicateException异常,都会被handleDuplicateSpittle这个方法来处理。

3.4控制器通知实现统一处理异常

控制器通知(Controller Advice)不是用来专门处理异常,我只描述通过控制器通知方式来处理异常的实现。

控制器通知要解决的问题是:将控制器类的特定切面能运用到整个应用程序的所有控制器中,但又避免出现重复相同的代码。

Spring3.2引入了控制器通知,它是一个带有@ControllerAdvice注解的类,这个类包含一个或多个如下类型方法:

  • @ExceptionHandler注解标注的方法
  • @InitBinder注解标注的方法
  • ModelAttribute注解标注的方法。

在带有@ControllerAdvice注解的类中,以上所述的这些方法会运用到整个应用程序所有控制器中带有@RequestMapping注解的方法上。

@ControllerAdvice注解本身已经使用了@Component,因此@ControllerAdvice注解所标注的类会自动被组件扫描获取到,就像带有@Component注解的类一样。

@ControllerAdvice最实用的场景就是将所有的@ExceptionHandler方法收集到一个类中,这样所有控制器的异常就能在一个地方进行一致的处理。

例如,我们将DuplicateSpittleException的处理方法应用到整个应用程序的所有控制器上,下面AppWideExceptionHandler就能做到:

package spittler.web;
import org.spring.framework.web.bind.annotation.ControllerAdvice;
import org.spring.framework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class AppWideExceptionHandler{
    
    @ExceptionHandler(DuplicateSpittleException.class)
    public String duplicateSpittleHandler(){
        return "error/duplicate";
    }

    @ExceptionHandler(RecordNotFoundException.class)
    public String recordNotFoundHandler(){
        return "error/notfound";
    }
    
    //后面还可以再补充其他的异常处理方法
}

现在,如何任何控制器方法抛出DuplicateSpittleException异常,或者RecordNotFoundException异常,都会来这个控制器通知类中来匹配相应的方法来进行处理。

 

 

转载于:https://my.oschina.net/alexjava/blog/1927257

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值