Java-SpringMVC配置详解

概念

  • SpringMVC是Spring的一部分。
  • 什么是MVC?
    • M(dao、service)V(html、jsp)C(Servlet)
    • 他是纯Java实现的
    • 核心三要素
      • 处理器映射器:(BeanNameUrlHandlerMapping)
      • 处理器适配器:(SimpleControllerHandlerAdapter)
      • 视图解析器:(InternalResourceViewResolver)
  • idea如何创建简单的web项目(基于Maven)?
    • 新建父工程
    • 在父工程中new一个module(普通Maven)
    • 右击该module,依次点击Add Frameworks Support->Web Application
  • 官方文档:https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#spring-web

一个简单的Servlet

  • Maven添加servlet-api,jsp-api依赖(其他spring-webmvc等此处省略)
    
    <dependency>
        <groupId>javax.servletgroupId>
        <artifactId>servlet-apiartifactId>
        <version>2.5version>
        <scope>providedscope>
    dependency>
    
    
    <dependency>
        <groupId>javax.servletgroupId>
        <artifactId>jsp-apiartifactId>
        <version>2.0version>
        <scope>providedscope>
    dependency>
    
  • 新建web项目(参考本文:idea如何创建简单的web项目(基于Maven)?)
  • 新建类,让它继承HttpServlet类,并重写里边的doGet()、doPost()方法等
    public class MyServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String msg = "hello.";
            String action = req.getParameter("action");
            if (action.equals("add")) {
                msg = "执行了add方法。。。";
            }
            req.getSession().setAttribute("msg", msg);
            req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req, resp);
        }
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doGet(req, resp);
        }
    }
    
  • 在web.xml中配置servlet
    <servlet>
        <servlet-name>MyServletservlet-name>
        <servlet-class>cn.cnyasin.servlet.MyServletservlet-class>
    servlet>
    <servlet-mapping>
        <servlet-name>MyServletservlet-name>
        <url-pattern>/servleturl-pattern>
    servlet-mapping>
    
  • idea设置中添加Application Servers:Tomcat(参考idea相关笔记)

为什么要学习SpringMVC?

  • 特点
    • 轻量级,简单易学
    • 高效,基于请求响应的MVC架构
    • 于Spring兼容性好,无缝结合
    • 预定大于配置
    • 功能强大:restful、数据验证、格式化、本地化、主题等
    • 关键是都在用
    • 所有的请求都是围绕DispatcherServlet[调度Servlet]设计

一个基于XML配置的SpringMVC

  • 新建web项目(参考本文:idea如何创建简单的web项目(基于Maven)?)
  • 确定导入了依赖
  • 配置web.xml,注册DispatcherServlet
    
    <servlet>
        <servlet-name>app1servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
        <init-param>
            
            <param-name>contextConfigLocationparam-name>
            <param-value>classpath:app1-servlet.xmlparam-value>
        init-param>
        
        <load-on-startup>1load-on-startup>
    servlet>
    <servlet-mapping>
        <servlet-name>app1servlet-name>
        <url-pattern>/url-pattern>
    servlet-mapping>
    
  • 新建Spring配置:classpath:app1-servlet.xml
    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
           http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    ">
        
        <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
        
        <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
        
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
            
            <property name="prefix" value="/WEB-INF/jsp/"/>
            
            <property name="suffix" value=".jsp"/>
        bean>
        
        <bean name="/hello" class="cn.cnyasin.controller.HelloController"/>
    beans>
    
  • 新建jsp目录:/WEB-INF/jsp/
  • 新建一个控制器类,让其实现Controller接口
    package cn.cnyasin.controller;
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.mvc.Controller;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    public class HelloController implements Controller {
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            ModelAndView view = new ModelAndView();
            view.addObject("msg", "hello.");
            view.setViewName("hello");
            return view;
        }
    }
    
  • 在jsp目录新建视图文件:/WEB-INF/jsp/hello.jsp
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    hello
    ${msg}
    
    
  • idea设置中添加Application Servers:Tomcat(参考idea相关笔记)
  • run
  • 问题:
    • 配置无误,页面404?
      • 排查module下是否有lib目录并且加载了全部依赖:Project Structure -> Artifacts -> 你的module -> WEB-INF -> lib

