【SSM框架】SpringMVC笔记 — 汇总

1、什么是 SpringMVC?

SpringMVC 是基于 MVC 开发模式的框架,用来优化控制器。它是 Spring 家族的一员,它也具备 IOC 和 AOP。

  • 什么是MVC?

MVC 是一种开发模式,它是模型视图控制器的简称,所有的 web 应用都是基于 MVC 开发。

1)M:模型层,包含实体类,业务逻辑层,数据访问层

2)V:视图层,html,javaScript,vue 等都是视图层,用来显现数据

3)C:控制器,它是用来接收客户端的请求,并返回响应到客户端的组件,Servlet就是组件

2、SpringMVC 框架的优点?

1)轻量级,基于 MVC 的框架

2)易于上手,容易理解,功能强大

3)它具备 IOC 和 AOP

4)完全基于注解开发

3、Springmvc 的执行流程:

执行流程说明:

1)向服务器发送HTTP请求,请求被前端控制器 DispatcherServlet 捕获。

2)DispatcherServlet 根据

3)DispatcherServlet 根据获得的 Handler,选择一个合适的 HandlerAdapter。

4)提取 Request 中的模型数据,填充 Handler 入参,开始执行 Handler(Controller)。在填充 Handler的入参过程中,根据你的配置,Spring 将帮你做一些额外的工作:

HttpMessageConveter:将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息。

数据转换:对请求消息进行数据转换。如String转换成Integer、Double等。

数据格式化:对请求消息进行数据格式化。如将字符串转换成格式化数字或格式化日期等。

数据验证:验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中。

5)Handler(Controller)执行完成后,向 DispatcherServlet 返回一个 ModelAndView 对象。

6)根据返回的ModelAndView,选择一个适合的 ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet。

7)ViewResolver 结合Model和View,来渲染视图。

8)视图负责将渲染结果返回给客户端

4、基于注解的 SpringMVC 框架开发的步骤:

1)新建项目,选择 webapp 模板

2)修改目录,添加缺失的 test 目录,java目录,resources目录(两套),并修改目录属性

3)修改 pom.xml 文件,添加 SpringMVC 的依赖,添加 Servlet 的依赖

<!--添加springmvc的依赖-->
<dependency>
    <groupid>org.springframework</groupid>
    <artifactid>spring-webmvc</artifactid>
    <version>5.2.5.RELEASE</version>
</dependency>
<!--添加servlet的依赖-->
<dependency>
    <groupid>javax.servlet</groupid>
    <artifactid>javax.servlet-api</artifactid>
    <version>3.1.0</version>
</dependency>

4)添加 springmvc.xml 配置文件,指定包扫描,添加视图解析器.

SpringMVC 框架为了避免请求资源路径与扩展名上的冗余,在视图解析器 InternalResouceViewResolver 中引入了请求的前辍与后辍。而 action 中只需给出要跳转页面的文件名即可,对于具体的文件路径与文件扩展名,视图解析器会自动完成拼接;

<!--添加包扫描-->
<context:component-scan base-package="com.bjpowernode.controller"></context:component-scan>
<!--添加视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <!--配置前缀-->
    <property name="prefix" value="/admin/"></property>
    <!--配置后缀-->
    <property name="suffix" value=".jsp"></property>
</bean>

5)删除 web.xml 文件,新建 web.xml

6)在 web.xml 文件中注册 springMVC 框架(所有的 web 请求都是基于 servlet 的)

<!--注册SpringMVC框架-->
<servlet>
    <servlet-name>springmvc</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>springmvc</servlet-name>
    <!--
          指定拦截什么样的请求
          <a href="${pageContext.request.contextPath}/demo.action">访问服务器</a>
     -->
    <!--指定拦截以.action结尾的请求,交给核心处理器DispatcherServlet处理。-->
    <url-pattern>*.action</url-pattern>
</servlet-mapping>

7)在 webapp 目录下新建 admin 目录,在 admin 目录下新建 main.jsp 页面,删除 index.jsp 页面,并新建

8)开发控制器(Servlet),这是一个普通的类,不用继承和实现接口。类中的每个方法就是一个具体的action控制器。

