第4章 Spring MVC 4.x

2018-12-06  本文已影响0人  意大利大炮

4.1 Spring MVC概述

4.2 Spring MVC项目快速搭建

4.2.1 构建maven项目

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.spring</groupId>
    <artifactId>springmvcDemo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <jsp.verion>2.2</jsp.verion>
        <jstl.version>1.2</jstl.version>
        <servlet.version>3.1.0</servlet.version>

        <!-- spring -->
        <spring-framework.version>4.1.5.RELEASE</spring-framework.version>

        <!-- logging -->
        <logback.version>1.0.13</logback.version>
        <slf4j.version>1.7.5</slf4j.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring-framework.version}</version>
        </dependency>


        <!-- 其他web依赖 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>${jstl.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${servlet.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>${jsp.verion}</version>
            <scope>provided</scope>
        </dependency>

        <!-- spring and Transactions -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring-framework.version}</version>
        </dependency>

        <!-- 使用slf4J 和 LogBack作为日志 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${logback.version}</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>${logback.version}</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-access</artifactId>
            <version>${logback.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
4.2.2 日志配置
<?xml version="1.0" encoding="UTF-8" ?>
<configuration scan="true" scanPeriod="1 seconds">
    <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
        <resetJUL>true</resetJUL>
    </contextListener>

    <jmxConfigurator/>

    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>logback: %d{HH:mm:ss.SSS} %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <logger name="org.springframework.web" level="DEBUG"/>
    <root level="info">
        <appender-ref ref="console"/>
    </root>
</configuration>
4.2.3 演示页面
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
</head>
<body>
    <pre>
        Welcome to Spring MVC world
    </pre>
</body>
</html>
4.2.4 SpringMVC配置
@Configuration
@EnableWebMvc
@ComponentScan("com.springmvcDemo")
public class MyMvcConfig {
    public InternalResourceViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/classes/views/");
        viewResolver.setSuffix(".jsp");
        viewResolver.setViewClass(JstlView.class);
        return viewResolver;
    }
}
4.2.5 Web配置
public class WebInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        // 注册
        ctx.register(MyMvcConfig.class);
        // 关联
        ctx.setServletContext(servletContext);

        ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
        servlet.addMapping("/");
        servlet.setLoadOnStartup(1);
    }
}
4.2.6 简单控制器
@Controller
public class HelloController {

    @RequestMapping("/index")
    public String hello() {
        return "index";
    }
}
4.2.7 运行

4.3 Spring MVC 的常用注解

4.3.1 常用注解
4.3.2 使用示例
<dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
            <version>2.5.3</version>
        </dependency>

只纯支持json的依赖

  <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.5.3</version>
        </dependency>

创建一个对象,用于演示获取request对象参数和返回此对象到response
jackson对对象和json做转换时,一定需要一个空的构造方法???

public class DemoObj {
    private Long id;
    private String name;
    public DemoObj() {
        super();
    }
    public DemoObj(Long id, String name) {
        this.id = id;
        this.name = name;
    }
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

创建演示控制器

@Controller   // 表明是一个控制器
@RequestMapping("/anno")  // 映射此类的访问路径
public class DemoAnnoContraoller {

    @RequestMapping(produces = "text/plain;charset=UTF-8")   // 未设置路径,所以使用类级别的路径;produces可指定返回的response的媒体类型和字符集
    public @ResponseBody String index(HttpServletRequest request) {  // 演示可接收HttpServletRequest作为参数
        return "url:" + request.getRequestURL() + "can access";
    }

    @RequestMapping(value = "/pathvar/{str}", produces = "text/plain;charset=UTF-8")  // 演示可接收路径参数,并在方法参数前结合@PathVariable使用
    public @ResponseBody String demoPathVar(@PathVariable String str, HttpServletRequest request) {
        return "url:" + request.getRequestURL() + "can access, str" + str;
    }

    @RequestMapping(value = "/requestParam/", produces = "text/plain;charset=UTF-8")  // 演示常规的request参数获取,访问路径为/anno/requestParam?id=1
    public @ResponseBody String passRequestParam(Long id, HttpServletRequest request) {
        return "url:" + request.getRequestURL() + "can access, id" + id;
    }

    @RequestMapping(value = "/obj", produces = "application/json;charset=UTF-8") // 演示直接解释参数到对象,访问路径为/anno/obj?id=1&name=xx
    @ResponseBody       // 演示@ResponseBody注解可以用到方法上
    public String passObj(DemoObj obj, HttpServletRequest request) {
        return "url:" + request.getRequestURL() + "can access, obj id" + obj.getId() + " obj name: " + obj.getName();
    }

    @RequestMapping(value = {"/name1", "/name2"}, produces = "text/plain;charset=UTF-8")  // 演示映射不同的路径到相同的方法上,访问路径为/anno/name1或/anno/name2
    public @ResponseBody String remove(HttpServletRequest request) {
        return "url:" + request.getRequestURL() + "can access";
    }
}

演示rest方式的控制器

@RestController
@RequestMapping("/rest")
public class DemoRestController {

    // 演示返回对象自动解析为json
    @RequestMapping(value = "/getJson", produces = "application/json;charset=UTF-8")
    public DemoObj getJson(DemoObj obj) {
        return new DemoObj(obj.getId() + 1, obj.getName() + "yy");
    }

