SpringMVC框架从入门到总结二

json数据交互

案例实现

  1. 导入pom依赖
    说明:springmvc框架,默认使用HttpMessageConverter消息转换器,进行json格式数据转换。需要加入jackson依赖包支持
 <!--依赖管理-->
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.0.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.0.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.9.8</version>
        </dependency>
        <!--Apache的文件解析器-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
    </dependencies>
  1. SpringMVC核心配置文件
<?xml version="1.0" encoding="UTF-8"?>
<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 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- bean definitions here -->
    
	<!--开启包扫描注解-->
    <context:component-scan base-package="cn.itcast.controller"></context:component-scan>
    
	<!--springmvc的注解驱动-->
    <mvc:annotation-driven></mvc:annotation-driven>
	
	<!--视图解析器的前缀和后缀-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="suffix" value=".jsp"></property>
        <property name="prefix" value="/WEB-INF/jsp/"></property>
    </bean>
	
	<!--前端控制器是/,所以要释放静态资源-->
    <mvc:default-servlet-handler></mvc:default-servlet-handler>
</beans>
  1. web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">

    <!--配置前端控制器-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--将springmvc的配置文件交给前端控制器-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:SpringConfig.xml</param-value>
        </init-param>
    </servlet>

    <!--拦截规则-->
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!--乱码过滤器-->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
</web-app>
  1. log4j日志文件
### direct log messages to stdout ###
### 输出源的配置 语法  log4j.appender.输出源的名字=输出源的实现类 ###
### log4j.appender.输出源的名字.属性=属性值   ###
log4j.appender.a=org.apache.log4j.ConsoleAppender
log4j.appender.a.Target=System.out
log4j.appender.a.layout=org.apache.log4j.PatternLayout
log4j.appender.a.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=/home/travel.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss,SSS} [%t] [%c]-[%p] %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###
### 日志记录器的配置,固定语法  log4j.rootLogger=输出级别, 输出源,输出源...  ###
log4j.rootLogger=debug, a,file
  1. MyController
@Controller
public class MyController {
    @RequestMapping("/demo")
    public String demo() {
        return "demo";
    }

    @ResponseBody  //直接声明一个方法,返回值类型是java实体对象类型.在方法上添加@ResponseBody注解通过springmvc转换json
    @RequestMapping("/returnJson")
    public Item returnJson() {
        Item item = new Item();
        item.setName("耳机");
        item.setPrice(1000);
        item.setDetail("详情");
        return item;
    }

    @RequestMapping("/getJson")
    @ResponseStatus(HttpStatus.OK)//void类型,并且没有响应体
    public void getJson(@RequestBody Item item) { //@RequestBody 让springmvc将请求中的json转换成java中的对象
        System.out.println(item);
    }
}

如果一个controller中所有的方法全部都是json返回值,我们直接使用@RestController来替代之前的@Controller

restful支持

restful介绍

  1. restful是一种软件设计风格
  2. restful根据HTTP请求方法:
    POST/GET/PUT/DELETE,定义了资源的操作方法:新增/查询/修改/删除
  3. restful风格的优点:
    结构清晰、符合标准、易于理解、 扩展方便、请求的url更加简洁,得到越来越多网站的采用

案例实现

步骤:

  /**
     *  restful风格:
     *  需求:
     *      /item/1   get     查询id为1的商品信息
     *      /item/1   delete  删除id为1的商品
     *      /item/1   put     更新id为1的商品
     *      /item     post     新增
     *
     *  步骤:
     *      1.后台需要4个方法来处理请求.但是这4个方法映射的路径是一样,只是限定请求的方式不一样
     *      2.前端发送请求,请求的地址一样,但是请求的方式不一样:
     *          a.通过rest插件发送put和delete请求
     *          b.springmvc提供了一个HiddenHttpMethodFilter,将所有的POST请求转换成对应的post或者delete或者get或者put请求
     *            根据POST请求中的_method参数的值进行转换
     */

RestfulController

@Controller
public class RestfulController {