@Controller &#xA0;//&#x8868;&#x793A;&#x5F53;&#x524D;&#x7C7B;&#x4E3A;&#x5904;&#x7406;&#x5668;,&#x4EA4;&#x7ED9;Spring&#x53BB;&#x521B;&#x5EFA;&#x5BF9;&#x8C61;
public class DemoAction {
    /**
    * &#x4EE5;&#x524D;&#x7684;Servlet&#x7684;&#x89C4;&#x8303;
    * protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
    * action&#x4E2D;&#x6240;&#x6709;&#x7684;&#x529F;&#x80FD;&#x5B9E;&#x73B0;&#x90FD;&#x662F;&#x7531;&#x65B9;&#x6CD5;&#x6765;&#x5B8C;&#x6210;&#x7684;
    * action&#x65B9;&#x6CD5;&#x7684;&#x89C4;&#x8303;
    * 1)&#x8BBF;&#x95EE;&#x6743;&#x9650;&#x662F;public
    * 2)&#x65B9;&#x6CD5;&#x7684;&#x8FD4;&#x56DE;&#x503C;&#x4EFB;&#x610F;
    * 3)&#x65B9;&#x6CD5;&#x540D;&#x79F0;&#x4EFB;&#x610F;
    * 4)&#x65B9;&#x6CD5;&#x53EF;&#x4EE5;&#x6CA1;&#x6709;&#x53C2;&#x6570;,&#x5982;&#x679C;&#x6709;&#x53EF;&#x662F;&#x4EFB;&#x610F;&#x7C7B;&#x578B;
    * 5)&#x8981;&#x4F7F;&#x7528;@RequestMapping&#x6CE8;&#x89E3;&#x6765;&#x58F0;&#x660E;&#x4E00;&#x4E2A;&#x8BBF;&#x95EE;&#x7684;&#x8DEF;&#x5F84;(&#x540D;&#x79F0;)
    *
    */
    @RequestMapping("/demo")
    public String demo(){
    System.out.println("&#x670D;&#x52A1;&#x5668;&#x88AB;&#x8BBF;&#x95EE;&#x5230;&#x4E86;.......");
    return "main"; &#xA0;//&#x53EF;&#x4EE5;&#x76F4;&#x63A5;&#x8DF3;&#x5230;/admin/main.jsp&#x9875;&#x9762;&#x4E0A;
    }
}

9)添加 tomcat 进行测试功能

5、分析 web 请求:

web请求执行的流程:

index.jsp

one.jsp

  • DispatcherServlet 要在 web.xml 文件中注册才可用

6、@RequestMapping 注解详解:

  • 此注解就是来映射服务器访问的路径。@RequestMapping 的 value 属性用于定义所匹配请求的 URI。

1)此注解可加在方法上,是为此方法注册一个可以访问的名称(路径)。

@RequestMapping("/demo")
public String demo(){
System.out.println("&#x670D;&#x52A1;&#x5668;&#x88AB;&#x8BBF;&#x95EE;&#x5230;&#x4E86;.......");
return "main"; &#xA0;//&#x53EF;&#x4EE5;&#x76F4;&#x63A5;&#x8DF3;&#x5230;/admin/main.jsp&#x9875;&#x9762;&#x4E0A;
}
//<a href="${pageContext.request.contextPath}/demo.action">&#x8BBF;&#x95EE;&#x670D;&#x52A1;&#x5668;</a>

2)此注解可以加在类上,相当于是包名(虚拟路径),区分不同类中相同的 action 的名称。URI 的请求是相对于 Web 的根目录。换个角度说,要访问处理器的指定方法,必须要在方法指定 URI 之前加上处理器类前定义的模块名称。

@RequestMapping("/user")
public class DemoAction1 {..}
//<a href="${pageContext.request.contextPath}/user/demo.action">&#x8BBF;&#x95EE;&#x670D;&#x52A1;&#x5668;</a>

3)此注解可区分 get 请求和 post 请求:

  • 对于@RequestMapping,其有一个属性 method,用于对被注解方法所处理请求的提交方式进行限制,即只有满足该 method 属性指定的提交方式的请求,才会执行该被注解方法。
 @Controller