    // 演示返回对象为xml
    @RequestMapping(value = "/getJson", produces = "application/xml;charset=UTF-8")
    public DemoObj getXml(DemoObj obj) {
        return new DemoObj(obj.getId() + 1, obj.getName() + "yy");
    }
}

4.4 Spring MVC的基本配置

public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {
    public WebMvcConfigurerAdapter() {
    }
    public void addFormatters(FormatterRegistry registry) {
    }
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    }
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
    }
    public Validator getValidator() {
        return null;
    }
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
    }
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
    }
    public void configurePathMatch(PathMatchConfigurer configurer) {
    }
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    }
    public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
    }
    public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> exceptionResolvers) {
    }
    public MessageCodesResolver getMessageCodesResolver() {
        return null;
    }
    public void addInterceptors(InterceptorRegistry registry) {
    }
    public void addViewControllers(ViewControllerRegistry registry) {
    }
    public void configureViewResolvers(ViewResolverRegistry registry) {
    }
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
    }
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    }
}

WebMvcConfigurer:


public interface WebMvcConfigurer {
    void addFormatters(FormatterRegistry var1);

    void configureMessageConverters(List<HttpMessageConverter<?>> var1);

    void extendMessageConverters(List<HttpMessageConverter<?>> var1);

    Validator getValidator();

    void configureContentNegotiation(ContentNegotiationConfigurer var1);

    void configureAsyncSupport(AsyncSupportConfigurer var1);

    void configurePathMatch(PathMatchConfigurer var1);

    void addArgumentResolvers(List<HandlerMethodArgumentResolver> var1);

    void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> var1);

    void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> var1);
    // 注册拦截器
    void addInterceptors(InterceptorRegistry var1);

    MessageCodesResolver getMessageCodesResolver();
    // 无任何事务处理,只是简单页面转向的简化配置
    void addViewControllers(ViewControllerRegistry var1);

    void configureViewResolvers(ViewResolverRegistry var1);
    // 增加静态文件映射
    void addResourceHandlers(ResourceHandlerRegistry var1);

    void configureDefaultServletHandling(DefaultServletHandlerConfigurer var1);
}
4.4.1 静态资源映射

/**
 * 测试,静态资源映射
 */
@Configuration
@EnableWebMvc
@ComponentScan("com.springmvcDemo.resource_handlers")
public class MyMvcConfig extends WebMvcConfigurerAdapter {
    
    // 类似于xml的<mvc: resource />的静态资源映射配置
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 指定目录下的本地文件映射为一个url,使得可以直接访问
        registry.addResourceHandler("/views/**").addResourceLocations("classpath:/views/");
    }
}
4.4.2 拦截器配置
  1. 让Bean实现HanlderInterceptor接口或者继承HandlerInterceptorAdapter类来实现拦截器
  2. 通过重写WebMvcConfigurerAdapter 的addInterceptors方法来注册自定义的拦截器
    实现一个拦截器:
public class DemoInterceptor implements HandlerInterceptor {
    // 请求前调用
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        httpServletRequest.setAttribute("startTime", System.currentTimeMillis());
        return true;
    }
    // 请求后调用
    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("本次请求处理时间为:" + (System.currentTimeMillis() - (long) httpServletRequest.getAttribute("startTime")));
    }
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    }
}

注册拦截器到配置Bean:

    @Bean
    public DemoInterceptor demoInterceptor() {
        return new DemoInterceptor();
    }
    // 注册拦截器
    @Autowired 
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(demoInterceptor());
    }
4.4.3 @ControllerAdvice(建言)
@ControllerAdvice //生命一个控制器建言,此注解组合了@Component注解
public class DemoHandlerAdvice {
    // 定义全局异常处理,拦截所有的Exception
    @ExceptionHandler(value = Exception.class)
    public ModelAndView exception(Exception exception, WebRequest request) {
        ModelAndView modelAndView = new ModelAndView("error");
        modelAndView.addObject("errorMsg", exception.getMessage());
        return modelAndView;
    }
    // 将键值对添加到全局,所有注解@RequestMappering的方法都可以获得此键值对
    @ModelAttribute
    public void addAttributes(Model model) {
        model.addAttribute("msg", "额外信息");
    }
    // 定制WebDataBinder
    @InitBinder
    public void initBinder(WebDataBinder webDataBinder) {
        webDataBinder.setDisallowedFields("id"); // 这里过滤掉了Id,即后台无法获取到该字段
    }
}

创建演示的控制器

@Controller
public class AdviceController {
    @RequestMapping("/advice")
    public String getSomething(@ModelAttribute("msg") String msg, DemoObj demoObj) { // 这里接收msg和demoObj,但demoObj中的id无法获取到了
        throw new IllegalArgumentException("非常抱歉,参数有误");
    }
}
4.4.4 其他配置
  1. ViewController
    正常的页面转向代码:
// 演示简单页面转向
    @RequestMapping("/index")
    public String hello() {
        return "index";
    }

通过重写addViewController方法来简化:

    @Autowired
    // 配置页面转向
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("index").setViewName("index");
    }

4.5 Spring MVC的高级配置

4.5.1 文件上传配置
4.5.2 自定义HttpMessageConverter
上一篇下一篇

猜你喜欢

热点阅读