SpringMVC笔记


SpringMVC

结构图


HelloMvc

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/cache
        http://www.springframework.org/schema/cache/spring-cache.xsd">

HelloController

// 需要实现相关接口
public class HelloController implements Controller {
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
        // 模型和视图
        ModelAndView mv = new ModelAndView();
        // 封装对象,将属性放到mv中
        mv.addObject("msg", "hellSpringMVC");
        // 封装要跳转的视图,放入mv
        // 这个helloMVC和注册的那个"/hello"有什么关联呢?
        // 答:输入"/hello"之后,会运行这个mv,这个mv设置属性后会跳转到具体的页面
        // 页面的名字为:前缀 + ViewName + 后缀
        mv.setViewName("helloMVC");
        return mv;
    }
}

springmvc-servlet.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

    <!--如何让解析器和所有的关联呢?-->
    <!--答: 通过web.xml里的servlet对springmvc进行配置, 再让所有的跳转都处理改servlet,就能对所有的进行关联-->
    <!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <!--前后缀就是在注册的方法路径上, 对路径进行补全-->
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--具体的处理还是在这里配置的-->
    <bean id="/hello" class="it.controller.HelloController"/>

</beans>

web.xml

<?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">

    <!--1. 注册DispatcherServlet-->
    <!--这个是包的类-->
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--关联一个springmvc的配置文件-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-servlet.xml</param-value>
        </init-param>
        <!--设置启动级别为1-->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!--设置匹配的请求-->
    <!--/ 不包括.jsp?-->
    <!--/* 包括jsp-->
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

//*的区别
/只匹配所有请求,不会匹配jsp,就是输入/hello.jsp不会匹配,直接跳转
/*当跳转的时候到了jsp,还会再匹配jsp,会无限嵌套。

helloMVC.jsp

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

SpringMVC执行原理


使用注解开发

web.xml:
不变的

springmvc-servlet.xml:
使用注解的写法,配置了新内容,也不用注册bean了

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">


    <!--自动扫描包,让指定包下的注解生效,由IOC容器统一管理-->
    <context:component-scan base-package="it.controller"/>
    <!--让Spring MVC不处理静态资源-->
    <mvc:default-servlet-handler/>
    <!--支持mvc注解驱动,可以代替原来的两个-->
    <mvc:annotation-driven/>

    <!--视图解析器-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
        <!--前后缀就是在注册的方法路径上, 对路径进行补全-->
        <!--前缀-->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!--后缀-->
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

HelloController

package it.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

// 不用实现,直接写注解
@Controller
public class HelloController {
    // 设置映射地址
    @RequestMapping("/hello")
    public String sayHello(Model model){
        // 向模型中添加属性
        model.addAttribute("msg", "hello,anno,mvc");
        // return的是jsp路径,会被加上前缀和后缀
        return "helloMVC";
    }
}

我是不是要知道哪些工作被省略了?


RequestMapper

作用:用域映射url到控制器类或一个特定的处理程序方法。可用于类或方法上。用于类上时,表示类中的所有响应请求的方法都是以该地址作为父路径。

代码

@Controller
@RequestMapping("/h1")
public class HelloController {
    // 设置映射地址
    @RequestMapping("/hello")
    public String sayHello(Model model){
        // 向模型中添加属性
        model.addAttribute("msg", "hello,anno,mvc");
        // return的是jsp路径,会被加上前缀和后缀
        return "helloMVC";
    }
}

url输入/h1/hello


RESTful风格

这一块怎么用呢,总不能自己手打参数吧,应该是某方法调用这个给方法,传参进来,然后跳转吧?

传统

操作方式
通过不同的参数来实现不同的效果,方法比较单一

url输入http://localhost:8080/add?a=1&b=2

代码

@Controller
public class ResfulTest {
    @RequestMapping("/add")
    public String test1(int a, int b, Model model){
        int res = a + b;
        model.addAttribute("msg", "结果为:" + res);
        return "test";
    }
}

RESTful

普通方式
输入:http://localhost:8080/add2/1/2,让方法参数的值对应绑定到一个URL模板变量上。
代码:

@Controller
public class RestfulTest2 {
    // 设定格式
    @RequestMapping("/add2/{p}/{q}")
    // 指定参数
    public String test(@PathVariable int p,@PathVariable int q, Model model){
        int res = q + p;
        model.addAttribute("msg", "res: " + res);
        return "test";
    }
}

指定请求方法类型
输入:http://localhost:8080/add3/1/2
代码:

@Controller
public class RestfulTest3 {
    // 设定格式
    @RequestMapping(value="/add3/{p}/{q}", method= RequestMethod.GET)
    // 指定参数
    public String test(@PathVariable int p,@PathVariable int q, Model model){
        int res = q + p;
        model.addAttribute("msg", "res: " + res);
        return "test";
    }
}

精简、重载版
输入:http://localhost:8080/add4/1/bongba
输出:res: 1bongba Get
代码:

@Controller
public class RestfulTest4 {
    @PostMapping("/add4/{p}/{q}")
    public String test1(@PathVariable int p,@PathVariable String q, Model model){
        model.addAttribute("msg", "res: " + p + q + " Post");
        return "test";
    }

    @GetMapping("/add4/{p}/{q}")
    public String test2(@PathVariable int p,@PathVariable String q, Model model){
        model.addAttribute("msg", "res: " + p + q + " Get");
        return "test";
    }
}


重定向和转发

使用ServletAPI实现,不使用视图解析器

// 此时关闭了视图解析器
@Controller
public class ServletAPI {

    // 这个参数真是说有就有啊!
    @RequestMapping("/t1")
    public void test1(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // 先打印个看看
        resp.getWriter().println("Hello, servlet API");
    }

    @RequestMapping("/t2")
    public void test2(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // 重定向
        resp.sendRedirect("/index.jsp");
    }

    @RequestMapping("/t3")
    public void test3(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 转发,带上信息
        req.setAttribute("msg", "转发");
        // 别放了forward
        req.getRequestDispatcher("/WEB-INF/jsp/test.jsp").forward(req, resp);
    }
}

利用SpringMVC框架,不使用视图解析器

@Controller
public class MVCnoSt {

    @RequestMapping("/m/t1")
    public String test1(){
        // 转发
        return "/index.jsp";
    }

    @RequestMapping("/m/t2")
    public String test2(){
        // 转发2
        return "forward:/index.jsp";
    }

    @RequestMapping("/m/t3")
    public String test3(){
        // 重定向
        return "redirect:/index.jsp";
    }
}

利用SpringMVC框架,使用视图解析器
就是把路径加上了呗,然后还能识别redirect关键字

@Controller
public class MVCst {

    @RequestMapping("/h/t1")
    public String test1(){
        // 转发
        return "test";
    }

    @RequestMapping("/h/t2")
    public String test2(){
        // 重定向
        return "redirect:/index.jsp";
    }
}

接受请求参数及数据回显

提交的域名和处理方法的参数名不一致
使用注解改成别的名字,原来的名字也不能用了
url输入为:http://localhost:8080/hello?username=coco

@Controller
public class Commit {
    // 打印传入的参数,并指定参数的名字
    @RequestMapping("/hello")
    public String test1(@RequestParam("username") String name){
        System.out.println(name);
        return "helloMVC";
    }
}

提交的是一个对象
首先要有个实体类,然后提交的表单域和对象的成员变量名一致,参数使用对象即可。
前端和实体类的参数名若不一致,改成员变量就会变成null
url输入为:http://localhost:8080/user?id=1&age=12&name=jojo

    // 传入的是对象
    @RequestMapping("/user")
    public String test2(User user){
        System.out.println(user);
        return "helloMVC";
    }
}

建议
前端参数不管用不用都加上注解

这是个啥?


乱码问题

使用get可以解决
在方法上用@GetMapping()

利用SpringMVC本身的类过滤

    <!--配置SpringMVC的乱码过滤-->
    <filter>
        <filter-name>encoding</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <!--很关键,别写错了-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>

修改tomcat的配置文件
位置在config/servlet.xml

    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
			   URIEncoding="UTF-8"/>

使用注解

    @RequestMapping(value = "/j2", produces = "application/json;charset=utf-8")

Spring统一配置
可以批量解决编码问题,写在SpringMVC的配置文件中,但是要导个包

    <mvc:annotation-driven>
        <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>

JASON详解

前端生成json

HTML前端json对象
可在开发者工具的console栏看到对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>
        // 这东西不能自闭和
        // 编写一个JavaScript对象
        var user={
            name:"jojo",
            age:3,
            sex:"m"
        };
        // console打印
        console.log(user)
    </script>
</head>
<body>

</body>
</html>

Json和JavaScript对象互转

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script>
        // 这东西不能自闭和
        // 编写一个JavaScript对象
        var user={
            name:"jojo",
            age:3,
            sex:"m"
        };
        // console打印
        console.log(user);
        // json转字符串
        var str = JSON.stringify(user);
        console.log(str);
        // 字符串转json
        var json = JSON.parse('{"a":"hello", "b":"world"}');
        console.log(json);
    </script>
</head>
<body>

</body>
</html>

结果展示:

后端返回多种对象

导包

        <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>

直接返回字符串
很普通的字符串,不能转换为json。

@Controller
public class reJson {

    @RequestMapping("/j1")
    @ResponseBody   // 有了这个注解就不走视图解析器,直接返回字符串
    public String json1(){
        User user = new User("jojo",3);
        return user.toString();
    }
}

输出为:User(name=jojo, age=3)

调包返回字符串
这个方法返回的字符串像json的格式,前端拿到以后能转换为json。

    @RequestMapping("/j2")
    @ResponseBody
    public String json2() throws JsonProcessingException {
        // jackson里面的类
        ObjectMapper mapper = new ObjectMapper();
        // 创建一个对象
        User user = new User("jojo",3);

        String str = mapper.writeValueAsString(user);

        return str;
    }

输出为:{"name":"jojo","age":3}

只返回字符串的注解

@RestController

返回List

    @RequestMapping("/j3")
    public String json3() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        List<User> userList = new ArrayList<User>();
        userList.add(new User("jostar", 2));
        userList.add(new User("jotaro",3));
        userList.add(new User("josehu", 4));

        String str = mapper.writeValueAsString(userList);
        return str;
    }

输出为:[{"name":"jostar","age":2},{"name":"jotaro","age":3},{"name":"josehu","age":4}]

返回时间戳
ObjectMapper会自动把时间换成时间戳返回

    @RequestMapping("/j4")
    public String json4() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        Date date = new Date();
        // ObjectMapper会自动把时间换成时间戳返回
        String str = mapper.writeValueAsString(date);
        return str;
    }

输出为:1595723954367

返回自定义日期格式
两种方法,一种是java自身做;另一种是使用mapper的方法做

    // java方法
    @RequestMapping("/j5")
    public String json5(){
        ObjectMapper mapper = new ObjectMapper();
        // 自定义日期格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = new Date();
        String format = sdf.format(date);
        return format;
    }

输出为:2020-07-26 08:46:55,不带引号

    // mapper方法
    @RequestMapping("/j6")
    public String json6() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        // 自定义日期格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // mapper设置为不适用时间戳的方式
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        // 指定格式
        mapper.setDateFormat(sdf);
        Date date = new Date();
        String str = mapper.writeValueAsString(date);
        return str;
    }

输出为:"2020-07-26 08:46:12",带引号了

自定义输出的工具类

工具类
可以输入格式,也可以不输入格式

public class JsonUtils {
    // 没给格式就是默认格式
    public static String getJson(Object object){
        return getJson(object, "yyyy-MM-dd HH:mm:ss");
    }

    public static String getJson(Object object, String sdf){
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(sdf);
        mapper.setDateFormat(simpleDateFormat);
        // 可能出错
        try {
            String str = mapper.writeValueAsString(object);
            return str;
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
}

测试:

    @RequestMapping("/j7")
    public String json7(){
        Date date = new Date();
        return JsonUtils.getJson(date);
    }

    @RequestMapping("/j8")
    public String json8(){
        Date date = new Date();
        return JsonUtils.getJson(date, "yyyy-MM-dd");
    }
}

后端的转换

    @RequestMapping("/j9")
    public String json9(){
        User user = new User("jojo",12);
        System.out.println("java对象转json字符串");
        String str = JSON.toJSONString(user);
        System.out.println(str);
        System.out.println("json字符串转java对象");
        User user1 = JSON.parseObject(str, User.class);
        System.out.println(user1);
        System.out.println("java对象转json对象并获取单个元素");
        JSONObject jsonObject = (JSONObject) JSON.toJSON(user);
        // 可以通过key获取value,真正的json
        System.out.println(jsonObject.getString("name"));
        System.out.println("json对象转java对象");
        User user2 = JSON.toJavaObject(jsonObject, User.class);
        System.out.println(user2);

        return "helloMVC";
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值