&#xA0; &#xA0; public class ReqAction {
&#xA0; &#xA0; &#xA0; &#xA0; @RequestMapping(value = "/req",method = RequestMethod.GET)
&#xA0; &#xA0; &#xA0; &#xA0; public String req(){
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; System.out.println("&#x6211;&#x662F;&#x5904;&#x7406;get&#x8BF7;&#x6C42;&#x7684;........");
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; return "main";
&#xA0; &#xA0; &#xA0; &#xA0; }
&#xA0; &#xA0; &#xA0; &#xA0; @RequestMapping(value = "/req" ,method = RequestMethod.POST)
&#xA0; &#xA0; &#xA0; &#xA0; public String req1(){
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; System.out.println("&#x6211;&#x662F;&#x5904;&#x7406;post&#x8BF7;&#x6C42;&#x7684;........");
&#xA0; &#xA0; &#xA0; &#xA0; &#xA0; &#xA0; return "main";
&#xA0; &#xA0; &#xA0; &#xA0; }
&#xA0; &#xA0; }

7、五种数据提交方式:

  • 前四种数据注入的方式,会自动进行类型转换。但无法自动转换日期类型。

1)单个提交数据

  • 在方法中声明一个和表单提交的参数名称相同的参数,由框架按照名称直接注入。

栗子:

/*&#xA0;
    <form action="${pageContext.request.contextPath}/one.action">
        &#x59D3;&#x540D;:<input name="myname">
        &#x5E74;&#x9F84;:<input name="age">
        <input type="submit" value="&#x63D0;&#x4EA4;">
    </form>
*/

    @RequestMapping("/one")
    public String one(String myname,int age){ &#xA0;===>&#x81EA;&#x52A8;&#x6CE8;&#x5165;,&#x5E76;&#x4E14;&#x7C7B;&#x578B;&#x8F6C;&#x6362;
        System.out.println("myname="+myname+",age="+(age+100));
        return "main";
    }

2)对象封装提交数据:

  • 声明一个自定义的实体类参数,框架调用实体类中相应的setter方法注入属性值,只要保证实体类中成员变量的名称与提交请求的name属性值一致即可。

实体类:

public class Users {
    private String name;
    private int age;
    //&#x6784;&#x9020;&#x65B9;&#x6CD5;&#xFF0C;setter&#x65B9;&#x6CD5;&#x7B49;&#x7701;&#x7565;&#x3002;&#x3002;&#x3002;
}

页面:

<form action="${pageContext.request.contextPath}/two.action" method="post">
    &#x59D3;&#x540D;:<input name="name">
    &#x5E74;&#x9F84;:<input name="age">
    <input type="submit" value="&#x63D0;&#x4EA4;">
</form>

action:

@RequestMapping("/two")
public String two(Users u){
    System.out.println(u);
    return "main";
}

3)动态占位符提交

  • 仅限于超链接或地址拦提交数据,它是一杠一值,一杠一大括号,使用注解 @PathVariable 来解析。
//<a href="${pageContext.request.contextPath}/three/&#x5F20;&#x4E09;/22.action">&#x52A8;&#x6001;&#x63D0;&#x4EA4;</a> &#xA0; &#xA0;
@RequestMapping("/three/{uname}/{uage}")
public String three(@PathVariable("uname") //&#x7528;&#x6765;&#x89E3;&#x6790;&#x8DEF;&#x5F84;&#x4E2D;&#x7684;&#x8BF7;&#x6C42;&#x53C2;&#x6570;
                    String name,
                    @PathVariable("uage")
                    int age){
    System.out.println("name="+name+",age="+(age+100));
    return "main";
}

4)映射名称不一致

  • 提交请求参数与action方法的形参的名称不一致,使用注解@RequestParam来解析
/**
* &#xA0;&#x59D3;&#x540D;:<input name="name">
* &#xA0;&#x5E74;&#x9F84;:<input name="age">
*/
@RequestMapping("/four")
public String four(@RequestParam("name") //&#x4E13;&#x95E8;&#x7528;&#x6765;&#x89E3;&#x51B3;&#x540D;&#x79F0;&#x4E0D;&#x4E00;&#x81F4;&#x7684;&#x95EE;&#x9898;
                    String uname,
                    @RequestParam("age")
                    int uage){
    System.out.println("uname="+uname+",uage="+(uage+100));
    return "main";
}

