SpringMvcDay(01)

16 篇文章 1 订阅
5 篇文章 0 订阅

@Resource注解的使用

@Resource注解的功能和@Autowired

将我们之前编写的代码中的@Autowired注解替换为@Resource一般情况下都是可以正常运行的

也就是说由@Resource标注的属性也会进行自动装配

他们的区别是:

1.提供者不同:@Autowired是Spring提供的@Resource是java提供的

2.注入规则不同:

原则上@Autowired注入规则为"byType"(通过类型)

​ @Resource注入规则为"byName"(通过名称)这里的名称就是对象的id

@Autowired是先检查类型,如果有类型匹配直接匹配,只通过类型不能匹配了,再通过id

@Resource是先匹配id,如果id匹配直接成功,如果没有id匹配再匹配类型

SpringMVC

什么是MVC

MVC实际上并不是Spring专有的

MVC实际是指

M:Model(数据模型) V:View(视图) C:Controller(控制器)

M:实体类 V:页面 C:Servlet

由于自己编写MVC思想的项目有些步骤比较繁琐所以市面上有很多MVC框架

简化MVC设计编写过程

常见的有:Struts2,JFinal,SpringMVC

SpringMvc概述

SpringMvc实际上主要针对的是视图(V)到控制器©的代码

控制器中要想获得视图的信息有很多冗余代码

(Servlet中需要很多request.getParameter()这样的方法获得表单中的信息)

如果使用SpringMvc就能简便的获得他们

而且现在我们是请求和Servlet1对1的关系,

如果项目大,请求多nameServlet的数量也是不可控的

这也是SpringMvc解决的问题

SpringMvc执行流程

  • DispatcherServlet:前端控制器,用于接收所有请求
  • HandlerMapping:用于配置请求与运行的方法的对应关系
  • Controller:控制器,这种对象时我们编写处理具体功能的
  • ModelAndView:控制器完成请求处理后,的处理结果一般是指定页面名称
  • ViewResolver:视图解析器,根据给定的页面名称,生成页面内容

在这里插入图片描述

SpringMvc的HelloWorld程序

步骤1:

修改一下web.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
	version="3.0">
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>

步骤2:

添加pom.xml文件中 SpringMvc以及其他相关内容的依赖

<!-- Spring MVC -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>
<!-- Thymeleaf -->
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf</artifactId>
    <version>3.0.11.RELEASE</version>
</dependency>
<!-- Thymeleaf整合Spring -->
<dependency>
    <groupId>org.thymeleaf</groupId>
    <artifactId>thymeleaf-spring5</artifactId>
    <version>3.0.11.RELEASE</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.25</version>
</dependency>

步骤3:

创建一个包(cn.tedu.config)

在这个包新建一个WebApp类

代码如下

//AbstractAnnotationConfigDispatcherServletInitializer
//是SpringMVC提供的,它包含几个必须由我们重写并配置SpringMvc运行信息的方法

public class WebApp extends
        AbstractAnnotationConfigDispatcherServletInitializer {
    // 继承的这个抽象类有一个特征
    // tomcat一旦启动就会自动运行下面的三个方法

    @Override
    protected Class<?>[] getRootConfigClasses() {
        System.out.println("111111");
        return new Class[0];
    }
    @Override
    protected Class<?>[] getServletConfigClasses() {
        System.out.println("222222");
        return new Class[0];
    }
    @Override
    protected String[] getServletMappings() {
        System.out.println("333333");
        return new String[0];
    }
}

启动tomcat会看到111,222,333的输出

证明现在SpringMvc框架配置是正确的

步骤4:

配置SpringMvc的信息

有两方面信息要配置

1.请求的拦截规则 我们暂时规定 以".do"结尾的请求由SpringMvc接收处理

2.指定Spring的配置类,配置的是配置类的反射

//AbstractAnnotationConfigDispatcherServletInitializer
//是SpringMVC提供的,它包含几个必须由我们重写并配置SpringMvc运行信息的方法

public class WebApp extends
        AbstractAnnotationConfigDispatcherServletInitializer {
    // 继承的这个抽象类有一个特征
    // tomcat一旦启动就会自动运行下面的三个方法

    //RootConfig配置和控制器无关的Spring配置类
    @Override
    protected Class<?>[] getRootConfigClasses() {
        System.out.println("111111");
        return new Class[0];
    }
    //ServletConfig配置和控制器相关的Spring配置类
    @Override
    protected Class<?>[] getServletConfigClasses() {
        System.out.println("222222");
        return new Class[]{SpringMvcConfig.class};
    }
    //getServletMappings是指定SpringMvc对什么样的请求进行处理的方法
    //配置*.do 表示所有以.do结尾的请求,都会交由SpringMvc处理
    @Override
    protected String[] getServletMappings() {
        System.out.println("333333");
        return new String[]{"*.do"};
    }
}