    @RequestMapping(value = "/item/{id}", method = RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    public void queryItemById(@PathVariable("id") String id) {
        System.out.println("查询商品:" + id);
    }

    @RequestMapping(value = "/item/{id}", method = RequestMethod.DELETE)
    @ResponseStatus(HttpStatus.OK)
    public void deleteItemById(@PathVariable String id) {
        System.out.println("删除商品:" + id);
    }

    @RequestMapping(value = "/item/{id}", method = RequestMethod.PUT)
    @ResponseStatus(HttpStatus.OK)
    public void updateItemById(@PathVariable String id) {
        System.out.println("修改商品:" + id);
    }

    @RequestMapping(value = "/item/{id}", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    public void add() {
        System.out.println("添加商品");
    }

}

前端页面请求:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    <form action="/item/1" method="post">
        <input type="hidden" name="_method" value="GET">
        <input type="submit" value="get请求">
    </form>

    <form action="/item/2" method="post">
        <input type="hidden" name="_method" value="DELETE">
        <input type="submit" value="delete请求">
    </form>

    <form action="/item/3" method="post">
        <input type="hidden" name="_method" value="PUT">
        <input type="submit" value="put请求">
    </form>

    <form action="/item/1" method="post">
        <input type="hidden" name="_method" value="POST">
        <input type="submit" value="post请求">
    </form>
</body>
</html>

web.xml
请求方式过滤器

<!--请求方式过滤器-->
<filter>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

@PathVariable注解

请求中,路径中的变量

路径中的变量:
 *      变量格式 : {变量名}
 *
 *     获取路径中的变量格式   @PathVariable(变量名)
 *                      如果变量名和方法名一样,  直接写@PathVariable

文件上传

servlet中的文件上传

  •   前端
      a.请求的方式必须是post类型.
      b.inpute type=file 文件标签
      c.enctype=multipart/form-data
    
  •   后台servlet
      a.在servlet上添加一个注解,用来解析文件上传的这种数据格式类型
      b.直接使用request.getPart();获取文件
    

文件上传三要素

  • 表单的提交方式 method=“POST”
  • 表单的enctype属性是多部分表单形式 enctype=“multipart/form-data"
  • 表单项(元素)type=“file”
<form action="" method="post" enctype="multipart/form-data">
    姓名:<input type="text" name="username"> <br>
	头像:<input type="file" name="picFile"> <br>
</form>

SpringMVC实现文件上传

案例实现

步骤:

  /**
     *  springmvc的文件上传:
     *   前端:
     *      a.请求的方式必须是post类型.
            b.inpute type=file 文件标签
            c.enctype=multipart/form-data
     *
     *   后台:
     *      springmvc是通过apache的fileUpload依赖来解析文件的.
     *      1.需要引入apache的fileupload依赖
     *      2.配置一个文件解析器
     *      3.直接在handler中声明MultipartFile 类型的变量,然后直接操作
     */

pom依赖

<!--apache的文件解析器-->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
</dependency>

springMVC.xml

    <!--配置文件解析器-->
    <!--id:必须是multipartResolver-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--限制文件上传的大小 字节-->
        <property name="maxUploadSize" value="10240000"></property>
        <!--上传的文件名的编码-->
        <property name="defaultEncoding" value="utf-8"></property>

    </bean>

UploadFileController

@Controller
public class UploadFileController {

    @ResponseStatus(HttpStatus.OK)
    @RequestMapping("/updateItem.do")
    public void updateItem(Item item, @RequestParam("img") MultipartFile pictureFile) {
        System.out.println("表单参数插入到数据库:" + item);

        //获取源文件名
        String originalFilename = pictureFile.getOriginalFilename();
        //保存图片
        try {
            pictureFile.transferTo(new File("d://" + originalFilename));
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

统一异常处理

概述

  1. 请求流程:
    客户端(浏览器)–>前端控制器(DispatcherServlet)–>表现层(controller)–>业务层(service)–>持久层(dao)

  2. 处理思路:
    从持久层dao开始,每一层发生异常都向上一层抛出,一直抛到前端控制器(DispatcherServlet)。到此不能再抛出,我们不能把异常抛给用户
    在前端控制器需要进行异常处理,前端控制器是中央处理器,不负责具体的业务处理,因此在前端控制器需要调用异常处理器进行异常处理,最终返回一个友好的异常提示页面,提示用户
    在这里插入图片描述

案例实现

需求:根据商品id查询商品,如果查询不到商品,抛出商品不存在异常
步骤:

  • 1.自定义异常
  • 2.抛出运行时异常
  • 3.自定义异常处理器,实现HandlerExceptionResolver接口
  • 4.在springmvc中配置当前异常处理器对象

NoResultException

//自定义一个异常类
public class NoResultException extends Exception {
    public NoResultException(String message) {
        super(message);
    }
}

Controller

@Controller
public class ExceptionController {

    @ResponseStatus(HttpStatus.OK)
    @RequestMapping("/findItemById")
    public void findItemById(Integer id) throws NoResultException {
        if (id > 5) {
            System.out.println("查询id为" + id + "的商品不存在");
            //throw new NoResultException("查询id为" + id + "的商品不存在");
        } else {
            System.out.println("查询id为" + id + "的商品信息");
        }
    }
}

MyExceptionResolver

//自定义异常处理器,捕获到的所有异常,都在这里统一处理
public class MyExceptionResolver implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        ModelAndView modelAndView = new ModelAndView();

        //需要判断异常的类型
        if (ex instanceof NoResultException) {
            //获取业务中的错误信息
            String message = ex.getMessage();
            //保存数据
            modelAndView.addObject("errorMsg", message);
        } else if (ex instanceof MaxUploadSizeExceededException) {
            modelAndView.addObject("errorMsg", "上传的图片过大");

        }
        //错误的页面视图
        modelAndView.setViewName("error");
        return modelAndView;
    }
}

SpringMVC.xml

    <!--配置异常处理器-->
    <bean id="exceptionResolver" class="cn.itcast.exceptionHandler.MyExceptionResolver"></bean>

SpringMVC拦截器

概述

  1. springmvc框架中的拦截器,相当于web阶段学习的过滤器(filter),可以实现前置增强和后置增强功能
  2. 在springmvc框架中,拦截器可以对处理器方法执行预处理(前置增强),和执行后处理(后置增强)
  •   web开发中过滤器的作用:
      在请求访问目标资源之前进行拦截,一般都是通用性功能的抽取。(多个请求共有功能的抽取)
      例如乱码的处理,用于登录的判断,权限的判断。。。。
    
  •   在springmvc中,只有一个servlet。所有的请求,都是经过servlet再派发到controller。
      ItemController进行拦截。
      /item/save
      /item/delete
    

在这里插入图片描述

快速入门

需求:

  1. 创建一个demo级别的handler
  2. 创建一个类,实现拦截器接口 HandlerInterceptor
  3. 在springmvc.xml中配置拦截器

Controller

@Controller
@RequestMapping("/interceptor")
public class InterceptorController {
    @RequestMapping("/demo")
    public String demo(Model model) {
        model.addAttribute("msg", "controller");
        System.out.println("经过了controller");
        return "demo";
    }

}

interceptor

//拦截器
public class MyInterceptor1 implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("在controller的handler之前执行");
        return true; //返回true,表示放行.
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("在controller的handler之后执行,但是在视图渲染之前");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        System.out.println("在视图渲染之后做这个功能");
    }
}

/**输出结果为:
 * 在controller的handler之前执行
 * 经过了controller
 * 在controller的handler之后执行,但是在视图渲染之前
 * 2020-06-23 21:04:01,587 [http-nio-8080-exec-1] [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] Rendering view [org.springframework.web.servlet.view.InternalResourceView: name 'demo'; URL [/WEB-INF/jsp/demo.jsp]] in DispatcherServlet with name 'DispatcherServlet'
 * 2020-06-23 21:04:01,587 [http-nio-8080-exec-1] [org.springframework.web.servlet.view.InternalResourceView]-[DEBUG] Added model object 'msg' of type [java.lang.String] to request in view with name 'demo'
 * 2020-06-23 21:04:01,588 [http-nio-8080-exec-1] [org.springframework.web.servlet.view.InternalResourceView]-[DEBUG] Forwarding to resource [/WEB-INF/jsp/demo.jsp] in InternalResourceView 'demo'
 * 在视图渲染之后做这个功能
 *
 *
 *
 */

SpringMVC.xml

<!--
    配置拦截器
    声明拦截器配置
-->
<mvc:interceptors>
    <!-- 配置单个拦截器-->
    <mvc:interceptor>
        <!-- 配置拦截器拦截的路径-->
        <mvc:mapping path="/interceptor/*"/>
        <!-- 配置拦截器对象-->
        <bean class="cn.itcast.interceptors.MyInterceptor1"></bean>
    </mvc:interceptor>
</mvc:interceptors>

拦截器作用方法说明

在这里插入图片描述

拦截器链

<!--
    配置拦截器
    声明拦截器配置

