springmvc

三层架构和mvc设计模式

  • 三层架构

    • 表现层: 接收请求响应用户
      servlet – springMVC

    • 业务层:处理业务,事务
      自己写业务层 – spring 管理业务层

    • 持久层: 对数据库进行增删改查操作
      jdbc – dbutils --jdbcTemplate – mybatis – spring data

  • MVC设计模式

    • M:model 模型:封装数据
      广义:业务模型层 = dao + service + domain

    • V:view 视图:展示数据
      广义:能展示数据都是视图:jsp, html ,pdf ,freemarker

    • controller: 控制层:接收请求响应用户

mvc框架要做哪些事情

在这里插入图片描述

回顾servlet

<dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
        </dependency>
    </dependencies>
<?xml version="1.0" encoding="UTF-8"?>
<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>hello</servlet-name>
        <servlet-class>HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>


<!--    <session-config>-->
<!--&lt;!&ndash;        session超过15min就会超时&ndash;&gt;-->
<!--        <session-timeout>15</session-timeout>-->
<!--    </session-config>-->

<!--    <welcome-file-list>-->
<!--&lt;!&ndash;        欢迎页,默认就是 index.jsp&ndash;&gt;-->
<!--        <welcome-file>index.jsp</welcome-file>-->
<!--    </welcome-file-list>-->


</web-app>
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 1. 获取前端参数
        String method = req.getParameter("method");
        if (method.equals("add")){
            req.getSession().setAttribute("msg","执行了add方法");
        }
        if (method.equals("delete")){
            req.getSession().setAttribute("msg","执行了delete方法");
        }
        // 2. 调用业务层
        // 3. 视图转发或者重定向
        req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req,resp);
//        resp.sendRedirect();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

<%--
  Created by IntelliJ IDEA.
  User: EDY
  Date: 2023/12/26
  Time: 10:00
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="/hello" method="post">
        <input type="text" name="method">
        <input type="submit">
    </form>
</body>
</html>

<%--
  Created by IntelliJ IDEA.
  User: EDY
  Date: 2023/12/26
  Time: 9:53
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    ${msg}
</body>
</html>

初识springmvc

springmvc是spring framework的一部分,是基于java实现mvc的轻量级web框架。

在这里插入图片描述

spring是一个大杂烩,我们可以将springmvc中所有要用到的bean,注册到spring中!

在这里插入图片描述

  • 不同的处理器:类和方法
    在这里插入图片描述

在这里插入图片描述
我们之前使用servlet是创建了很多servlet的,通过调用service、dao、数据库最终再返回给用户jsp页面

很多servlet就是个问题,我们就在中间加一层调度,负责处理请求、适配url、跳转页面等功能,这就是DispatcherServlet的作用。

之前我们需要创建很多servlet,在使用springmvc之后就只需要添加几个方法即可。

springmvc的执行原理

在这里插入图片描述

  • 前端控制器:DispatcherServlet
  • 请求处理器:一段儿java程序
  • 模型:service、dao、pojo
  • modelAndView:携带视图和model的信息交给前端控制器

在这里插入图片描述
虚线的地方是需要我们做的,实线的地方都是由springmvc帮我们做的

  • HandlerMapping处理器映射器:建立地址与方法的映射,HandlerMapping负责根据用户请求url找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。
  • HandlerAdapter处理器适配器:根据地址调用方法
    Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。
  • ViewResolver 视图解析器:处理ModelAndView数据和视图
    根据handler返回的view地址文件类型(jsp/pdf….)去寻找相应的视图解析器来进行解析

简要分析springmvc执行流程

在这里插入图片描述
在这里插入图片描述

springMvc的执行流程(原理2)

  1. 用户发送请求至前端控制器DispatcherServlet。
  2. DispatcherServlet收到请求调用HandlerMapping处理器映射器。
  3. 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
  4. DispatcherServlet通过HandlerAdapter处理器适配器调用处理器。
  5. 执行处理器(Controller层,也叫后端控制器)。
  6. Controller执行完成返回数据和视图(ModelAndView)。
  7. HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
  8. DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
  9. ViewReslover解析后返回具体的View视图(JSP / HTML)。
  10. DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
  11. DispatcherServlet响应用户,用户看到界面和数据。

总结流程

Spring MVC所有的请求都经过DispatcherServlet来统一分发
DispatcherServlet将请求分发给Controller之前,需要借助于Spring MVC提供的HandlerMapping定位到具体的Controller
HandlerMapping接口负责完成客户请求到Controller映射。

Controller接口将处理用户请求,这和Java Servlet扮演的角色是一致的。一旦Controller处理完用户请求,则返回ModelAndView(数据和视图)对象给DispatcherServlet前端控制器。

从宏观角度考虑,DispatcherServlet是整个Web应用的控制器;从微观考虑,Controller是单个Http请求处理过程中的控制器,而ModelAndView是Http请求过程中返回的模型(Model)和视图(View)。

返回的视图需要通过ViewResolver接口(视图解析器)在Web应用中负责查找View对象,从从而将相应结果渲染给客户。