步骤5:

创建配置类

SpringMvcConfig类

只需要添加一个扫描的包就可以了

@ComponentScan("cn.tedu.controller")
public class SpringMvcConfig {

}

步骤6:

创建cn.tedu.controller包

在这个包中新建一个控制器DemoController

//使用@Controller注解这个类
//能够将这个类注入到Spring容器的同时还能表明它是一个控制器
@Controller
public class DemoController {

    // 编写@GetMapping注解来规定什么请求能够访问这个方法
    // 我们配置了只有.do结尾的请求能够进入SpringMvc所以这里的路径必须以.do结尾
    @GetMapping("/hello.do")
    // 我们由于没有具体页面可以显示,所以需要添加下面的注解
    // 表示当前请求的结果就是在浏览器上显示返回的字符串
    @ResponseBody
    public String demo(){
        System.out.println("demo运行");
        return "Hello SpringMvc";
    }
}

SpringMvc实现显示视图

SpringMvc显示视图也是依赖Thymeleaf

Thymeleaf也是哦Spring框架推荐使用的模板引擎,使用率是比较高的

我们已经在上面的配置中包含了pom.xml的依赖的配置

我们直接将Thymeleaf模板引擎注入到Spring容器中即可

在SpringMvcConfig类中获得代码如下

注意注入的代码不是自己编写的,不用了解具体每行代码的功能

@ComponentScan("cn.tedu.controller")
public class SpringMvcConfig {

    @Bean
    public ThymeleafViewResolver viewResolver(){
        System.out.println("init ThymeleafViewResolver");

        //设置模板保存位置为 /resources/templates/*.html
        ClassLoaderTemplateResolver templateResolver =
                new ClassLoaderTemplateResolver();
        //模版存储文件夹
        templateResolver.setPrefix("/templates/");
        //模版后缀
        templateResolver.setSuffix(".html");
        templateResolver.setCharacterEncoding("UTF-8");
        templateResolver.setTemplateMode(TemplateMode.HTML);
        templateResolver.setCacheable(true);
        //创建模板引擎
        SpringTemplateEngine templateEngine =
                new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver);
        templateEngine.setEnableSpringELCompiler(true);
        //创建模版解析器
        ThymeleafViewResolver viewResolver =
                new ThymeleafViewResolver();
        viewResolver.setCharacterEncoding("UTF-8");
        viewResolver.setTemplateEngine(templateEngine);
        return viewResolver;
    }
}

需要注意,我们模板文件(html)文件

必须放在resources/templates/文件夹下,没有的话需要创建!

创建了templates文件夹后可以在其中创建一个html文件

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>这是SpringMvc和Thymeleaf显示的页面</h1>
</body>
</html>

下面我就可以使用SpringMvc来访问这个页面了

控制器中新加一个方法来返回这个页面

代码如下

 @GetMapping("/test.do")
    public ModelAndView test(){
        System.out.println("运行了test");
        //返回的hello会被模板引擎自动添加配置好的前缀和后缀
        //resources/templates/hello.html
        return new ModelAndView("hello");
    }

我们想让SpringMvc有用武之地需要表单来体现一下

创建一个带有表单的页面:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>用户注册</title>
</head>
<body>
<h1>注册</h1>
<form method="post" action="handle_reg.do">
    <div>
        <label>用户</label>
        <input type="text" name="username">
    </div>
    <div>
        <label>密码</label>
        <input type="password" name="password">
    </div>
    <div>
        <label>年龄</label>
        <input type="number" name="age">
    </div>
    <div>
        <label>电话</label>
        <input type="tel" name="phone">
    </div>
    <div>
        <label>电邮</label>
        <input type="email" name="email">
    </div>
    <div>
        <input type="submit" value="提交">
    </div>
</form>
</body>
</html>

习题:再编写一个方法

使用reg.do的路径让这个表单页面显示在浏览器上!

使用SpringMvc接收表单信息

实现上面的功能新建一个控制器

UserController代码如下