    拦截器链:多个拦截器组成的整体. 按照上下的配置顺序
-->
<mvc:interceptors>
    <!-- 配置单个拦截器-->
    <mvc:interceptor>
        <!-- 配置拦截器拦截的路径-->
        <mvc:mapping path="/interceptor/*"/>
        <!-- 配置拦截器对象-->
        <bean class="cn.itcast.interceptors.MyInterceptor1"></bean>
    </mvc:interceptor>
    <!-- 配置单个拦截器-->
    <mvc:interceptor>
        <!-- 配置拦截器拦截的路径-->
        <mvc:mapping path="/interceptor/*"/>
        <!-- 配置拦截器对象-->
        <bean class="cn.itcast.interceptors.MyInterceptor2"></bean>
    </mvc:interceptor>
    <!-- 配置单个拦截器-->
    <mvc:interceptor>
        <!-- 配置拦截器拦截的路径-->
        <mvc:mapping path="/interceptor/*"/>
        <!-- 配置拦截器对象-->
        <bean class="cn.itcast.interceptors.MyInterceptor3"></bean>
    </mvc:interceptor>
</mvc:interceptors>

在这里插入图片描述

拦截器应用实现

案例需求

  •   用户访问商品列表数据,判断用户是否登录:
      1.如果用户已经登录,直接访问商品列表数据
      2.如果用户未登录,先到登录页面执行登录。成功登录以后再访问商品列表数据
    

代码实现

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">