一个基于注解的SpringMVC

  • 新建web项目(参考本文:idea如何创建简单的web项目(基于Maven)?)
  • 确定导入了依赖
  • 配置web.xml,注册DispatcherServlet
    
    <servlet>
        <servlet-name>app1servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
        <init-param>
            
            <param-name>contextConfigLocationparam-name>
            <param-value>classpath:app1-servlet.xmlparam-value>
        init-param>
        
        <load-on-startup>1load-on-startup>
    servlet>
    <servlet-mapping>
        <servlet-name>app1servlet-name>
        <url-pattern>/url-pattern>
    servlet-mapping>
    
  • 新建Spring配置:classpath:app1-servlet.xml
    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xsi:schemaLocation="
           http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
        
        <context:component-scan base-package="cn.cnyasin"/>
        
        <mvc:default-servlet-handler/>
        
        <mvc:annotation-driven/>
        
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
            
            <property name="prefix" value="/WEB-INF/jsp/"/>
            
            <property name="suffix" value=".jsp"/>
        bean>
    beans>
    
  • 新建jsp目录:/WEB-INF/jsp/
  • 新建一个控制器类,添加注解
    package cn.cnyasin.controller;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    @Controller
    public class AnnotationController {
        @RequestMapping("/annotation")
        public String annotation(Model model){
            model.addAttribute("msg", "annotation...");
            return "annotation"; // return 视图文件名
        }
    }
    
  • 在jsp目录新建视图文件:/WEB-INF/jsp/annotation.jsp
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    
    annotation
    ${msg}
    
    
  • 排查module下是否有lib目录并且加载了全部依赖:Project Structure -> Artifacts -> 你的module -> WEB-INF -> lib
  • idea设置中添加Application Servers:Tomcat(参考idea相关笔记)
  • run

一个restful风格的SpringMVC

  • 具体步骤跟上边的基本一样,这里仅记录Controller代码
    package cn.cnyasin.controller;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.*;
    @Controller
    public class RestfulController {
        /* 方式一 */
        @RequestMapping("/rest/test/{a}/{b}")
        /* 方式二 */
        // @RequestMapping(path = "/rest/test/{a}/{b}", method = RequestMethod.GET)
        /* 方式三 */
        // @RequestMapping(value = "/rest/test/{a}/{b}", method = RequestMethod.GET)
        /* 方式四 */
        // @GetMapping("/rest/test/{a}/{b}")
        // @PostMapping("/rest/test/{a}/{b}")
        public String test(@PathVariable int a, @PathVariable int b, Model model) {
            int sum = a + b;
            model.addAttribute("msg", sum);
            return "restful";
        }
    }
    

重定向redirect

  • 语法:return "redirect:/foo/bar";
    // @PostMapping("/rest/test/{a}/{b}")
    public String test(@PathVariable int a, @PathVariable int b, Model model) {
        int sum = a + b;
        model.addAttribute("msg", sum);
        //return "redirect:/index.jsp";
        return "redirect:/rest/test2";
    }
    @GetMapping("/rest/test2")
    public String test2(Model model) {
        model.addAttribute("msg", "redirect ok...");
        return "restful";
    }
    

获取参数

  • 建议所有参数都加上@RequestParam()
    package cn.cnyasin.controller;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    @Controller
    public class EncodingController {
        @RequestMapping("/encoding/test1")
        public String test1(@RequestParam("data") String data, Model model) {
            model.addAttribute("msg", data);
            return "encoding";
        }
    }
    