5)使用HttpServletRequest对象提取;

/**
* &#xA0;&#x59D3;&#x540D;:<input name="name">
* &#xA0;&#x5E74;&#x9F84;:<input name="age">
*/
@RequestMapping("/five")
    public String five(HttpServletRequest request){
    String name = request.getParameter("name");
    int age = Integer.parseInt(request.getParameter("age"));
    System.out.println("name="+name+",age="+(age+100));
    return "main";
} &#xA0;&#xA0;

8、中文乱码解决方案:

  • 对于前面所接收的请求参数,若含有中文,则会出现中文乱码问题。Spring 对于请求参数中的中文乱码问题,给出了专门的字符集过滤器:
  • spring-web-5.2.5.RELEASE.jar 的 org.springframework.web.filter 包下的 CharacterEncodingFilter 类。

解决方案:

  • 在 web.xml 中注册字符集过滤器,即可解决 Spring 的请求参数的中文乱码问题。不过,最好将该过滤器注册在其它过滤器之前。因为过滤器的执行是按照其注册顺序进行的。
<filter>
    <filter-name>encode</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <!--
            配置参数
            private String encoding;
            private boolean forceRequestEncoding;
            private boolean forceResponseEncoding;
        -->
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
        <param-name>forceRequestEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <param-name>forceResponseEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>encode</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

9、action方法的返回值:

1)String:

处理器方法返回的字符串可以指定逻辑视图名,通过视图解析器解析可以将其转换为物理视图地址;

可以自动拼接前缀和后缀,可以指定返回的路径;

当然,也可以直接返回资源的物理视图名。不过,此时就不需要再在视图解析器中再配置前辍与后辍了。

2)Object:

返回 json 格式的对象,自动将对象或集合转为 json,使用的 jackson 工具进行转换,必须要添加 jackson 依赖,一般用于 ajax 请求;

处理器方法也可以返回 Object 对象,这个 Object 可以是 Integer,自定义对象,Map,List 等。但返回的对象不是作为逻辑视图出现的,而是作为直接在页面显示的数据出现的。返回对象,需要使用@ResponseBody 注解,将转换后的 JSON 数据放入到响应体中。Ajax请求多用于Object返回值类型。

3)void:

无返回值,一般用于ajax请求;

若处理器对请求处理后,无需跳转到其它任何资源,此时可以让处理器方法返回 void。

4)基本数据类型,用于 ajax 请求。

5)ModelAndView:返回数据和视图对象,现在用的很少。

10、完成 ajax 请求访问服务器,返回学生集合:

1)添加jackson依赖

<dependency>
    <groupid>com.fasterxml.jackson.core</groupid>
    <artifactid>jackson-databind</artifactid>
    <version>2.9.8</version>
</dependency>

2)在 webapp 目录下新建 js目录,添加 jQuery 函数库

3)在 index.jsp 页面上导入函数库:

4)在 action 上添加注解@ResponseBody,用来处理ajax请求

@Controller
public class AjaxAction {
    //&#x5904;&#x7406;ajax&#x8BF7;&#x6C42;,&#x4E00;&#x5B9A;&#x8981;&#x52A0;@ResponseBody
    @ResponseBody
    @RequestMapping("/ajax")
    public List<student> ajax(){
        Student stu1 = new Student("&#x5F20;&#x4E09;",22);
        Student stu2 = new Student("&#x674E;&#x56DB;",24);
        Student stu3 = new Student("&#x738B;&#x4E94;",23);
        List<student> list = new ArrayList<>();
        list.add(stu1);
        list.add(stu2);
        list.add(stu3);
        //&#x8C03;&#x7528;json&#x8F6C;&#x6362;&#x5DE5;&#x5177;ObjectMapper&#x8FDB;&#x884C;&#x8F6C;&#x6362;
        return list; &#xA0;//===>springmvc&#x8D1F;&#x8D23;&#x8F6C;&#x6362;&#x6210;json
        }
    }</student></student>