code

<?xml version="1.0" encoding="UTF-8"?>
<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">


<!--    配置DispatcherServlet:这个是springmvc的核心:前端控制器-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<!--     DispatcherServlet绑定spring的配置文件   -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>

<!--
    启动级别:1

    由于系统刚启动有些请求就会被处理了,所以我们让它和服务器一起启动
-->
        <load-on-startup>1</load-on-startup>
    </servlet>

<!--
    /:只匹配所有的请求,不会去匹配jsp页面
    /*:匹配所有的请求和jsp页面
        jsp页面应该是直接返回给客户的,但是使用/*,视图解析器就会在.jsp后面再加一个.jsp
-->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>
<?xml version="1.0" encoding="UTF-8"?>
<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
		https://www.springframework.org/schema/beans/spring-beans.xsd">

<!--

    ===================  springmvc的核心三大组件 =====================

    实际开发中并不需要配置,这里为了学习
-->
<!--    处理器映射器-->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--    处理器适配器-->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<!--
    视图解析器实际中也需要配置

    模板引擎 Thymeleaf Freemarker
-->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--        前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>


<!--
    BeanNameUrlHandlerMapping:这个处理映射器会根据bean的id来匹配路径
-->
    <bean id="/hello" class="com.lx.controller.HelloController"/>


</beans>
package com.lx.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 {
    @Override
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {

        ModelAndView modelAndView = new ModelAndView();

        // 业务代码

        // 添加返回的数据,model
        modelAndView.addObject("msg","success");

        // 视图跳转
        modelAndView.setViewName("test");


        return modelAndView;
    }
}

在这里插入图片描述

springmvc常用知识

  • springmvc post乱码解决
  • springmvc 核心配置文件
  • springmvc 参数绑定
  • springmvc controller返回值
<?xml version="1.0" encoding="UTF-8"?>
<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">


    <!--    配置DispatcherServlet:这个是springmvc的核心:前端控制器-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

        <!--     DispatcherServlet绑定spring的配置文件   -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>

        <!--
            启动级别:1

            由于系统刚启动有些请求就会被处理了,所以我们让它和服务器一起启动
        -->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!--
        /:只匹配所有的请求,不会去匹配jsp页面
        /*:匹配所有的请求和jsp页面
            jsp页面应该是直接返回给客户的,但是使用/*,视图解析器就会在.jsp后面再加一个.jsp
    -->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>


<!--    解决springmvc post乱码问题-->
    <filter>
        <filter-name>encodingFilter</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>
<!--        强制使用编码格式-->
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
<!--    所有的请求必须先通过CharacterEncodingFilter过滤,再进入其他Filter。-->
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>
<?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
		https://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">


<!--    自动扫描包,让指定包下的注解生效,由ioc容器统一管理-->
    <context:component-scan base-package="com.lx.controller"/>



<!--
    支持mvc注解驱动

    在spring中一般采用@Requestmapping注解来完成映射关系,要想使@RequestMapping注解生效
    必须向上下文中注册DefaultAnnotationHandlerMapping(处理器映射器)和
    AnnotationMethodAdapter(处理适配器)实例
    这两个实例分别在类级别和方法级别处理。
    而annotation-driven帮助我们自动完成上述两个实例的注入
-->

    <!--mvc的注解驱动,可以自动加载处理映射器,处理适配器-->
    <!--注解驱动可以加载springMVC的丰富的功能: 自定义类型转换器, ajax 技术必须引入注解驱动-->
    <mvc:annotation-driven>
        <!--    json乱码问题配置-->
        <mvc:message-converters>
            <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>



<!--

    让springmvc不处理静态资源 .css .js .html .mp3
    这些资源不需要走视图解析
-->
    <mvc:default-servlet-handler/>



    <!--对静态资源放行-->
    <!--把js下的文件映射到js目录下-->
<!--    <mvc:resources mapping="/js/**" location="/js/"></mvc:resources>-->




    <!--配置内部资源视图解析器-->
    <!--拼接:/WEB-INF/show.jsp -->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--        前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>
package com.lx.controller;

import com.lx.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

// @Controller代表这个类会被spring接管,其中所有的方法如果返回值是String,并且有具体的页面可以跳转
// 那么就会被视图解析器解析
@Controller
public class HelloController {

    /**
     * ==================================== 初识demo ======================================
     * 返回字符串 直接找视图解析器进行拼接页面
     * @param model
     * @return
     */
    @RequestMapping("hello")
    public String hello(Model model){

        model.addAttribute("msg","success");

        return "hello";
    }


    /**
     * ============================================  参数的绑定 ========================================
     *      简单类型
     *      方法的参数名与表单属性名一致,即可获取
     *
     *      pojo类型
     *      只要实体类的属性名与表单属性名一致,即可获取
     *
     *          表单中属性名name映射到方法参数username
     *          @RequestParam(“name”) String username;
     *
     *             required:是否必要参数,默认为true
     *              defaultValue:默认值,优先使用传递的参数
     * @param id
     * @param model
     * @return
     */
    @GetMapping("testPathVariable/{id}")