处理乱码问题

  • 方式一:你可以自己写一个类,让其实现Filter接口,然后重写doFilter方法,然后注册到web.xml
    • 自定义过滤器:MyFilter.java
      package cn.cnyasin.utils;
      import javax.servlet.*;
      import java.io.IOException;
      public class MyFilter implements Filter {
          public void init(FilterConfig filterConfig) throws ServletException {}
          public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
              request.setCharacterEncoding("utf-8");
              response.setCharacterEncoding("utf-8");
              chain.doFilter(request, response);
          }
          public void destroy() {}
      }
      
    • web.xml中添加:
      
      <filter>
          <filter-name>MyFilterfilter-name>
          <filter-class>cn.cnyasin.utils.MyFilterfilter-class>
      filter>
      <filter-mapping>
          <filter-name>MyFilterfilter-name>
          
          <url-pattern>/*url-pattern>
      filter-mapping>
      
  • 方式二:SpringMVC提供了强大的乱码过滤器,只需要在web.xml中添加:
    
    <filter>
        <filter-name>encodingfilter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
        <init-param>
            <param-name>encodingparam-name>
            <param-value>utf-8param-value>
        init-param>
    filter>
    <filter-mapping>
        <filter-name>encodingfilter-name>
        
        <url-pattern>/*url-pattern>
    filter-mapping>
    

JSON格式数据传输

  • 实现方式
    • 方式一
      • 控制器使用@RestController注解
      • 方法正常注解@RequestMapping、@GetMapping等
      • 示例代码
        @RestController
        public class JsonController {
            @RequestMapping("/json/test1")
            public String test1(){
                return "test1";
            }
        }
        
    • 方拾二
      • 控制器使用@Controller注解
      • 方法除了使用正常注解@RequestMapping、@GetMapping等以外,额外添加一个@ResponseBody注解
      • 示例代码
        @Controller
        public class JsonController {
            @RequestMapping("/json/test1")
            @ResponseBody
            public String test1(){
                return "test1";
            }
        }
        
  • 处理JSON乱码
    • 方式一:produces参数(不推荐)
      @RequestMapping(value = "/json/test1", produces = "application/json;charset=utf-8")
      
    • 方式二:SpringMVC统一乱码解决(推荐)
      • 在spring-mvc.xml中添加如下代码(此方法需要导入jackson依赖)
        
        <mvc:annotation-driven>
            <mvc:message-converters register-defaults="true">
                <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                    <constructor-arg value="UTF-8"/>
                bean>
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                    <property name="objectMapper">
                        <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
                            <property name="failOnEmptyBeans" value="false"/>
                        bean>
                    property>
                bean>
            mvc:message-converters>
        mvc:annotation-driven>
        

Jackson使用

  • 结合上一节“JSON格式数据传输”代码
  • Maven导入Jackson依赖
    
    <dependency>
        <groupId>com.fasterxml.jackson.coregroupId>
        <artifactId>jackson-databindartifactId>
        <version>2.12.5version>
    dependency>
    
  • 更新lib目录,确定加入Jackson依赖
  • 在控制器类中要使用json传输数据的方法中使用
    @RestController
    public class JsonController {
        // @RequestMapping(value = "/json/test1", produces = "application/json;charset=utf-8")
        @RequestMapping(value = "/json/test1")
        public String test1() throws JsonProcessingException {
            HashMap user = new HashMap();
            user.put("id", 123);
            user.put("name", "张三");
            user.put("age", 12);
            List userList = new ArrayList();
            userList.add(user);
            HashMap data = new HashMap();
            data.put("total", 10);
            data.put("userList", userList);
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonStr = objectMapper.writeValueAsString(data);
            return jsonStr;
        }
    }
    

Fastjson使用

  • 使用方法类似“Jackson”,但是据说bug较多,此处就不练习了
  • Maven导入Jackson依赖
    
    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>fastjsonartifactId>
        <version>1.2.76version>
    dependency>
    

SSM整合

  • 依赖:
    • Junit(junit)
    • 数据库驱动(mysql-connector-java)
    • 连接池(默认、c3p0、dhcp、druid等)
    • Servlet(servlet-api)
    • JSP(jsp-api,jstl)
    • Mybatis(mybatis)
    • Mybatis-Spring(mybatis-spring)
    • Spring(spring-mvc,spring-jdbc)
  • 整合分层后配置文件列表(具体文件内容已经单独列为一个文件夹:SSM分层配置)
    • /pom.xml
    • /web/WEB-INF/web.xml
    • /classpath:jdbc.properties
    • /classpath:mybatis-config.xml
    • /classpath:applicationContext.xml
    • /classpath:spring-mvc.xml
    • /classpath:spring-service.xml
    • /classpath:spring-dao.xml
  • 整合分层后以书籍查询为例代码演示
    • cn.cnyasin.pojo.Book.jsva
      package cn.cnyasin.pojo;
      public class Book {
          private int id;
          private String name;
          private int status;
          private long createdAt;
          // getter,setter...
      }
      
    • cn.cnyasin.dao.BookMapper.java
      package cn.cnyasin.dao;
      import cn.cnyasin.pojo.Book;
      import java.util.List;
      public interface BookMapper {
          // 增加
          int insertOne(Book book);
          // 修改
          int updateOne(Book book);
          // 删除
          int deleteOne(int id);
          // 一个
          Book getOne(int id);
          // 所有
          List<Book> getAll();
      }
      
    • cn.cnyasin.dao.BookMapper.xml
      
      DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      <mapper namespace="cn.cnyasin.dao.BookMapper">
          
          <insert id="insertOne" parameterType="book">
              insert into book (`name`, `status`, `created_at`)
              values (#{name}, #{status}, #{createdAt})
          insert>
          
          <update id="updateOne" parameterType="book">
              update book set `name` = #{name} where id = #{id}
          update>
          
          <delete id="deleteOne" parameterType="int">
              delete from book where id = #{id}
          delete>
          
          <select id="getOne" resultType="book">
              select * from book where id = #{id}
          select>
          
          <select id="getAll" resultMap="bookList">
              select * from book
          select>
          <resultMap id="bookList" type="book">
              <result property="createdAt" column="created_at"/>
          resultMap>
      mapper>
      
    • cn.cnyasin.service.BookService.java
      package cn.cnyasin.service;
      import cn.cnyasin.pojo.Book;
      import java.util.List;
      public interface BookService {
          // 增加
          int insertOne(Book book);
          // 修改
          int updateOne(Book book);
          // 删除
          int deleteOne(int id);
          // 一个
          Book getOne(int id);
          // 所有
          List<Book> getAll();
          // 事务测试:插入&删除&查全部
          List<Book> insertDeleteGetAll(Book book);
      }
      
    • cn.cnyasin.service.BookServiceImpl.java
      package cn.cnyasin.service;
      import cn.cnyasin.dao.BookMapper;
      import cn.cnyasin.pojo.Book;
      import java.util.List;
      public class BookServiceImpl implements BookService {
          private BookMapper bookMapper;
          public void setBookMapper(BookMapper bookMapper) {
              this.bookMapper = bookMapper;
          }
          public int insertOne(Book book) {
              return bookMapper.insertOne(book);
          }
          public int updateOne(Book book) {
              return bookMapper.updateOne(book);
          }
          public int deleteOne(int id) {
              return bookMapper.deleteOne(id);
          }
          public Book getOne(int id) {
              return bookMapper.getOne(id);
          }
          public List<Book> getAll() {
              return bookMapper.getAll();
          }
          public List<Book> insertDeleteGetAll(Book book) {
              bookMapper.insertOne(book);
              int i = 10 / 0;
              bookMapper.deleteOne(15);
              return bookMapper.getAll();
          }
      }
      
    • cn.cnyasin.controller.BookController.java
      package cn.cnyasin.controller;
      import cn.cnyasin.pojo.Book;
      import cn.cnyasin.service.BookService;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.beans.factory.annotation.Qualifier;
      import org.springframework.stereotype.Controller;
      import org.springframework.ui.Model;
      import org.springframework.web.bind.annotation.RequestMapping;
      import java.util.List;
      @Controller
      public class BookController {
          @Autowired
          @Qualifier("bookServiceImpl")
          private BookService bookService;
          @RequestMapping("/book/list")
          public String getAllBook(Model model) {
              List<Book> list = bookService.getAll();
              model.addAttribute("list", list);
              return "bookList";
          }
          @RequestMapping("/book/insert")
          public String insertDeleteGetAll(Model model) {
              Book book = new Book();
              book.setName("哈喽啊");
              book.setStatus(1);
              book.setCreatedAt(new Date().getTime() / 1000);
              bookService.insertDeleteGetAll(book);
              return "redirect:/book/list";
          }
      }
      
    • WEB-INF/index.jsp
      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      
      
        bookList
        
      
      
      
      
      
      
    • WEB-INF/jsp/bookList.jsp
      <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
      <%@ page contentType="text/html;charset=UTF-8" language="java" %>
      
      
          bookList
          
      
      
      

      书籍列表

      编号 名字 状态 时间
      ${book.id} ${book.name} ${book.status} ${book.createdAt}

SpringMVC拦截器(Interceptor)

  • 概念?
    • 类似于Servlet开发中的过滤器Filter,不过Filter是Tomcat容器部分的功能,而SpringMVC拦截器是spring的功能。
    • 拦截器是Spring的AOP思想的具体应用。
  • 过滤器和拦截器区别
    • 过滤器Filter
      • 是Servlet规范中的一部分,任何JavaWeb工程都可以拥有
      • 在url-pattern中配置了/*以后,可以对所有要访问的资源过滤
    • 拦截器
      • 是SpringMVC自己的
      • 拦截器只会拦截控制器方法,不会拦截任何静态资源
  • 如何使用拦截器
    • 自定义拦截器类,让其实现HandlerInterceptor接口,重写里边的三个方法
    • 然后在Spring的配置文件中注入拦截器配置
  • 核心代码
    • /web/WEB-INF/web.xml
      
      <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
               version="4.0">
      
          
          <servlet>
              <servlet-name>springmvcservlet-name>
              <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
              <init-param>
                  <param-name>contextConfigLocationparam-name>
                  <param-value>classpath:applicationContext.xmlparam-value>
              init-param>
              <load-on-startup>1load-on-startup>
          servlet>
          <servlet-mapping>
              <servlet-name>springmvcservlet-name>
              <url-pattern>/url-pattern>
          servlet-mapping>
      
          
          <filter>
              <filter-name>encodingfilter-name>
              <filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
              <init-param>
                  <param-name>encodingparam-name>
                  <param-value>utf-8param-value>
              init-param>
          filter>
          <filter-mapping>
              <filter-name>encodingfilter-name>
              <url-pattern>/*url-pattern>
          filter-mapping>
      web-app>
      
    • classpath:applicationContext.xml
      
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:context="http://www.springframework.org/schema/context"
             xmlns:mvc="http://www.springframework.org/schema/mvc"
             xsi:schemaLocation="
             http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
             http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
             http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
      
          
          <context:component-scan base-package="cn.cnyasin.controller"/>
          
          <mvc:default-servlet-handler/>
          
          <mvc:annotation-driven/>
      
          
      
          
      
          
          <mvc:interceptors>
              <mvc:interceptor>
                  <mvc:mapping path="/**"/>
                  <bean class="cn.cnyasin.interceptor.TokenInterceptor"/>
              mvc:interceptor>
          mvc:interceptors>
      beans>
      
    • cn.cnyasin.controller.Testcontroller.java
      package cn.cnyasin.controller;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RestController;
      @RestController
      public class TestController {
          @RequestMapping("/test/test1")
          public String test1() {
              return "{json}";
          }
      }
      
    • cn.cnyasin.interceptor.TokenInterceptor.java
      package cn.cnyasin.interceptor;
      import org.springframework.web.servlet.HandlerInterceptor;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      public class TokenInterceptor implements HandlerInterceptor {
          public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
              String token = request.getParameter("token");
              System.out.println(token);
              if (null == token || !token.equals("token")) {
                  request.getRequestDispatcher("/").forward(request, response);
              }
              return true;
          }
      }
      

你可能感兴趣的:(Spring,Java,java,spring,SpringMVC,JSON,SSM)