复习整理的DAY26_SpringMVC

首先,什么是SpringMVC?

SpringMVC是一个MVC框架,也是Spring的一个模块,有Spring的特性。

那么,什么是MVC?

MVC的全名是Model View Controller,M是指业务模型,V是指用户界面,C则是控制器,是模型(model)-视图(view)-控制器(controller)的缩写,是一种软件设计典范。

MVC在客户端/服务器(b/s)系统下的应用:

SpringMVC是一个基于Spring的web架构:

 SpringMVC依赖于Core(IOC),SpringMVC需要导入Core包和SpringMVC特有的包。

SpringMVC框架:

需要程序员开发的:处理器Handler(Controller)视图View

具体怎么做呢?

举例(我用的是IDEA):

第一步,先在WEB-INF下的lib目录中加入如下包

Spring框架的各类包下载:https://repo.spring.io/ui/native/release/org/springframework

commons-logging的各个版本下载:http://archive.apache.org/dist/commons/logging/binaries/

jstl的jar包下载看https://blog.csdn.net/qq_39445165/article/details/84107885

 第二步,WEB-INF下的web.xml文件里添加配置

 <!-- 配置DispatcherServlet(前端控制器) -->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <!-- classpath:代表就是src这个路径 -->
            <param-value>classpath:springmvc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <!-- /student.action   /user.action
          所有以action结尾的请求都交给DispatcherServlet来处理
         -->
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>

第三步,创建model(entity)类,比如我是在src下面创建了test目录,创建Student类

public class Student {
    private Integer id;
    private String name;
    private Integer age;
    private String gender;

    public Student() {
    }

    public Student(Integer id, String name, Integer age, String gender) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
    public Student(String name, Integer age, String gender) {
        this.name = name;
        this.age = age;
        this.gender = gender;
    }
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }
}

第四步,创建jsp文件,比如我这里创建的是student_insert.jsp和student_info.jsp

为了系统一些,我先创建了jsp目录

然后才在jsp目录下添加 jsp文件。

student_insert.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>学生插入</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/student/insert.action" method="post">
    姓名:<input type="text" name="name"/><br/>
    年龄:<input type="text" name="age"/><br/>
    性别:<input type="text" name="gender"/><br/>
    <input type="submit" value="提交"/>
</form>
</body>
</html>

student_info.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
student_info.jsp
${student}
</body>
</html>

 第五步,创建控制器Controller(即之前说的Handler,一般来说,Controller是Handler,但Handler不一定是Controller),比如我创建的是StudentController

@Controller
// 请求映射,怎么样找到这些请求的路径 /student/insert.action,*.action在xml文件里面配置了
@RequestMapping(value = "/student")
public class StudentController {
   @RequestMapping(value = "/insert")
   public ModelAndView insert(Student student) {
     System.out.println("StudentController.insert()");
     System.out.println(student);
     
     // Model:数据     View:界面
     ModelAndView modelAndView = new ModelAndView();
     // request.setAttribute("student", student);
     modelAndView.addObject("student", student);
     // request.getRequestDispatcher("/jsp/student_info.jsp").forward(request,response);
// /jsp/在之前配置过了,此处需要省略,否则如果加上,会造成两个/jsp/累加,找不到文件,但可以加上/
     modelAndView.setViewName("student_info");
     // modelAndView.setViewName("/student_info");这样也正确
     return modelAndView;
   }
}

第六步,创建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:p="http://www.springframework.org/schema/p"
	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-4.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <!-- 扫描base-package对应的包下面类中所有的注解-->
	<context:component-scan base-package="test"/>

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

	<!-- 视图解析器
		1、如果Controller中书写的是视图的逻辑名,这个视图解析器必须要配置。
		前缀+视图逻辑名+后缀=真实路径
		/jsp/student_insert.jsp
		/jsp/ + student_insert + .jsp
		2、如果视图解析器书写的是视图的真实路径,那么这个视图解析器可以不配置
	-->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<!-- 路径前缀 -->
		<property name="prefix" value="/jsp/"/>
		<!-- 路径后缀 -->
		<property name="suffix" value=".jsp"></property>
	</bean>
</beans>

最后,Tomcat一运行,输入网址http://localhost:8080/SpringMVC/jsp/student_insert.jsp(我的端口号是8080,项目名是SpringMVC)

 填写信息,提交,