//    @PostMapping
    public String testPathVariable(@PathVariable("id") String id,  Model model){

        model.addAttribute("msg",id);

        return "hello";
    }
    @RequestMapping("testRequestParam")
    public String testRequestParam(@RequestParam("id") String id, Model model){

        model.addAttribute("msg",id);

        return "hello";
    }
    @RequestMapping("testRequestParamPojo")
    public String testRequestParamPojo(User user,HttpServletResponse response,Model model) throws IOException {

        // http://localhost:8080/testRequestParamPojo?name=zs&age=4&sex=0
        model.addAttribute("msg",user);

        return "hello";
    }





    // ==============================springmvc中也可以使用request和response=================================
    @RequestMapping("testHttpServletRequest")
    public String testHttpServletRequest(HttpServletRequest request, HttpServletResponse response,Model model){

        model.addAttribute("msg",request.getSession().getId());


        return "hello";
    }







    // ===============================不同的返回值跳转的页面=========================================

    /**
     *
     * 返回void 则拼接请求路径
     *    请求路径为 /controller/page/{1}  访问的页面为 /WEB-INF/jsp/controller/page/1.jsp
     *
     * 返回string
     *     视图解析器直接拼接
     *
     * 使用全路径
     *      返回值从 /WEB-INF 开始
     *
     * 使用 ModelAndView
     *
     * forward和redirect不走视图解析器
     *      WEB-INF目录只可以forward,不能redirect
     *
     *
     * @param request
     * @param response
     * @param model
     * @return
     */
    @RequestMapping("testForward1")
    public String testForward(HttpServletRequest request, HttpServletResponse response,Model model){

        // 测试请求转发需要注释掉 视图解析器
        // forward和redirect不注释视图解析器也生效,直接 / 就会变成 .jsp.jsp
        model.addAttribute("msg","testForward1");

        // 返回值加 / 就是不通过视图解析器
        return "/WEB-INF/jsp/testReturnPath.jsp";

        // 相当于用了原生的servlet
//        request.setAttribute("msg","testForward");
//        request.getRequestDispatcher("/WEB-INF/jsp/test.jsp");

    }
    @RequestMapping("testForward2")
    public String testForward2(HttpServletRequest request, HttpServletResponse response,Model model){

        model.addAttribute("msg","testForward2");


        return "forward:/WEB-INF/jsp/testReturnPath.jsp";
    }
    @RequestMapping("testRedirect")
    public String testRedirect(HttpServletRequest request, HttpServletResponse response,Model model){

        model.addAttribute("msg","testRedirect");

        // http://localhost:8080/testRedirect 就会变成
        // http://localhost:8080/index.jsp?msg=testRedirect
        return "redirect:/index.jsp";
    }






    /**
     *
     * ==================================解决springmvc post请求乱码问题=========================================
     * 处理前端乱码问题,就是前端form表单填中文提交之后,后端再回显给页面这个时候就会出现乱码
     *  post请求是乱码的,get请求不会
     *  在web.xml中配置filter
     *
     *  过滤器解决乱码
     * @param name
     * @param model
     * @return
     */
    @RequestMapping("messyCode")
    public String messyCode(@RequestParam("name") String name,Model model){

        model.addAttribute("msg",name);

        return "hello";
    }
}

<%--
  Created by IntelliJ IDEA.
  User: EDY
  Date: 2023/12/28
  Time: 19:48
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>

<form action="/messyCode" method="post">
    <input type="text" name="name">
    <input type="submit">
</form>
</body>
</html>

springmvc 相关知识

restful风格

在这里插入图片描述

json

在这里插入图片描述

在这里插入图片描述

jackson和fastjson

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.10.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.60</version>
</dependency>
package com.lx.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.lx.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

//@Controller  会走视图解析器
@RestController // 该类的所有方法都不会走视图解析器,全部返回字符串
public class UserController {


    /**
     *  @ResponseBody 不走视图解析器 将返回的java对象解析成json
     *
     *
     * 当controller的方法标记@ResponseBody或者Controller标记@RestController注解后,会用解析器去解析Controller的返回值,
     *      解析器会去搜索SpringMVC中注册的HttpMeesageConverter接口的实现类,如果没有添加对应的依赖,就会报出找不到Json类型的转换器异常
     *
     * 如果是Springboot项目的话,不用这么麻烦,因为你只需要添加web的启动依赖即可,不要再额外添加解析器的依赖,以为springboot都做了底层的依赖管理
     *
     * @return
     */
    // produces = "application/json;charset=utf-8" 解决前端乱码,但是每个请求都需要这么配置就很烦
    // 我们只需要在配置文件中配置即可
    @RequestMapping(value = "jacksonTest")
//    @ResponseBody
    public String jacksonTest() throws JsonProcessingException {

        ObjectMapper objectMapper = new ObjectMapper();

        User user = new User("林朝夕", "17", "女");

        String s = objectMapper.writeValueAsString(user);


        return s;
    }


