Spring MVC 基本配置

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiaolyuh123/article/details/68926630

1、Spring MVC基本配置

Spring MVC的定制配置需要我们的配置类继承WebMvcConfigurerAdapter类(Adapter适配器),并在此类加上@EnableWebMvc注解,来开启对Spring MVC的配置支持,这样我们就可以重写这个类的方法,来完成我们的配置。如果不加@EnableWebMvc注解,重写这些方法也无效。


2、静态资源配置

2.1 点睛

程序的静态文件(js、css、图片等)需要直接访问,这时我们可以在配置里重写addResourceHandlers方法类实现。

2.2 示例

1、添加静态资源
我们在src/main/resources下建立assets/js目录,并复制jquery.js到这个目录,如图:

配置代码:
package com.chenfeng.xiaolyuh.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

/**
 * MVC 配置类。这里我们配置了一个jsp的ViewResolver,用来映射路径和实际页面的位置,
 * 其中@EnableWebMvc注解会开启一些默认的配置,如一些ViewResolver或者MessageConverter。
 * 
 * Spring MVC的定制配置需要我们的配置类继承WebMvcConfigurerAdapter类(Adapter适配器),
 * 并在此类加上@EnableWebMvc注解,来开启对Spring MVC的配置支持,这样我们就可以重写这个类的方法,
 * 来完成我们的配置。如果不加@EnableWebMvc注解,重写这些方法也无效。
 * @author yuhao.wang
 * @Date 2017年3月29日 下午3:41:20
 */
@Configuration
@EnableWebMvc// 开启对Spring MVC的支持,如果不加@EnableWebMvc注解,重写这些方法也无效。
@ComponentScan("com.chenfeng.xiaolyuh")
public class MvcConfig extends WebMvcConfigurerAdapter {// 重写WebMvcConfigurerAdapter类的方法可以对Spring MVC
	
	@Bean
	public InternalResourceViewResolver viewResolver() {
		InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
		viewResolver.setPrefix("/WEB-INF/classes/views/");// 运行时代码会将页面自动编译到/WEB-INF/classes/views/下
		viewResolver.setSuffix(".jsp");
		viewResolver.setViewClass(JstlView.class);
		return viewResolver;
	}
	
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		// addResourceLocations是指文件放置的目录,addResourceHandler是指对外暴露的地址
		registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/assets/");
	}
}


3、拦截器配置

3.1  点睛

拦截器(Interceptor)实现对每一个请求处理前后进行相关的业务处理,类似于Servlet的Filter。
可以让普通的Bean实现HandlerInterceptor接口或者继承HandlerInterceptorAdapter类来实现自定义拦截器。
通过重写WebMvcConfigurerAdapter的addInterceptors方法来注册自定义拦截器。

3.2 示例

计算每一个请求的处理时间
1、拦截器
package com.chenfeng.xiaolyuh.interceptor;

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

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

/**
 * 可以让普通的Bean实现HandlerInterceptor接口或者继承HandlerInterceptorAdapter类来实现自定义拦截器。
 * 这里通过继承HandlerInterceptorAdapter类来实现。
 * @author yuhao.wang
 * @Date 2017年3月31日 下午5:29:32
 */
@Component // 声明成一个Bean
public class DemoInterceptor extends HandlerInterceptorAdapter {
	
	// 请求发生之前执行
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		request.setAttribute("startTime", System.currentTimeMillis());
		System.out.println("请求之前执行");
		return true;
	}
	
	// 请求发生之后执行
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		
		Long startTime = (Long)request.getAttribute("startTime");
		request.removeAttribute("startTime");
		Long endTIme = System.currentTimeMillis();
		System.out.println("请求之后执行");
		System.out.println("本次请求的时间是:" + (endTIme - startTime) + "ms");
	}
}

2、配置类
package com.chenfeng.xiaolyuh.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

import com.chenfeng.xiaolyuh.interceptor.DemoInterceptor;

/**
 * MVC 配置类。这里我们配置了一个jsp的ViewResolver,用来映射路径和实际页面的位置,
 * 其中@EnableWebMvc注解会开启一些默认的配置,如一些ViewResolver或者MessageConverter。
 * 
 * Spring MVC的定制配置需要我们的配置类继承WebMvcConfigurerAdapter类(Adapter适配器),
 * 并在此类加上@EnableWebMvc注解,来开启对Spring MVC的配置支持,这样我们就可以重写这个类的方法,
 * 来完成我们的配置。如果不加@EnableWebMvc注解,重写这些方法也无效。
 * @author yuhao.wang
 * @Date 2017年3月29日 下午3:41:20
 */
@Configuration
@EnableWebMvc// 开启对Spring MVC的支持,如果不加@EnableWebMvc注解,重写这些方法也无效。
@ComponentScan("com.chenfeng.xiaolyuh")
public class MvcConfig extends WebMvcConfigurerAdapter {// 重写WebMvcConfigurerAdapter类的方法可以对Spring MVC
	