//@RestController和@Controller的区别
//@RestController除了Controller注解的功能将当前类注入到Spring容器之外
//所有返回字符串的方法,都是直接将字符串返回相当于加了@ResponseBody
//如果想返回页面,直接返回ModelAndView对象即可
@RestController
//@RequestMapping()写在类上,表示要访问这个类中的方法,需要统一前置增加指定内容
//比如("/user") 就表示要想访问这个类中的方法需要先写"/user"
@RequestMapping("/user")
public class UserController {

    //@GetMapping("/abc.do")//localhost:8080/user/abc.do
    //...
    @GetMapping("/reg.do")//localhost:8080/user/reg.do
    public ModelAndView reg(){
        return new ModelAndView("reg");
    }


}

显示表单以后我们想提交信息到控制器

就像之前在Servlet类中获得表单中的信息一样

但是SpringMvc控制器完成这个操作比Servlet简单很多

代码如下

	//接收表单信息的方法
    //@PostMapping来接受post请求
    @PostMapping("/handle_reg.do")
    public String handReg(
            String username,
            String password,
            int age,
            String phone,
            String email
    ){
        System.out.println("用户名:"+username);
        System.out.println("密码:"+password);
        System.out.println("年龄:"+age);
        System.out.println("电话:"+phone);
        System.out.println("电邮:"+email);
        return "OK";
    }

需要注意上面的方法接收的请求是Post请求所以使用@PostMapping来接收

方法的参数必须严格按照对应表单中name属性的值来获得用户输入的信息

类型会自动转换(int age直接获取即可)

虽然这样的代码已经比Servlet简单了,但是开发大型项目可能又十几甚至更多属性的表单

我们可以再简单一些

新建一个包,包中新建一个User类

代码如下

public class User implements Serializable {
    private String username;
    private String password;
    private int age;
    private String phone;
    private String email;

	//省略set\get\toString

}

上面定义的类中的属性名和表单的name属性值对应

有了这个类我们就可以更简单的获得表单中的信息

代码如下

    @PostMapping("/handle_reg.do")
    public String handReg(User user){
        System.out.println(user);
        return "OK";
    }

常见问题解答

1.User类对象时怎么接收到表单信息的

本质上是DispatcherServlet检测Controller方法属性的

内部是同属性的set方法为对象赋值的

赋值原则是尽量赋值

2.路径问题

/user是怎么保持的

访问/user/reg.do就已经进入了/user/目录下

表单提交action="handle_reg.do"是相对路径,是在/user/下提交的

提交结果是/user/handle_reg.do ,所以不需要编写前置的/user/

表单提交的中文信息处理

上面提交信息到Controller中如果是中文会发生乱码

为了防止乱码,回到WebApp类中添加一个方法,设置过滤器即可

//这个方法不是必须重写的
    //但是表单提交中文有乱码
    //添加一个过滤器防止乱码的出现
    @Override
    protected Filter[] getServletFilters() {
        return new Filter[]{new CharacterEncodingFilter("UTF-8")};
    }

控制器方法获得Request对象

我们可能仍然偶尔需要HttpServletRequest类的方法

name怎么在现有的控制器方法中获得这个对象呢?

代码如下

@PostMapping("/handle_reg.do")
    public String handReg(User user, HttpServletRequest request){
        System.out.println(user);
        //输出客户端的ip地址
        System.out.println("访问服务器的客户端地址为:"+request.getRemoteAddr());
        return "OK";
    }

直接再方法的参数列表中声明HttpServletRequest类型的变量即可

DispatcherServlet会自动将当前请求对象赋值为这个属性!

控制器方法接收get请求参数

get请求参数一般都是以url中?开始的

例如

http://localhost:8080/deleteUser.do?id=10&name=tom

控制器中编写代码,原理和写法和接收表单信息是一致的

    //接收get请求参数的方法
    @GetMapping("/get.do")
    //参数的参数名必须和?后面的名称一致
    public String get(int id){
        System.out.println("id:"+id);
        return  "ok";
    }

特殊参数名处理

当get请求参数名称是java关键字时,必须使用@RequestParam进行注解

代码如下

@GetMapping("/get.do")
    //如果get请求参数名是特殊字符\java关键字name参数名称就无法直接对应
    //需要在参数前添加@RequestParam注解
    // 这个注解可以指定后门参数对象的get请求参数名
    public String get(@RequestParam("if") int num){
        System.out.println("num:"+num);
        return  "ok";
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值