    @RequestMapping(value = "jacksonTestList")
    public String jacksonTestList() throws JsonProcessingException {

        ObjectMapper objectMapper = new ObjectMapper();

        List<User> userList = new ArrayList<>();
        User user1 = new User("林朝夕", "17", "女");
        User user2 = new User("东野圭吾", "50", "男");
        userList.add(user1);
        userList.add(user2);

        String s = objectMapper.writeValueAsString(userList);


        return s;
    }


    @RequestMapping(value = "jacksonTestDate")
    public String jacksonTestDate() throws JsonProcessingException {

        ObjectMapper objectMapper = new ObjectMapper();

        // 默认是生成时间戳的,false代表不用默认的
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);

        // 第一种方式,使用LocalDate直接格式化
//        LocalDateTime localDateTimeNow = LocalDateTime.now();
//        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//        String string = formatter.format(localDateTimeNow);

        // 第二种,使用jackson来格式化日期  老师用的是Date类,localDateTimeNow在这儿并不生效
        // 使用localdatetime 返回的还是它本身,
        // {"month":"JANUARY","year":2024,"dayOfMonth":4,"hour":14,"minute":51,"monthValue":1,"nano":826000000,"second":29,
        // "dayOfWeek":"THURSDAY","dayOfYear":4,"chronology":{"id":"ISO","calendarType":"iso8601"}}
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        LocalDateTime localDateTimeNow = LocalDateTime.now();


        // "2024-01-04 14:41:45"
        String s = objectMapper.writeValueAsString(localDateTimeNow);


        return s;
    }

    @RequestMapping(value = "fastJsonTest")
    public String fastJsonTest() {

        List<User> userList = new ArrayList<>();
        User user1 = new User("林朝夕", "17", "女");
        User user2 = new User("东野圭吾", "50", "男");
        userList.add(user1);
        userList.add(user2);

        System.out.println("============================================================");

        System.out.println("--------java对象转json字符串--------");
        // {"age":"17","name":"林朝夕","sex":"女"}
        System.out.println(JSON.toJSONString(user1));
        // [{"age":"17","name":"林朝夕","sex":"女"},{"age":"50","name":"东野圭吾","sex":"男"}]
        System.out.println(JSON.toJSONString(userList));


        System.out.println("-------------json字符串转java对象-----------");
        // User(name=林朝夕, age=17, sex=女)
        System.out.println(JSON.parseObject(JSON.toJSONString(user1),User.class));


        System.out.println("-----------java对象转json对象----------");
        // 林朝夕
        System.out.println(((JSONObject)JSON.toJSON(user1)).getString("name"));


        System.out.println("-----------json对象转java对象----------");
        // User(name=林朝夕, age=17, sex=女)
        System.out.println(JSON.toJavaObject((JSONObject)JSON.toJSON(user1),User.class));




        return JSON.toJSONString(userList);


    }
}

springmvc spring mybatis整合

以下代码只需要关注服务端即可

pom

<?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.itheima</groupId>
    <artifactId>springmvc_day03</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>


    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.36</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>

        <!--mybatis 与 spring 整合包-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.1</version>
        </dependency>

        <!--spring数据源-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.9</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.10.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.10.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-web</artifactId>
            <version>2.10.0</version>
        </dependency>

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.9.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-jcl</artifactId>
            <version>2.9.1</version>
        </dependency>


        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
    </dependencies>
</project>

web.xml

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Archetype Created Web Application</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>


    <!--post请求编码过滤器-->
    <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>
        <!--请求和相应的编码都为指定编码格式, 一般不配置-->
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>



    <!--配置servlet-->

    <!--配置前端控制器:核心控制类(springmvc已经创建好),就是一个servlet-->

    <!--前端控制器创建的是 spring ioc 子容器

        父容器中的对象可以直接使用

        子容器中的对象,父容器不能使用

        子容器中的对象,其他子容器也不能使用
    -->

    <!--创建父容器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <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:spring-mvc.xml,classpath:applicationContext.xml</param-value>
        </init-param>

        <!--配置的servlet的创建的顺序, 在启动tomcat时即会创建-->
        <load-on-startup>1</load-on-startup>


    </servlet>

    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <!-- 拦截所有的请求和静态资源(js,css,img,插件)-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>


</web-app>

spring与mybatis整合的配置文件

applicationContext.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:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://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/tx https://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--dao层-->
    <!--引入属性文件-->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>

    <!--配置spring数据源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!-- 创建sqlSessionFactory对象-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="typeAliasesPackage" value="com.itheima.domain"></property>
    </bean>

    <!--扫描dao层的包,创建动态代理对象,并存入spring ioc容器中-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.itheima.dao"></property>
    </bean>





    <!--service层-->

    <context:component-scan base-package="com.itheima.service"></context:component-scan>

    <!--事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--事务增强-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
            <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
            <tx:method name="query*" propagation="SUPPORTS" read-only="true"/>
            <tx:method name="*"></tx:method>
        </tx:attributes>
    </tx:advice>

    <!--aop配置,织入-->
    <aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution( * com.itheima.service.impl.*.*(..))"></aop:advisor>
    </aop:config>