	@Autowired
	private DemoInterceptor demoInterceptor;
	
	@Bean
	public InternalResourceViewResolver viewResolver() {
		InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
		viewResolver.setPrefix("/WEB-INF/classes/views/");// 运行时代码会将页面自动编译到/WEB-INF/classes/views/下
		viewResolver.setSuffix(".jsp");
		viewResolver.setViewClass(JstlView.class);
		return viewResolver;
	}
	
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		// addResourceLocations是指文件放置的目录,addResourceHandler是指对外暴露的地址
		registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/assets/");
	}
	
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		// 注册拦截器
		registry.addInterceptor(demoInterceptor);
	}
}

4、@ControllerAdvice

4.1 点睛

        通过@ControllerAdvice,我们可以将对于控制器的全局配置放在同一位置,注解了@Controller的类的方法可使用@ExceptionHandler、@InitBinder、@ModelAttribute注解到方法上,这对所有注解了@RequestMapping的控制器内的方法有效。
        @ExceptionHandler: 用于全局处理控制器里的异常。
        @@InitBinder:用来设置WebDataBinder,WebDataBinder用来自动绑定前台参数到Model中。
        @ModelAttribute:此注解本身的作用是绑定键值对到Model里,此处是让全局的@RequestMapping都能获得在此处设置的键值对。

4.2 示例

1、定制@ControllerAdvice
package com.chenfeng.xiaolyuh.advice;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.ModelAndView;

@ControllerAdvice// 声明一个控制器建言,@ControllerAdvice组合了@Component注解,所以自动注册成Spring的一个Bean。
public class HandlerAdvice {
	Logger log = LoggerFactory.getLogger(HandlerAdvice.class);
	
	@ExceptionHandler(value = Exception.class)// 全局异常处理,可以通过value设置全局拦截条件
	public ModelAndView exception(Exception exception, WebRequest request) {
		ModelAndView modelAndView = new ModelAndView("error");// 跳转到Error页面
		modelAndView.addObject("errorMessage", exception.getMessage());
		log.debug(exception.getMessage(), exception);
		return modelAndView;
	}
	
	@ModelAttribute
	public void addAttributes(Model model) {
		
		//使用@ModelAttribute注解将键值对添加到全局,所有注解了@RequestMapping的地方都可以获得此键值对
		model.addAttribute("msg", "额外信息"); 
	}

	@InitBinder //通过注解定制WebDataBinder
	public void initBinder(WebDataBinder webDataBinder) {
		webDataBinder.setDisallowedFields("id"); //设置,忽略request参数的id
	}
}

2、控制器
package com.chenfeng.xiaolyuh.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import com.chenfeng.xiaolyuh.entity.DemoObj;

@Controller
public class AdviceController {
	Logger log = LoggerFactory.getLogger(AdviceController.class);
	
	@RequestMapping("/advice")
	public String getSomething(@ModelAttribute("msg") String msg,DemoObj obj){//1
		log.debug("参数id:" + obj.getId());
		log.debug("参数name:" + obj.getName());
		throw new IllegalArgumentException("非常抱歉,参数有误/"+"来自@ModelAttribute:"+ msg);
	}

}

3、异常页面
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>@ControllerAdvice Demo</title>
</head>
<body>
	${errorMessage}
</body>
</html>

5、其他配置

5.1  快捷的ViewController

配置页面跳转的代码
	@RequestMapping("index")
	public String hello() {
		// 通过InternalResourceViewResolver的Bean配置,说明我们的放置路径是/WEB-INF/classes/views/index.jsp
		return "index";
	}	

此处无任何业务逻辑处理,只是简单的页面转向,写了至少三行有效代码;在实际开发中回涉及大量的页面跳转,如果都这样写很麻烦,我们可以通过在配置类中重写addViewControllers这个方法来简化配置:
	@Override
	public void addViewControllers(ViewControllerRegistry registry) {
		// 重定向
		registry.addRedirectViewController("index3", "index");
		// 直接配置请求路径(index3)和页面(index.jsp)之间的映射。
		// 无任何业务逻辑只是简单的业务逻辑可以这样子写,代码更简洁,管理集中
		registry.addViewController("index2").setViewName("index");
	}

这样写代码更简洁,管理更集中。

5.2 路径参数配置

在Spring MVC中,路劲参数如果带“.”的话,“.”后面的值将会被忽略,列如,访问http://localhost:8080/spring-mvc-student/advice?id=1&name=xx.yy,此时“.”后面的yy会被忽略。
我们可以通过重写configurePathMatch方法可以不忽略“.”,代码如下:
	@Override
	public void configurePathMatch(PathMatchConfigurer configurer) {
		configurer.setUseSuffixPatternMatch(false);
	}
PathMatchConfigurer文档地址:http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/PathMatchConfigurer.html


展开阅读全文

没有更多推荐了,返回首页