5)在 springmvc.xml 文件中添加注解驱动

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

11、SpringMVC 的四种跳转方式:

  • 本质就是两种跳转:请求转发和重定向,衍生出四种是请求转发页面,转发action,重定向页面,重定向action;
  • 默认的跳转是请求转发,直接跳转到 jsp 页面展示;

可以使用框架提供的关键字 redirect: ,进行一个重定向操作,包括重定向页面和重定向action;

可以使用框架提供的关键字forward:,进行服务器内部转发操作,包括转发页面和转发action;

  • 当使用 redirect: 和 forward: 关键字时,视图解析器中前缀后缀的拼接就无效了。

栗子:

@RequestMapping("/one")
public String one(){
    System.out.println("&#x8FD9;&#x662F;&#x8BF7;&#x6C42;&#x8F6C;&#x53D1;&#x9875;&#x9762;&#x8DF3;&#x8F6C;.........");
    return "main"; &#xA0;//&#x9ED8;&#x8BA4;&#x662F;&#x8BF7;&#x6C42;&#x8F6C;&#x53D1;,&#x4F7F;&#x7528;&#x89C6;&#x56FE;&#x89E3;&#x6790;&#x5668;&#x62FC;&#x63A5;&#x524D;&#x7F00;&#x540E;&#x7F00;&#x8FDB;&#x884C;&#x9875;&#x9762;&#x8DF3;&#x8F6C;
}

@RequestMapping("/two")
public String two(){
    System.out.println("&#x8FD9;&#x662F;&#x8BF7;&#x6C42;&#x8F6C;&#x53D1;action&#x8DF3;&#x8F6C;.........");
    // &#xA0;/admin/ &#xA0;/other.action &#xA0;.jsp
    //forward: &#x8FD9;&#x7EC4;&#x5B57;&#x7B26;&#x4E32;&#x53EF;&#x4EE5;&#x5C4F;&#x853D;&#x524D;&#x7F00;&#x548C;&#x540E;&#x7F00;&#x7684;&#x62FC;&#x63A5;.&#x5B9E;&#x73B0;&#x8BF7;&#x6C42;&#x8F6C;&#x53D1;&#x8DF3;&#x8F6C;
    return "forward:/other.action"; &#xA0;//&#x9ED8;&#x8BA4;&#x662F;&#x8BF7;&#x6C42;&#x8F6C;&#x53D1;,&#x4F7F;&#x7528;&#x89C6;&#x56FE;&#x89E3;&#x6790;&#x5668;&#x62FC;&#x63A5;&#x524D;&#x7F00;&#x540E;&#x7F00;&#x8FDB;&#x884C;&#x9875;&#x9762;&#x8DF3;&#x8F6C;
}

@RequestMapping("/three")
public String three(){
    System.out.println("&#x8FD9;&#x662F;&#x91CD;&#x5B9A;&#x5411;&#x9875;&#x9762;.......");
    //redirect: &#xA0;&#x8FD9;&#x7EC4;&#x5B57;&#x7B26;&#x4E32;&#x53EF;&#x4EE5;&#x5C4F;&#x853D;&#x524D;&#x7F00;&#x548C;&#x540E;&#x7F00;&#x7684;&#x62FC;&#x63A5;.&#x5B9E;&#x73B0;&#x91CD;&#x5B9A;&#x5411;&#x8DF3;&#x8F6C;
    return "redirect:/admin/main.jsp";
}

@RequestMapping("/four")
public String four(){
    System.out.println("&#x8FD9;&#x662F;&#x91CD;&#x5B9A;&#x5411;action.......");
    //redirect: &#xA0;&#x8FD9;&#x7EC4;&#x5B57;&#x7B26;&#x4E32;&#x53EF;&#x4EE5;&#x5C4F;&#x853D;&#x524D;&#x7F00;&#x548C;&#x540E;&#x7F00;&#x7684;&#x62FC;&#x63A5;.&#x5B9E;&#x73B0;&#x91CD;&#x5B9A;&#x5411;&#x8DF3;&#x8F6C;
    return "redirect:/other.action";
}