</beans>

springmvc 配置文件

spring-mvc.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
        https://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="com.itheima.controller"></context:component-scan>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/pages/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    <mvc:annotation-driven></mvc:annotation-driven>

    <mvc:resources mapping="/js/**" location="/js/"></mvc:resources>
    <mvc:resources mapping="/css/**" location="/css/"></mvc:resources>
    <mvc:resources mapping="/fonts/**" location="/fonts/"></mvc:resources>

    <!--&lt;!&ndash;把控制器作为servlet处理,不拦截静态资源&ndash;&gt;-->
    <!--<mvc:default-servlet-handler></mvc:default-servlet-handler>-->

</beans>

mybatis 映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.itheima.dao.AccountDao">
    <select id="findAll" resultType="account">
        select * from account
    </select>

    <select id="findById" parameterType="int" resultType="account">
        select * from account WHERE id = #{id}
    </select>

    <insert id="save" parameterType="account">
        INSERT INTO account (name,money) VALUES (#{name},#{money})
    </insert>

    <update id="update" parameterType="account">
        UPDATE account SET name = #{name},money = #{money} WHERE id = #{id}
    </update>

    <delete id="deleteById" parameterType="int">
        DELETE FROM account WHERE id = #{id}
    </delete>


</mapper>

controller 层

package com.itheima.controller;

import com.itheima.domain.Account;
import com.itheima.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.util.List;

@Controller
@RequestMapping("/account")
public class AccountController {

    @Autowired
    private AccountService accountService;

    @RequestMapping("/findAll")
    public ModelAndView findAll(){

        List<Account> accountList = accountService.findAll();

        ModelAndView modelAndView = new ModelAndView();

        modelAndView.addObject("accountList",accountList);

        modelAndView.setViewName("show");

        return modelAndView;

    }

    @RequestMapping("/save")
    public String save(Account account){

        accountService.save(account);

        ModelAndView modelAndView = new ModelAndView();

        modelAndView.setViewName("show");

        return "redirect:/account/findAll";
    }


    @RequestMapping("/del")
    public String del(Integer id){

        accountService.deleteById(id);

        return "redirect:/account/findAll";
    }


    @RequestMapping("/updateUI")
    public ModelAndView updateUI(Integer id){

        Account account = accountService.findById(id);

        ModelAndView modelAndView = new ModelAndView();

        modelAndView.addObject("account",account);

        modelAndView.setViewName("update");

        return modelAndView;
    }

    @RequestMapping("/update")
    public String update(Account account){

        accountService.update(account);


        return "redirect:/account/findAll";
    }

}

service层

package com.itheima.service.impl;

import com.itheima.dao.AccountDao;
import com.itheima.domain.Account;
import com.itheima.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountDao accountDao;

    public List<Account> findAll() {
        return accountDao.findAll();
    }

    public Account findById(Integer id) {
        return accountDao.findById(id);
    }

    public List<Account> findByName(String name) {
        return accountDao.findByName(name);
    }

    public void save(Account account) {
        accountDao.save(account);
    }

    public void update(Account account) {
        accountDao.update(account);
    }

    public void deleteById(Integer id) {

        accountDao.deleteById(id);
    }
}

dao层

package com.itheima.dao;

import com.itheima.domain.Account;

import java.util.List;

public interface AccountDao {

    List<Account> findAll();

    Account findById(Integer id);

    List<Account> findByName(String name);

    void save(Account account);

    void update(Account account);

    void deleteById(Integer id);
}

前端主要是使用jsp

展示页面

<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


<html>
<head>
    <title>Title</title>
    <!-- 引入CSS样式 -->
    <link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.min.css">
</head>
<body>

<div class="panel panel-default">
    <!-- Default panel contents -->
    <div class="panel-heading">
        <a class="btn btn-default" href="${pageContext.request.contextPath}/pages/save.jsp">添加</a>
    </div>

    <!-- Table -->
    <table class="table">

        <thead>
        <tr>
            <th>id</th>
            <th>name</th>
            <th>money</th>
        </tr>
        </thead>

        <tbody>
        <c:forEach items="${accountList}" var="item">
        <tr>
            <td>${item.id}</td>
            <td>${item.name}</td>
            <td>${item.money}</td>
            <td>
                <%--点击事件也可以--%>
                <a href="javascript:del(${item.id})" class="btn btn-danger">删除</a>
                <a href="${pageContext.request.contextPath}/account/updateUI?id=${item.id}" class="btn btn-info">修改</a>
            </td>
        </tr>
        </c:forEach>
        </tbody>

    </table>
</div>
</body>
<!-- 引入JS文件 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.9.1.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/bootstrap.min.js"></script>

<script type="text/javascript">

    function del(id){

        if(confirm("您确定要删除么?")){

            location.href = "${pageContext.request.contextPath}/account/del?id=" + id

        }
    }
</script>
</html>

保存页面

<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


<html>
<head>
    <title>Title</title>
    <!-- 引入CSS样式 -->
    <link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.min.css">
</head>
<body>