浏览器跳到了http://localhost:8080/SpringMVC/student/insert.action,显示

一次SpringMVC的简单尝试就OK了

 之前提到的都是服务器内部转发,如果要重定向,可以直接在return中写

@RequestMapping(value = "/insert")
    public String insert() {
        System.out.println("StudentController.insert");
        // 这是重定向,不是转发,/jsp和.jsp不能省略!
        return "redirect:/jsp/student_insert.jsp";
    }

说一下ModelAndView和Model

ModelAndView:既放数据,也放转发的界面

Model:放数据,以方法返回值的形式设置转发的页面

之前举例中就用了ModelAndView

Model的用法举例:

@RequestMapping("/insert")
public String insert(Student student, Model model) {
   System.out.println("StudentController.insert()");
   System.out.println(student);
   // req.setAttritbu("student", student);
   model.addAttribute("student", student);
   // req.getRequestDispatcher("/jsp/student_info.jsp").forword(req, resp);
   return "student_info";
}

简单说一下RequestMapping注解:

RequestMapping是建立请求URL和处理方法之间的对应关系。

之前的@RequestMapping("/student")其实等于@RequestMapping(value = "/student")

之前的@RequestMapping("/insert")等于@RequestMapping(value = "/insert")

就像URL链接上是http://localhost:8080/SpringMVC/student/insert.action,就是通过这个注解(.action是通过之前的配置)

如果不写method,那么就会默认既支持get也支持post

但有些时候,我们希望只支持一种,怎么设置呢?

比如,

// 只能用post
    @RequestMapping(value = "/insert", method = RequestMethod.POST)
    public String insert(Student student, Model model) {
        System.out.println("StudentController.insert");
        System.out.println(student);
        // Model:模型 数据 View:界面
        // request.setAttribute("student", student);
        model.addAttribute("student", student);
        // request.getRequestDispatcher("/jsp/student_info.jsp").forward();
        return "/student_info";
    }

例子中,就是只能用post方法,否则报405错误,如果只要get方法,将method对应的值设为RequestMethod.GET。

当然,要是觉得ModelAndView和Model不熟悉,不想用,也可以用传统的web参数:

@RequestMapping(value = "/insert", method = RequestMethod.POST)
public void insert(HttpServletRequest request, HttpServletResponse response, HttpSession session)throws ServletException, IOException {
   System.out.println("StudentController.insert()");
   String name = request.getParameter("name");
   String age = request.getParameter("age");
   String gender = request.getParameter("gender");
   Student student = new Student(name, Integer.parseInt(age), gender);
   request.setAttribute("student", student);
   // 不要省略/jsp/与.jsp
   request.getRequestDispatcher("/jsp/student_info.jsp").forward(request, response);
}

乱码问题:

在post方式传递参数出现了中文乱码问题,就在web.xml中配置:

<!-- 解决POST乱码问题 -->
 <filter>
     <filter-name>characterEncoding</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>characterEncoding</filter-name>
    <url-pattern>/*</url-pattern>
 </filter-mapping>

ResponseBody注解:

在lib目录下加入json有关jar包,可以使得函数返回值作为页面body里面的内容

下载地址:

https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations/2.4.0

https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core/2.4.2

https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind/2.2.4

@RequestMapping("/select")
    @ResponseBody
    public List<Student> selectById(Integer id) {
        System.out.println("StudentController.selectById");
        Student student1 = new Student(1, "zhangsan1", 1, "女");
        Student student2 = new Student(2, "zhangsan2", 1, "女");
        Student student3 = new Student(3, "zhangsan3", 1, "女");
        Student student4 = new Student(4, "zhangsan4", 1, "女");
        Student student5 = new Student(5, "zhangsan5", 1, "女");
        List<Student> list = new ArrayList<>();
        list.add(student1);
        list.add(student2);
        list.add(student3);
        list.add(student4);
        list.add(student5);
        return list;
    }

启动Tomcat,输入http://localhost:8080/SpringMVC/student/select.action,就可以得到有list数据的页面

RequestParameter注解:

在默认的情况下,只有方法参数名要与传递过来的name属性名相同,SpringMVC才会帮我们进行参数绑定,如果不相同,就需要用到RequestParameter注解了

在不相同的属性前加上注解@RequestParam,注解中的value设置为传递过来的参数名

比如,

@RequestMapping("/selectByPage")
    public void selectByPage(@RequestParam(value = "page" ) Integer pageNo, Integer pageSize) {
        System.out.println("StudentController.selectByPage");
        System.out.println("pageNo :" + pageNo);
        System.out.println("pageSize : " + pageSize);
        
    }

输入http://localhost:8080/SpringMVC/student/selectByPage.action?page=3&pageSize=10,在控制台可以看到

该注解中还有required、defaultValue ,

required设置为true表示这个属性必须传递了参数,否则既不传递参数,也没有默认值,就报错,而如果不设置required,也不设置默认值,就表示默认值是null

defaultValue可以设置默认值

比如,

@RequestMapping("/selectByPage")
    public List<Student> selectByPage(@RequestParam(value = "page",required = true) Integer pageNo, @RequestParam(defaultValue = "10") Integer pageSize) {
        System.out.println("StudentController.selectByPage");
        System.out.println("pageNo :" + pageNo);
        System.out.println("pageSize : " + pageSize);
        Student student1 = new Student(1, "zhangsan1", 1, "女");
        Student student2 = new Student(2, "zhangsan2", 1, "女");
        Student student3 = new Student(3, "zhangsan3", 1, "女");
        Student student4 = new Student(4, "zhangsan4", 1, "女");
        Student student5 = new Student(5, "zhangsan5", 1, "女");
        List<Student> list = new ArrayList<>();
        list.add(student1);
        list.add(student2);
        list.add(student3);
        list.add(student4);
        list.add(student5);
        return list;
    }

输入http://localhost:8080/SpringMVC/student/selectByPage.action?page=3 

控制台打印的也是

PathVariable注解:

通过 @PathVariable 可以将URL中占位符参数{xxx}绑定到处理器类的方法形参中

比如,

@RequestMapping("/select/{id}")
public void select( @PathVariable("id") Long id) {
    System.out.println(id);
}

输入http://localhost:8080/SpringMVC/student/select/12.action

可以在控制台打印12

视图解析器
1、如果Controller中书写的是视图的逻辑名,这个视图解析器必须要配置。
前缀+视图逻辑名+后缀=真实路径,比如之前的return "/student_info";在配置之后,就等于
return "/jsp/studnet_info.jsp";
2、如果Controller中写的是视图的真实路径,那么这个视图解析器可以不配置
具体配置(之前提到过):
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
   <!-- 路径前缀 -->
   <property name="prefix" value="/jsp/"/>
   <!-- 路径后缀 -->
   <property name="suffix" value=".jsp"></property>
</bean>

拦截器:

如果想要对于用户信息进行拦截过滤,那么在这里,只需要创建相关的类,再在之前提到过的springmvc.xml中进行配置即可。拦截器本质是AOP(面向切面编程),也就是说符合横切关注点的所有功能都可以放入拦截器实现。

比如,

在test包下面建了一个interceptor包,在该包里我创建了两个拦截器用于测试,

MyInterceptor1

public class MyInterceptor1 implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("MyInterceptor1.preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor1.postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}

MyInterceptor2

public class MyInterceptor2 implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("MyInterceptor2.preHandle");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("MyInterceptor2.postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}

然后在springmvc.xml文件里面加上配置(放在</beans>前,别放错在最下面了):

<!--配置拦截器-->
	<mvc:interceptors>
		<mvc:interceptor>
			<mvc:mapping path="/**"/>
			<bean class="test.interceptor.MyInterceptor1"></bean>
		</mvc:interceptor>
		<mvc:interceptor>
			<mvc:mapping path="/**"/>
			<bean class="test.interceptor.MyInterceptor2"></bean>
		</mvc:interceptor>
	</mvc:interceptors>

如果再次输入之前提到过的http://localhost:8080/SpringMVC/student/select/12.action

就会发现控制台打印了

MyInterceptor1.preHandle
MyInterceptor2.preHandle
12
MyInterceptor2.postHandle
MyInterceptor1.postHandle
MyInterceptor2.afterCompletion
MyInterceptor1.afterCompletion

具体是怎么实现的呢?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值