@RequestMapping("/five")
public String five(){
    System.out.println("&#x8FD9;&#x662F;&#x968F;&#x4FBF;&#x8DF3;.......");

    return "forward:/fore/login.jsp";
}

12、SpringMVC 默认的参数类型:

不需要去创建,直接拿来使用即可。

1)HttpServletRequest

2)HttpServletResponse

3)HttpSession

4)Model

5)Map

6)ModelMap

栗子:

//&#x505A;&#x4E00;&#x4E2A;&#x6570;&#x636E;,&#x4F20;&#x5230;main.jsp&#x9875;&#x9762;&#x4E0A;
Users u = new Users("&#x5F20;&#x4E09;",22);

//&#x4F20;&#x9012;&#x6570;&#x636E;
request.setAttribute("requestUsers",u);
session.setAttribute("sessionUsers",u);
model.addAttribute("modelUsers",u);
map.put("mapUsers",u);
modelMap.addAttribute("modelMapUsers",u);

注意:Map,Model,ModelMap 和 request 一样,都使用请求作用域进行数据传递,所以服务器端的跳转必须是请求转发,页面才可以得到值。

13.日期处理:

1)日期的提交处理

A、单个日期处理

  • 要使用注解@DateTimeFormat,此注解必须搭配 springmvc.xml 文件中的

在方法的参数上使用@DateTimeFormat注解;

在类的成员setXXX()方法上使用@DateTimeFormat注解

  • 但这种解决方案要在每个使用日期类型的地方都去添加使用@DateTimeFormat注解,比较麻烦,我们可以使用@InitBinder注解来进行类中统一日期类型的处理。

B.类中全局日期处理

注册一个注解,用来解析本类中所有的日期类型,自动转换

@InitBinder&#xFF1B;
public void initBinder(WebDataBinder dataBinder){
    dataBinder.registerCustomEditor(Date.class,new CustomDateEditor(sf,true));
}

2)日期的显示处理:

  • 在页面上显示好看的日期,必须使用 JSTL

步骤:

A)添加依赖 jstl

<dependency>
    <groupid>jstl</groupid>
    <artifactid>jstl</artifactid>
    <version>1.2</version>
</dependency>

B)在页面上导入标签库 :

  • 如果是单个日期对象,直接转为好看的格式化的字符串进行显示

如果是 list 中的实体类对象的成员变量是日期类型,则必须使用 jstl 进行显示。

<%--导入jstl核心标签库--%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--导入jstl格式化标签库--%>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %></%@taglib></%--导入jstl格式化标签库--%></%@taglib></%--导入jstl核心标签库--%>

C)使用标签显示数据:

<table width="800px" border="1">
    <tr>
        <th>&#x59D3;&#x540D;</th>
        <th>&#x751F;&#x65E5;</th>
    </tr>
    <c:foreach items="${list}" var="stu">
        <tr>
            <td>${stu.name}</td>
            <td>${stu.birthday}------ <fmt:formatdate value="${stu.birthday}" pattern="yyyy-MM-dd"></fmt:formatdate></td>
        </tr>
    </c:foreach>
</table>

14、SpringMVC 的拦截器:

  • 针对请求和响应进行的额外的处理,在请求和响应的过程中添加预处理,后处理和最终处理

&#x62E6;&#x622A;&#x5668;&#x6267;&#x884C;&#x7684;&#x65F6;&#x673A;&#xFF1A;

1)preHandle():在请求被处理之前进行操作(预处理)

2)postHandle():在请求被处理之后,但结果还没有渲染前进行操作,可以改变响应结果(后处理)

3)afterCompletion:所有的请求响应结束后执行善后工作,清理对象,关闭资源(最终处理)

&#x62E6;&#x622A;&#x5668;&#x5B9E;&#x73B0;&#x7684;&#x4E24;&#x79CD;&#x65B9;&#x5F0F;&#xFF1A;

1)继承 HandlerInterceptorAdapter 的父类

2)实现 HandlerInterceptor 接口

&#x62E6;&#x622A;&#x5668;&#x5B9E;&#x73B0;&#x7684;&#x6B65;&#x9AA4;&#xFF1A;

1)创建登录方法,在 session 中存储用户信息,用于进行权限验证