<div class="panel panel-default">
    <!-- Default panel contents -->
    <form class="form-horizontal" role="form" action="${pageContext.request.contextPath}/account/save">
        <div class="form-group">
            <label for="accountName" class="col-sm-2 control-label">账户名</label>
            <div class="col-sm-10">
                <input type="text" class="form-control" id="accountName" name="name"
                       placeholder="请输入账户名">
            </div>
        </div>
        <div class="form-group">
            <label for="balance" class="col-sm-2 control-label">余额</label>
            <div class="col-sm-10">
                <input type="text" class="form-control" id="balance" name="money"
                       placeholder="请输入余额">
            </div>
        </div>
        <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
                <button type="submit" class="btn btn-default">保存</button>
            </div>
        </div>
    </form>
    <!-- Table -->
</div>
</body>
<!-- 引入JS文件 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.9.1.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/bootstrap.min.js"></script>
</html>

更新页面

<%@ page isELIgnored="false" contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


<html>
<head>
    <title>Title</title>
    <!-- 引入CSS样式 -->
    <link rel="stylesheet" href="${pageContext.request.contextPath}/css/bootstrap.min.css">
</head>
<body>

<div class="panel panel-default">
    <!-- Default panel contents -->
    <form class="form-horizontal" role="form" action="${pageContext.request.contextPath}/account/update">
        <div class="form-group">
            <label for="accountName" class="col-sm-2 control-label">账户名</label>
            <div class="col-sm-10">
                <input type="hidden" name="id" value="${account.id}" ></input>
                <input type="text" class="form-control" id="accountName" value="${account.name}" name="name"
                       placeholder="请输入账户名">
            </div>
        </div>
        <div class="form-group">
            <label for="balance" class="col-sm-2 control-label">余额</label>
            <div class="col-sm-10">
                <input type="text" class="form-control" id="balance" value="${account.money}" name="money"
                       placeholder="请输入余额">
            </div>
        </div>
        <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
                <button type="submit" class="btn btn-default">保存</button>
            </div>
        </div>
    </form>
    <!-- Table -->
</div>
</body>
<!-- 引入JS文件 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.9.1.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/bootstrap.min.js"></script>
</html>

springmvc拦截器

在这里插入图片描述

  • 过滤器是会拦截静态资源的(拦截器看下面的配置的话也是可以配置拦截静态资源的,所以这个区别有待商榷 todo)

过滤器的用处:

  • 在 HttpServletRequest 到达 Servlet 之前,拦截客户的 HttpServletRequest;
    根据需要检查 HttpServletRequest,也可以修改 HttpServletRequest 头和数据;
  • 在 HttpServletResponse 到达客户端之前,拦截 HttpServletResponse;
    根据需要检查 HttpServletResponse,也可以修改 HttpServletResponse头和数据。

Spring 的 Interceptor(拦截器)与 Servlet 的 Filter 有相似之处,比如二者都是 AOP 编程思想的体现,都能实现权限检查、日志记录等。

不同之处总结如下:

1、拦截器是基于java的反射机制的,而过滤器是基于函数回调。

2、拦截器是属于springmvc的,过滤器是属于servlet的。

3、filter只在servlet前后起作用,拦截器能够深入到方法前后、异常抛出前后等,具有更大的弹性。
在spring中,优先使用拦截器,它几乎可以实现过滤器的所有功能。

<?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>springmvc_day03</groupId>
    <artifactId>interceptor</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <dependencies>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
        </dependency>
    </dependencies>

    
</project>
<?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
        https://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="com.itheima.controller"></context:component-scan>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/pages/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    <mvc:annotation-driven></mvc:annotation-driven>

    <mvc:resources mapping="/js/**" location="/js/"></mvc:resources>
    <mvc:resources mapping="/css/**" location="/css/"></mvc:resources>
    <mvc:resources mapping="/fonts/**" location="/fonts/"></mvc:resources>

    <!--配置拦截器链-->
    <mvc:interceptors>
        <mvc:interceptor>
            <!--拦截所有的请求,包括静态资源-->
            <mvc:mapping path="/**"/>
            <!--指定拦截器类-->

            <mvc:exclude-mapping path="/css/**"></mvc:exclude-mapping>
            <mvc:exclude-mapping path="/js/**"></mvc:exclude-mapping>
            <mvc:exclude-mapping path="/fonts/**"></mvc:exclude-mapping>
            <bean class="com.itheima.controller.interceptor.InterceptorFirst"></bean>
        </mvc:interceptor>
        <mvc:interceptor>
            <!--拦截所有的请求,包括静态资源-->
            <mvc:mapping path="/**"/>
            <!--指定拦截器类-->
            <mvc:exclude-mapping path="/css/**"></mvc:exclude-mapping>
            <mvc:exclude-mapping path="/js/**"></mvc:exclude-mapping>
            <mvc:exclude-mapping path="/fonts/**"></mvc:exclude-mapping>
            <bean class="com.itheima.controller.interceptor.InterceptorSecond"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

</beans>
package com.itheima.controller.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

public class InterceptorFirst implements HandlerInterceptor {