    <!--配置前端控制器-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--读取配置文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:SpringMvc.xml</param-value>
        </init-param>
    </servlet>
    <!--配置拦截规则-->
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

SpringMVC.xml

<?xml version="1.0" encoding="UTF-8"?>
<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 http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">


    <!--开启注解扫描-->
    <context:component-scan base-package="cn.itcast"></context:component-scan>

    <!--springmvc的注解驱动-->
    <mvc:annotation-driven></mvc:annotation-driven>

    <!--拦截路径是/,所以开启加载静态资源-->
    <mvc:default-servlet-handler></mvc:default-servlet-handler>

    <!--配置视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--前缀和后缀-->
        <property name="prefix" value="/WEB-INF/jsp/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    <!--拦截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/item/*"/>
            <bean class="cn.itcast.interceptor.LoginInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>
</beans>

UserController

@Controller
@RequestMapping("/user")
public class UserController {

    @RequestMapping("/goToLogin")
    public String goToLogin() {
        return "login";
    }

    @RequestMapping("/login")
    public String login(HttpSession session) {
        //表示登录成功
        session.setAttribute("user","user");
        return "list";
    }


}

ItemController

@Controller
@RequestMapping("/item")
public class ItemController {
    @RequestMapping("/goToItemList")
    public String goToItemList() {
        //商品信息页面
        return "list";
    }
}

LoginInterceptor

//登录拦截器
public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        //判断登录权限
        Object user = request.getSession().getAttribute("user");
        //判断
        if (user != null) {
            //登录成功
            return true;
        } else {
            //登录失败
            request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
            return false;
        }

    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章