@RequestMapping("/login")
public String login(String name, String pwd, HttpServletRequest request){
    if("zar".equalsIgnoreCase(name) && "123".equalsIgnoreCase(pwd)){
        //&#x5728;session&#x4E2D;&#x5B58;&#x50A8;&#x7528;&#x6237;&#x4FE1;&#x606F;,&#x7528;&#x4E8E;&#x8FDB;&#x884C;&#x6743;&#x9650;&#x9A8C;&#x8BC1;
        request.getSession().setAttribute("users",name);
        return "main";
    }else{
        request.setAttribute("msg","&#x7528;&#x6237;&#x540D;&#x6216;&#x5BC6;&#x7801;&#x4E0D;&#x6B63;&#x786E;!");
        return "login";
    }
}

2)开发拦截器的功能,实现 HandlerInterceptor 接口,重写 preHandle() 方法:

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //&#x662F;&#x5426;&#x767B;&#x5F55;&#x8FC7;&#x7684;&#x5224;&#x65AD;
        if(request.getSession().getAttribute("users") == null){
            //&#x6B64;&#x65F6;&#x5C31;&#x662F;&#x6CA1;&#x6709;&#x767B;&#x5F55;,&#x6253;&#x56DE;&#x5230;&#x767B;&#x5F55;&#x9875;&#x9762;,&#x5E76;&#x7ED9;&#x51FA;&#x63D0;&#x793A;
            request.setAttribute("msg","&#x60A8;&#x8FD8;&#x6CA1;&#x6709;&#x767B;&#x5F55;,&#x8BF7;&#x5148;&#x53BB;&#x767B;&#x5F55;!");
            request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
            return false;
        }
        return true;//&#x653E;&#x884C;&#x8BF7;&#x6C42;
    }
}

3)在 springmvc.xml 文件中注册拦截器:

<mvc:interceptors>
    <mvc:interceptor>
        <!--映射要拦截的请求-->
        <mvc:mapping path="/**">
        <!--设置放行的请求-->
        <mvc:exclude-mapping path="/showLogin"></mvc:exclude-mapping>
        <mvc:exclude-mapping path="/login"></mvc:exclude-mapping>
        <!--配置具体的拦截器实现功能的类-->
        <bean class="com.bjpowernode.interceptor.LoginInterceptor"></bean>
    </mvc:mapping></mvc:interceptor>
</mvc:interceptors>

&#xA0;&#x8D44;&#x6E90;&#x5728;WEB-INF&#x76EE;&#x5F55;&#x4E0B;&#xFF1A;

很多企业会将动态资源放在WEB-INF目录下,这样可以保证资源的安全性,因为在WEB-INF目录下的动态资源不可以直接访问,必须要通过请求转发的方式进行访问,这样避免了通过地址栏直接对资源的访问,重定向也无法访问动态资源。

栗子:

@Controller
public class WebInfAction {
    @RequestMapping("/showMain")
    public String showMain(){//&#x901A;&#x8FC7;&#x8BF7;&#x6C42;&#x8F6C;&#x53D1;&#x7684;&#x65B9;&#x5F0F;&#x8BBF;&#x95EE;webapp&#x76EE;&#x5F55;&#x4E0B;&#x7684;WEB-INF&#x76EE;&#x5F55;&#x4E0B;&#x7684;main.jsp
        System.out.println("&#x8BBF;&#x95EE;main.jsp");
        return "main";
    }
    @RequestMapping("/showLogin")
    public String showLogin(){////&#x901A;&#x8FC7;&#x8BF7;&#x6C42;&#x8F6C;&#x53D1;&#x7684;&#x65B9;&#x5F0F;&#x8BBF;&#x95EE;webapp&#x76EE;&#x5F55;&#x4E0B;&#x7684;WEB-INF&#x76EE;&#x5F55;&#x4E0B;&#x7684;login.jsp
        System.out.println("&#x8BBF;&#x95EE;login.jsp");
        return "login";
    }
}