    /**
     * 在控制器方法执行前执行
     *
     * 作用
     *      在操作之前进行验证
     *
     * 顺序
     *      按照配置顺序执行
     *
     *
     * 应用
     *
     *  判断是否登录了
     *      如果不存在登录信息,回到登录页面
     *      如果存在登录信息,则放行
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String requestURI = request.getRequestURI();

        if (requestURI.contains("login")){
//            放行
            return true;
        }else {
            response.sendRedirect("login.jsp");
            return false;
        }
    }

    /**
     * 控制器方法返回值之前执行
     * 所有的preHandle都返回true才会执行
     *
     * 顺序
     *      按照配置顺序倒序执行
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("first postHandle");
    }

    /**
     *
     * 控制器方法返回值后,页面渲染完成后执行
     * 所有的preHandle都返回true才会执行
     *
     *顺序
     *      按照配置顺序倒序执行
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("first afterCompletion");
    }
}

自定义类型转换器

参数是特殊类型,例如Date

package com.itheima.converter;


import org.springframework.core.convert.converter.Converter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 转换之前是String,转换之后是Date
 */
public class StringToDateConverter implements Converter<String,Date> {


    @Override
    public Date convert(String s) {

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

        try {
            Date data = simpleDateFormat.parse(s);
            return data;
        } catch (ParseException e) {
            e.printStackTrace();
        }

        return null;
    }
}

配置文件

<?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="com.itheima"></context:component-scan>

    <bean id="conversionService" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    <!--关联类型转换器工厂-->
    <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>

    <!--创建类型转换器工厂-->
    <bean class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.itheima.converter.StringToDateConverter"></bean>
            </set>
        </property>
    </bean>
</beans>

springmvc的文件上传

在这里插入图片描述

<%--
  Created by IntelliJ IDEA.
  User: EDY
  Date: 2023/12/28
  Time: 19:28
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  $END$

  <form action="${pageContext.request.contextPath}/user/upload" enctype="multipart/form-data" method="post">
    <input type="file" name="file" />
    <input type="submit">

  </form>
  </body>
</html>

<?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.itheima</groupId>
    <artifactId>springmvc_study</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>springmvc_study Maven Webapp</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <!--<dependency>-->
            <!--<groupId>org.springframework</groupId>-->
            <!--<artifactId>spring-context</artifactId>-->
            <!--<version>5.0.2.RELEASE</version>-->
        <!--</dependency>-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
        </dependency>

        <!--文件上传的依赖-->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.1</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>springmvc_study</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>3.2.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

<?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
        https://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="com.itheima"></context:component-scan>


    <!--<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">-->
        <!--<property name="prefix" value="/WEB-INF/"></property>-->
        <!--<property name="suffix" value=".jsp"></property>-->
    <!--</bean>-->

    <!--&lt;!&ndash;创建类型转换器工厂&ndash;&gt;-->
    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="com.itheima.converter.StringToDateConverter"></bean>
            </set>
        </property>
    </bean>

    <!--&lt;!&ndash;关联类型转换器工厂&ndash;&gt;e-->
    <mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>

    <!--对静态资源放行-->
    <!--把js下的文件映射到js目录下-->
    <mvc:resources mapping="/js/**" location="/js/"></mvc:resources>

    <!--文件上传解析器-->
    <!--id值是固定的-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--设置文件上传的最大尺寸为5m-->
        <property name="maxUploadSize">
            <value>5242880</value>
        </property>
    </bean>

</beans>
package com.itheima.controller;

import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.UUID;

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

    @RequestMapping("/upload")
    public String saveSesion(String username, MultipartFile upload, HttpServletRequest request) {

//       获取唯一的文件名称 -- uuid

        String uuidName = UUID.randomUUID().toString().replace("-", "");

//       获取扩展名

//      获取原始的文件名
        String originalFilename = upload.getOriginalFilename();

        String extendName = originalFilename.substring(originalFilename.lastIndexOf("."));

//       传到服务器上的文件名称
        String fileName = uuidName + extendName;

//       获取服务器的路径
//       获取upload在服务器上的绝对路径
        String uploadPath = request.getSession().getServletContext().getRealPath("upload");

//       判断路径是否存在
        if (!new File(uploadPath).exists()){
            new File(uploadPath).mkdirs();
        }

        try {
            upload.transferTo(new File(uploadPath + "/" + fileName));
        } catch (IOException e) {
            e.printStackTrace();
        }

        return "show";
    }

}

跨服务器上传
有专门处理图片的服务器

在上面服务的代码,再次创建一个服务

测试的时候用的是tomcat,需要修改tomcat的conf/web.xml,readonly为false

这个服务是空的,只在webapp下创建一个文件夹和一个文件即可,下面的代码都是上面那个服务器的

添加依赖

<!--引入jersey服务器的包-->
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-core</artifactId>
            <version>1.18.1</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-client</artifactId>
            <version>1.18.1</version>
        </dependency>

修改代码