Original: https://www.cnblogs.com/Burning-youth/p/16342656.html
Author: 猿头猿脑的王狗蛋
Title: 【SSM框架】SpringMVC笔记 — 汇总

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/586390/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Java控制Appium server start/stop

    相信很多人都会遇到这种场景,在进行appium自动化的时候用Windows OS,不好实现后台运行,每次启动Appium server: 使用Appium GUI版手动点击 就是在…

    Java 2023年5月29日
    085
  • MQTT 入门(2)–MQTT 发布订阅详解

    本文主要介绍 MQTT 协议中发布订阅的详细过程。 1、Connect(连接) MQTT 协议基于 TCP/IP 协议,MQTT Broker 和 Client 都有需要有 TCP…

    Java 2023年6月16日
    074
  • java xml转为json的两种方法

    java xml转为json的两种方法 先来看效果,效果一: 效果二: 从效果来看,明显是第二种方法,比第一种好。 下面把代码贴出出来 第一种实现:用到的包是fastjson, j…

    Java 2023年5月29日
    061
  • Spring Boot:集成Druid数据源

    综合概述 数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数…

    Java 2023年5月30日
    083
  • 微服务SpringCloud之服务注册与发现

    在找.net core 微服务框架时发现了Steeltoe开源项目,它可以基于Spring Cloud实现.net core和.net Framework的微服务。正好之前也有学习…

    Java 2023年5月30日
    087
  • 我的大一总结

    图片不太清楚这里附上链接密码: w98f https://udld.github.io/ (老师总结)大一内容总结 编程语言初级使用 C,java (python 未完成) Lin…

    Java 2023年6月5日
    082
  • 【每日算法】算法复习一

    存在重复元素 II &#x7ED9;&#x5B9A;&#x4E00;&#x4E2A;&#x6574;&#x6570;&#x6…

    Java 2023年6月9日
    097
  • 致和我一样迷茫的Java程序员们

    目前已发布的文章: 不止面试—jvm类加载面试题详解 不止面试—JVM内存模型面试题详解 缘起 从事近7年Java开发之后,在2019年这个寒冷的冬天里,我终于迎来了人生中的第一次…

    Java 2023年6月15日
    087
  • Linux 定时任务调度

    定时任务调度 任务调度:是指系统在某个时间执行的特定的命令或程序 任务调度分类 系统工作:有些重要的工作必须周而复始的执行 个别用户工作:个别用户可能希望执行某些程序 cronta…

    Java 2023年6月5日
    083
  • Spring源码之AOP的使用

    Spring往期精彩文章 Spring源码搭建 Spring源码阅读一 前言 我们都知道Java是一门面向对象(OOP)的语言,所谓万物皆对象。但是它也存在着一些个弊端:当你需要给…

    Java 2023年6月7日
    090
  • Java8之stream流的分组排序

    关于Java8的stream流,这里不讲groupBy分组,也不讲sort排序,这些都是很基础的用法,可以自行百度。 这里说一种业务场景,对于分组后的map,根据value对key…

    Java 2023年6月9日
    072
  • POSIX 线程的创建与退出

    创建线程: 退出线程: 使用多线程,首先就需要创建一个新线程。那么线程是如何被创建的呢,是用下面这个函数创建的。 创建函数的四个参数的意义分别如下: 返回值:如果函数执行成功,则返…

    Java 2023年5月30日
    078
  • SpringbootTest注入失败

    正确方法: java;gutter:true; /<strong> * <em>@author:sawsh * </em>@date:2021/…

    Java 2023年5月30日
    0114
  • springBoot-启动原理

    注:SpringBoot版本 2.6.2 SpringBoot的入口是从SpringApplication.run()传入我们的主启动类开始 @SpringBootApplicat…

    Java 2023年6月7日
    072
  • TypeScript(5)类、继承、多态

    前言 对于传统的 JavaScript 程序我们会使用 &#x51FD;&#x6570;和 &#x57FA;&#x4E8E;&#x539F;…

    Java 2023年6月9日
    0101
  • Java高并发27-ThreadPoolExecutor原理剖析(1)

    类图 线程池的好处: (1)性能好;(2)工厂方法便捷创建线程,个数自定义指定 类图描述 Excutors其实是一个工具类,ThreadPoolExecutor继承了Abstrac…

    Java 2023年6月13日
    087
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球