package com.itheima.controller;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.UUID;

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

    @RequestMapping("/upload")
    public String saveSesion(String username, MultipartFile upload, HttpServletRequest request) {

//       获取唯一的文件名称 -- uuid

        String uuidName = UUID.randomUUID().toString().replace("-", "");

//       获取扩展名

//      获取原始的文件名
        String originalFilename = upload.getOriginalFilename();

        String extendName = originalFilename.substring(originalFilename.lastIndexOf("."));

//       传到服务器上的文件名称
        String fileName = uuidName + extendName;

//       获取服务器的路径
//       获取upload在服务器上的绝对路径
        String url = "http://localhost:9090/imgserver/upload";


//      跨服上传
//      创建客户端
        Client client = Client.create();

//      获取服务器资源
        WebResource resource = client.resource(url + "/" + fileName);

//      开始上传
        try {
            resource.put(String.class,upload.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "show";
    }

}

springmvc统一处理异常

public class CustomException extends  Exception{

    private String message;
    public CustomException( String message) {
        super(message);
        this.message = message;
    }

    @Override
    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

@Component
public class HandlerResolver  implements HandlerExceptionResolver {
    /**
     * 在控制层出现了都会进入该方法执行
     * 所以service和dao层的异常都可以往上抛
     * @param request  请求对象
     * @param response 响应对象
     * @param handler  处理器
     * @param exception 异常对象
     * @return
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) {
        //打印异常信息
        exception.printStackTrace();
        //创建一个自定义异常类
        CustomException customException = new CustomException("系统错误,请于管理员联系,谢谢配合!!!!");
        //创建ModelAndView对象
        ModelAndView modelAndView = new ModelAndView();
        //添加数据
        modelAndView.addObject("customException",customException);
        //指定页面
        modelAndView.setViewName("error");
        return modelAndView;
    }
}

系统日志功能

实体类

public class SysLog {
    private Long id;
    private String visitTime;
    private String username;
    private String ip;
    private String method;
    //此处省略getter和setter方法... ...
}

springmvc.xml配置文件中开启aop的自动代理

<!--aop的自动代理
其中proxy-target-class设置为true代表目标类的代理对象不需要借助于接口
即使用cglib基于子类生成目标对象的代理对象
-->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>

在web.xml中配置监听request对象的监听器

<!--配置请求监听器:当请求发生时,在容器中创建请求对象-->
  <listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
  </listener>

编写切面类(切面类内部有增强)

package com.itheima.log;

import com.itheima.domain.Log;
import com.itheima.service.LogService;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

/**
 * aop: 切面 = 增强(通知) + 切入点
 *   增强:对真实方法的增强部分
 *      增强类型:前置增强,后置增强,异常增强,最终增强,环绕增强(必须执行目标对象的方法, 必须返回原始方法的返回值)
 *   切入点:对连接点的定义
 *   连接点:被拦截的方法, 在spring只有方法才是连接点
 *   目标对象:target, 真实对象
 *   织入:把切入点与增强关联
 *
 *   以此类为切面类
 *   controller中的方法为连接点
 *
 * @Aspect: 标记该类为切面类
 * @Component: 创建该类对象
 * @author 黑马程序员
 * @Company http://www.ithiema.com
 * @Version 1.0
 */
@Aspect
@Component
public class LogController {

    @Autowired
    LogService logService;

    @Autowired
    HttpServletRequest request;
    /**
     * 切入点声明
     */
    @Pointcut("execution(* com.itheima.controller.*.*(..))")
    public void pc(){}

    /**
     * 前置增强
     *
     *  获取日志信息,并保存到数据库
     */
    @Before("pc()")
    public void before(JoinPoint joinPoint){
        Log log = new Log();
        //获取日志信息
        // 访问者用户名 private String username;
        //获取上下文对象
        SecurityContext securityContext = SecurityContextHolder.getContext();
        //获取认证对象
        Authentication authentication = securityContext.getAuthentication();
        //获取用户对象
        User user = (User) authentication.getPrincipal();
        //获取用户名
        String username = user.getUsername();
        log.setUsername(username);

        //访问时间  private Date visitTime;
        log.setVisitTime(new Date());

        //访问者的ip地址  private String ip;
        String ip = request.getRemoteAddr();
        log.setIp(ip);

        //访问的方法全名称 =  全类名 +  方法名 private String method;
        //获取目标对象,被代理的对象,真实对象
        Object target = joinPoint.getTarget();
        //获取全类名
        String className = target.getClass().getName();
        //获取方法
        Signature signature = joinPoint.getSignature();
        //获取方法名称
        String methodName = signature.getName();
        log.setMethod(className + "." + methodName);

        logService.save(log);
    }
}

云朵如肮脏的棉团漂浮在前方的天空。
湖畔
东野圭吾

部分知识引用自:
https://blog.csdn.net/qq_39372821/article/details/88405196
https://blog.csdn.net/qq_40542534/article/details/109065239
https://www.cnblogs.com/lenve/p/10748453.html
https://www.bilibili.com/video/BV1aE41167Tu?p=4&vd_source=64c73c596c59837e620fed47fa27ada7

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值