1、MVC架构
MVC:模型(dao,service),视图(jsp),控制器(servlet)
MVC架构要做的事情
- 将url映射到java类或者java类的方法
- 封装用户提交的数据
- 处理请求—调用相关的业务处理—封装响应数据
- 将响应的数据进行渲染,jsp/html等表示层数据
搭建web环境时,Maven创建web项目不要直接在创建的时候勾选,我们需要在创建项目之后,右键项目,点击添加架构支持
点击之后的第一个就是web application勾选就行
2、springMVC初识
springMVC是spring framework的一部分,是基于java实现的MVC的轻量级web框架
springMVC的特点
- 轻量级,简单易学
- 高效,基于请求响应的MVC框架
- 与Spring兼容性好,无缝结合
- 约定优于配置
- 功能强大:RESTful(这就是将网参数传递从key=value模式转换为用斜杠来分割)、数据验证,格式化,本地化,主题等
- 简洁灵活
Spring的web框架围绕DispatcherServlet(调度Servlet)设计
DispatcherServlet的作用是将请求分发到不同的处理器,从Spring 2.5开始,使用Java 5 或者以上版本的用户可以采用基于注解形式开发,十分简洁
正因为SpringMVC好,简单,便捷,易学,天生和spring无缝继承(使用SpringIOC和AOP),使用约定由于配置,能够进行简单的junit测试,支持Restful风格,异常处理,本地化,国际化,数据验证,类型转换,拦截器等,所以需要学习
springMVC调用方法
3、HelloSpringMVC
-
新建一个Moudle,添加web的支持
-
确定导入了SpringMVC的依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.14</version> </dependency>
-
配置web.xml,注册DispatcherServlet
<?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--> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--关联一个springmvc的配置文件 [servlet-name]-name.xml--> <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>
-
编写springMVC的配置文件,名称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 https://www.springframework.org/schema/beans/spring-beans.xsd"> </beans>
-
添加处理映射器
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
-
添加处理器适配器
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
-
添加视图解析器
<!--视图解析器:DispatcherServlet给他的ModelAndView 1.获取了ModelAndView的数据 2.解析ModelAndView的视图名字 3.拼接视图名字,找到对应的视图 hello然后进行拼接 /WEB-INF/jsp/hello.jsp 4.将数据渲染到这个视图上 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <!--前缀--> <property name="prefix" value="/WEB-INF/jsp/"/> <!--后缀--> <property name="suffix" value=".jsp"/> </bean>
-
编写要操作的业务Controller,要么实现org.springframework.web.servlet.mvc包下的Controller接口,要么增加注解;返回一个ModelAndView,装数据,封视图
package com.hty.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 request, HttpServletResponse response) throws Exception { //ModelAndView模型和视图 ModelAndView mv = new ModelAndView(); //封装对象放在ModelAndView中 mv.addObject("msg","HelloSpringMVC!"); //封装要跳转的视图,放在ModelAndView中 mv.setViewName("hello");//: /WEB-INF/jsp/hello.jsp return mv; } }
-
将自己的类交给SpringIOC容器,注册bean
<!--Handler--> <bean id="/hello" class="com.hty.controller.HelloController"/>
-
写要跳转的jsp页面,显示ModelAndView存放的数据,以及我们正常页面
<%-- Created by IntelliJ IDEA. User: hty Date: 2022-02-22 Time: 21:17 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>
-
配置tomcat
可能会遇到代码没问题,但是页面404,可能的原因就是jar包识别不到
解决方法:
最后点击OK就行了
4、SpringMVC执行原理
图中圆圈圈出来的是需要我们自己实现的,剩下的都是springMVC实现的
流程简要分析
- DispatcherServlet表示前置控制器,是整个SpringMVC的控制中心,用户发出请求,DispatcherServlet接受请求并拦截请求
- 我们假设请求的url为:
http://localhost:8080/SpringMVC/hello
- 如上url拆分成三部分
http://localhost:8080
服务器域名- SpringMVC部署在服务器上的web站点
- hello表示控制器
- 通过分析,如上url表示为:请求位于服务器localhost:8080上的SpringMVC站点的hello控制器
- 我们假设请求的url为:
- HandlerMapping为处理器映射,DispatcherServlet调用HandlerMapping,HandlerMpping根据请求url查找Handler
- HandlerExecution表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello
- HandlerExecution将解析后的信息传递给DispatcherServlet,如解析控制器映射等
- HandlerAdapter表示处理器适配器,其按照特定的规则去执行Handler
- Handler让具体的Controller执行
- Controller将具体的执行信息返回给HandlerAdapter,如ModelAndView
- HandlerAdapter将视图逻辑名或模型传递给DispatcherServlet
- DispatcherServlet调用视图解析器(ViewResolver)来解析HandlerAdapter传递的逻辑视图名
- 视图解析器将解析的逻辑视图名传给DispatcherServlet
- DispatcherServlet根据视图解析器解析的视图结果,调用具体的视图
- 最终视图呈现给用户
5、使用注解开发SpringMVC
-
配置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"> <!--注册DispatcherServlet--> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!--关联一个springmvc的配置文件 [servlet-name]-name.xml--> <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>
-
编写spring配置文件
<?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.hty.controller"/> <!--让spring MVC不处理静态资源 css js html mp3 mp4--> <mvc:default-servlet-handler/> <!--支持mvc注解驱动 在spring中一般采用@RequestMapping注解来完成映射关系 要想使@RequestMapping注解生效 必须向上下文中注册DefaultAnnotationHandlerMapping 和一个AnnotationMethodHandlerAdapter实例 这两个实例分别在类级别和方法级别处理 而annotation-driver配置帮助我们自动完成上述两个实例的注入 --> <mvc:annotation-driven/> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <!--视图解析器:DispatcherServlet给他的ModelAndView 1.获取了ModelAndView的数据 2.解析ModelAndView的视图名字 3.拼接视图名字,找到对应的视图 hello然后进行拼接 /WEB-INF/jsp/hello.jsp 4.将数据渲染到这个视图上 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver"> <!--前缀--> <property name="prefix" value="/WEB-INF/jsp/"/> <!--后缀--> <property name="suffix" value=".jsp"/> </bean> </beans>
-
编写controller
package com.hty.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller //在类上加RequestMapping就相当于是下面所有的RequestMapping都要先加这个然后再加其自己的地址 //@RequestMapping("/hello") public class HelloController { @RequestMapping("/hello") public String hello(Model model){ //封装数据 可以在jsp中直接取到 model.addAttribute("msg","Hello,SpringMVCAnnoation"); return "hello";//会被视图解析器处理 } }
-
编写hello.jsp
<%-- Created by IntelliJ IDEA. User: hty Date: 2022-02-23 Time: 17:26 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必须配置的三大组件
- 处理器映射器
- 处理器适配器
- 视图解析器
通常我们只需要手动配置视图解析器,而处理器映射器和处理器适配器只需要开启注解驱动即可,而省去了大段的xml配置
6、Controller配置总结
6.1、控制器Controller
- 控制器负责提供访问应用程序的行为,通常通过接口定义或注解定义两种方法实现
- 控制器负责解析用户的请求并将其转换为一个模型
- 在SpringMVC中一个控制器类可以包含多个方法
6.2、Controller的配置方式
在SpringMVC中,对于Controller的配置方式有很多种
6.2.1、实现Controller接口
Controller是一个接口,接口中只有一个方法
//处理请求且返回一个模型与视图的控制器
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {}
配置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>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
编写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"
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.hty.controller"/>-->
<!--让spring MVC不处理静态资源 css js html mp3 mp4-->
<!-- <mvc:default-servlet-handler/>-->
<!--支持mvc注解驱动
在spring中一般采用@RequestMapping注解来完成映射关系
要想使@RequestMapping注解生效
必须向上下文中注册DefaultAnnotationHandlerMapping
和一个AnnotationMethodHandlerAdapter实例
这两个实例分别在类级别和方法级别处理
而annotation-driver配置帮助我们自动完成上述两个实例的注入
-->
<!-- <mvc:annotation-driven/>-->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!--视图解析器:DispatcherServlet给他的ModelAndView
1.获取了ModelAndView的数据
2.解析ModelAndView的视图名字
3.拼接视图名字,找到对应的视图 hello然后进行拼接 /WEB-INF/jsp/hello.jsp
4.将数据渲染到这个视图上
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="internalResourceViewResolver">
<!--前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--后缀-->
<property name="suffix" value=".jsp"/>
</bean>
</beans>
编写ControllerTest1测试类实现Controller接口
package com.hty.controller;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//只要实现了Controller接口的类 说明这就是一个控制器
public class ControllerTest1 implements Controller {
//返回一个视图对象
@Override
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg","HelloSpringMVC");
modelAndView.setViewName("test");
return modelAndView;
}
}
将ControllerTest1类配置到spring配置文件中
<bean id="/t1" class="com.hty.controller.ControllerTest1"/>
最后进行测试即可
注:
- 实现Controller接口定义控制器是比较老的方法
- 缺点是:一个控制器只有一个方法,如果要多个方法则需要定义多个controller,定义的方式比较麻烦
6.2.2、使用@Controller注解
-
@Controller注解类型用于声明Spring类的实例是一个遥控器(在Spring的IOC部分还有另外三个注解)
-
Spring可以使用扫描机制来找到应用程序中所有基于注解的控制器,为了保证Spring能找到控制器,需要在配置文件中声明组件扫描
<!--自动扫描包,让指定包下的注解生效,由IOC容器统一管理--> <context:component-scan base-package="com.hty.controller"/>
-
增加一个ControllerTest2类,使用注解实现
package com.hty.controller; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; //代表这个类会被spring接管,被这个注解的类中所有方法,如果返回值String,并且有具体页面可以跳转,那么就会被视图解析器解析 @Controller public class ContollerTest2 { //映射访问路径 @RequestMapping("/t2") public String index(Model model){ //SpringMVC会自动实例化一个Model对象用于向视图中传值 model.addAttribute("msg","ControllerTest2"); return "test"; } }
-
然后可以直接进行测试
我们于是就可以发现虽然指向同一个视图,但是返回不同的结果,从这里看出,视图是可以复用的,而且控制器与视图之间是弱耦合关系
7、@RequestMapping说明
@RequestMapping注解用于映射url到控制器类或一个特定的处理程序方法,可以用于类或方法上,用于类上,表示类中的所有响应请求的方法都是以改地址作为父路径
其实就是类似于javaweb中servlet在web.xml进行注册访问地址一样
案例
我们让所有的请求前都加上myweb
package com.hty.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/myweb")
public class ControllerTest3 {
@RequestMapping("/t1")
public String test1(Model model){
model.addAttribute("msg","myweb");
return "test";
}
}
这样访问的时候就需要加上/myweb
8、RestFul风格
Restful就是一个资源定位及资源操作的风格,不是标准也不是协议,只是一种风格,基于这风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制
功能
- 资源:互联网所有的事物都可以被抽象成资源
- 资源操作,使用POST,DELETE,PUT,GET使用不同方法对资源进行操作
- 分别对应 添加、删除、修改、查询
传统方式操作资源:通过不同参数来实现不同效果,方法单一
http://127.0.0.1/item?id=1
使用RESTful操作资源:可以通过不同的请求方式来实现不同的效果!如下:请求地址相同,但是功能可以不同
http://127.0.0.1/item/1
查询 GET
在spingMVC中可以使用@PahtVariable注解,让方法参数的值对应绑定到一个URL模板变量上,添加method参数后可以改变请求方式,此时只有DELETE方式可以访问,或者使用@DeleteMapping("/add/{a}/{b}")也可以
package com.hty.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class RestFulController {
//传统方式 http://localhost:8080/springMVC_04_controller_war_exploded/add?a=1&b=2
@RequestMapping("/add")
public String test1(int a,int b,Model model){
int res = a+b;
model.addAttribute("msg","a+b="+res);
return "test";
}
//Restful风格 http://localhost:8080/springMVC_04_controller_war_exploded/add/a/b
@RequestMapping(value = "/add/{a}/{b}",method = RequestMethod.DELETE)
//@DeleteMapping("/add/{a}/{b}")
public String test2(@PathVariable int a,@PathVariable int b, Model model){
int res = a+b;
model.addAttribute("msg","a+b="+res);
return "test";
}
}
我们使用一个表单页面去请求
<%--
Created by IntelliJ IDEA.
User: hty
Date: 2022-02-24
Time: 0:09
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="add" method="delete">
<input type="text" name="a">
<input type="text" name="b">
<input type="submit">
</form>
</body>
</html>
使用这种风格的好处
- 使路径变的更加简洁
- 获得参数更加方便,框架会自动进行类型转换
- 通过路径变量的类型可以约束访问参数,如果类型不一样,则访问不到对应的请求方法
小结:
springmvc中的@RequestMapping注解能够处理HTTP请求的方法,比如GET,PUT.POST,DELETE以及PATCH
9、结果跳转方式
9.1、使用Controller+视图解析器
在前面的文章中已经重复多次,在这里不赘述
9.2、使用原生的servlet来进行转发和重定向
package com.hty.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@Controller
public class ModelTest1 {
@RequestMapping("/m1/t1")
public String test(HttpServletRequest req, HttpServletResponse resp){
HttpSession session = req.getSession();
System.out.println(session.getId());
return "test";
}
}
9.3、使用springmvc实现转发和重定向
不配置视图解析器
package com.hty.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@Controller
public class ModelTest1 {
@RequestMapping("/m1/t1")
public String test1(Model model){
model.addAttribute("msg","hello1");
//请求转发的方式
return "/WEB-INF/jsp/test.jsp";
}
@RequestMapping("/m1/t2")
public String test2(Model model){
model.addAttribute("msg","hello2");
//请求转发的方式 显示的声明
return "forward:/WEB-INF/jsp/test.jsp";
}
@RequestMapping("/m1/t3")
public String test3(Model model){
model.addAttribute("msg","hello3");
//重定向
return "redirect:/index.jsp";
}
}
注意:转发是服务器内部的,重定向是客户端的,重定向是让客户端去访问重定向的地址,而WEB-INF下的文件是不能通过外部访问的!所以我们不能通过重定向访问WEB-INF下的test.jsp
配置视图解析器之后,转发的地址只需要写一个jsp页面的名称即可,但是重定向依然要写关键字Redirect
package com.hty.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@Controller
public class ModelTest1 {
@RequestMapping("/m1/t1")
public String test1(Model model){
model.addAttribute("msg","hello1");
//请求转发的方式
return "test";
}
@RequestMapping("/m1/t2")
public String test3(Model model){
model.addAttribute("msg","hello2");
//重定向
return "redirect:/index.jsp";
}
}
10、数据处理
10.1、从前端接收数据
10.1.1、提交的参数名称和方法参数名一样
提交数据:http://localhost:8080/springMVC_04_controller_war_exploded/user/t1?username=hty
处理方法
package com.hty.controller;
import com.sun.org.glassfish.gmbal.ParameterNames;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("/user")
public class UserController {
@GetMapping("/t1")
public String test1(String name, Model model){
//接收前端参数
System.out.println(name);
//将结果传递给前端
model.addAttribute("msg",name);
//跳转视图
return "test";
}
}
控制台输出:hty
10.1.2、提交的参数名称和方法参数名不一样
package com.hty.controller;
import com.hty.pojo.User;
import com.sun.org.glassfish.gmbal.ParameterNames;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("/user")
public class UserController {
@GetMapping("/t1")
//使用@RequestParam可以设置从前端接收的参数的名称是什么 此时访问地址就是
//http://localhost:8080/springMVC_04_controller_war_exploded/user/t1?username=hty
public String test1(@RequestParam("username") String name, Model model){
//接收前端参数
System.out.println(name);
//将结果传递给前端
model.addAttribute("msg",name);
//跳转视图
return "test";
}
}
10.1.3、提交的是一个对象
package com.hty.controller;
import com.hty.pojo.User;
import com.sun.org.glassfish.gmbal.ParameterNames;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("/user")
public class UserController {
//前端接收了一个对象 有id name age属性
//http://localhost:8080/springMVC_04_controller_war_exploded/user/t2?id=1&name=hty&age=18
//springmvc会自动进行属性注入
@GetMapping("/t1")
public String test2(User user){
System.out.println(user);
return "test";
}
}
10.2、回传数据给前端
10.2.1、使用ModelAndView
上文已经写过
10.2.2、使用model对象
上文已经写过
10.2.3、使用ModelMap
@GetMapping("/t3")
public String test3(ModelMap modelMap){
modelMap.addAttribute("msg","hello");
return "test";
}
10.2.4、区别
model:只有少数几个方法,只适合于存储数据,简化了新手对于Model对象的操作和理解
ModelMap:继承了LinkedHashMap,除了实现自身的一些方法,同样的继承了LinkedHashMap的方法和特性
ModelAndView:可以在存储数据的同时,可以进行设置返回的逻辑视图,进行控制展示层的跳转
10.3、乱码问题
后端接收到中文之后,发送给前端显示,出来是乱码
package com.hty.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("/e")
public class EncodingController {
@PostMapping("/t1")
public String test1(@RequestParam("name") String name, Model model){
model.addAttribute("msg",name);
return "test";
}
}
第一种解决方式:自定义过滤器
package com.hty.filter;
import javax.servlet.*;
import java.io.IOException;
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
chain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
在web.xml中进行注册
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>com.hty.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<!--这里一定要注意是/* 表示也要过滤jsp文件-->
<url-pattern>/*</url-pattern>
</filter-mapping>
这样可以解决get方法的乱码问题,但是不能解决post方法的乱码问题
第二种解决方式:使用springmvc的过滤器
web.xml配置
<!--springmvc中自带的过滤器-->
<filter>
<filter-name>encoding</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>encoding</filter-name>
<!--这里一定要注意是/* 表示也要过滤jsp文件-->
<url-pattern>/*</url-pattern>
</filter-mapping>
第三种解决方式:前两种方式都不能解决post的乱码问题那么就需要修改tomcat的配置文件,设置编码
修改conf目录下的server.xml,在第69行的代码进行修改
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
URIEncoding="UTF-8"/>
第四种解决方式:如果还是不能解决,那么就需要在网上寻找自定义过滤器
11、JSON
- json是一种轻量级的数据交换格式,目前使用特别广泛
- 采用完全独立编程语言的文本格式来存储和表示数据
- 简介和清晰的层次结构使得json成为理想的交换语言
- 易于人阅读和编写,同时也易于及其解析和生成,并有效的提升网络传输效率
JS语言中,一切都是对象,因此,任何JS支持的类型都可以通过json来表示,例如字符串,数字,对象,数组等,语法格式
- 对象表示为键值对,数据由逗号分隔
- 花括号保存对象
- 方括号保存数组
JSON键值对都是用来保存JS对选哪个的一种方法,写法
{"name":"hty"}
{"age":"3"}
{"sex":"男"}
11.1、JSON和JS对象转换
JSON->JS
var obj = JSON.parse({"a":"hello","b":"World"});
//结果是 {a:'Hello',b:'World'}
JS->JSON
var json = JSON.stringify({a:'Hello',b:'World'});
//结果是 '{"a":"hello","b":"World"'
案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
//编写一个javascript对象
var user = {
name : "hty",
age : 3,
sex : "男"
}
//将js对象转换为json对象
var json = JSON.stringify(user);
console.log(json);
//将json对象转换为js对象
var js = JSON.parse(json);
console.log(js);
</script>
</head>
<body>
</body>
</html>
11.2、jackson
json解析工具,还有fastjson等
使用jackson还需要导入jar包
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.1</version>
</dependency>
案例
package com.hty.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hty.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class UserController {
//使用produces可以解决乱码问题
@RequestMapping(value = "/j1",produces = "application/json;charset=UTF-8")
@ResponseBody //不会走视图解析器 会直接返回一个字符串 或者在类上使用RestController也可以实现
public String json1() throws JsonProcessingException {
//jackson ObjectMapper
ObjectMapper mapper = new ObjectMapper();
//创建一个对象
User user = new User("hty",18,"男");
//使用和这个方法可以把一个对象转换为json字符串
String s = mapper.writeValueAsString(user);
return s;
}
}
使用writeValueAsString方法可以将对象转化为json字符串格式
11.3、乱码问题解决方案
由于produces属性解决的时候过于麻烦,我们可以使用spring配置统一指定
<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>
只需要对mvc:annotation-driven标签进行配置即可
11.4、使用jackson将集合转换为json格式
使用方式和单个对象一样,生成的结果是
[{"name":"hty","age":18,"sex":"男"},{"name":"hty","age":18,"sex":"男"},{"name":"hty","age":18,"sex":"男"},{"name":"hty","age":18,"sex":"男"},{"name":"hty","age":18,"sex":"男"}]
两边会用中括号括起来
11.5、使用jackson将时间转换为json格式
ObjectMapper时间解析后的默认格式为:Timestamp 时间戳
要想改为自定义格式,需要使用SimpleDateFormat类来进行格式化
public String json3() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format = sdf.format(date);
String s = mapper.writeValueAsString(format);
return s;
}
使用ObjectMapper进行格式化输出
public String json3() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
//关闭时间戳
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
mapper.setDateFormat(sdf);
Date date = new Date();
String s = mapper.writeValueAsString(date);
return s;
}
11.6、jackson工具类的编写
package com.hty.util;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.text.SimpleDateFormat;
public class JsonUtil {
/**
* @param object 需要转换的对象
* @param dateformat 如果是日期那就需要传入日期格式 例如 "yyyy-MM-dd HH:mm:ss"
* @return 返回的是一个json格式的字符串
* */
public static String getJson(Object object,String dateformat){
ObjectMapper mapper = new ObjectMapper();
//关闭时间戳
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false);
SimpleDateFormat sdf = new SimpleDateFormat(dateformat);
mapper.setDateFormat(sdf);
try {
return mapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
/**
* @param object 需要转换的对象
* @return 返回的是一个json格式的字符串
* */
public static String getJson(Object object){
return getJson(object,"yyyy-MM-dd HH:mm:ss");
}
}
12、SSM框架整合
项目地址
E:\编程\java项目\狂神说ssm框架整合
13、Ajax技术
- Asynchronous JavaScript and XML(异步的JS和XML)
- Ajax是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术
- Ajax不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术
- Ajax就是在百度搜索的时候会自动在搜索框下面显示出来可能需要的搜索关键词,完成自动补充
- 传统的网页(即不用ajax技术的网页)想要更新内容或者提交一个表单,都需要重新加载整个网页
- 使用ajax技术的网页通过在后台服务器进行少量的数据交换,就可以实现异步局部更新
- 使用Ajax用户可以创建接近本地桌面应用的直接、高可用、更丰富、更动态的Web用户界面
我们可以使用jQuery中的ajax库来进行实现
语法:$.ajax({name:value, name:value, ... })
名称 | 值/描述 |
---|---|
async | 布尔值,表示请求是否异步处理。默认是 true。 |
beforeSend(xhr) | 发送请求前运行的函数。 |
cache | 布尔值,表示浏览器是否缓存被请求页面。默认是 true。 |
complete(xhr,status) | 请求完成时运行的函数(在请求成功或失败之后均调用,即在 success 和 error 函数之后)。 |
contentType | 发送数据到服务器时所使用的内容类型。默认是:“application/x-www-form-urlencoded”。 |
context | 为所有 AJAX 相关的回调函数规定 “this” 值。 |
data | 规定要发送到服务器的数据。 |
dataFilter(data,type) | 用于处理 XMLHttpRequest 原始响应数据的函数。 |
dataType | 预期的服务器响应的数据类型。 |
error(xhr,status,error) | 如果请求失败要运行的函数。 |
global | 布尔值,规定是否为请求触发全局 AJAX 事件处理程序。默认是 true。 |
ifModified | 布尔值,规定是否仅在最后一次请求以来响应发生改变时才请求成功。默认是 false。 |
jsonp | 在一个 jsonp 中重写回调函数的字符串。 |
jsonpCallback | 在一个 jsonp 中规定回调函数的名称。 |
password | 规定在 HTTP 访问认证请求中使用的密码。 |
processData | 布尔值,规定通过请求发送的数据是否转换为查询字符串。默认是 true。 |
scriptCharset | 规定请求的字符集。 |
success(result,status,xhr) | 当请求成功时运行的函数。 |
timeout | 设置本地的请求超时时间(以毫秒计)。 |
traditional | 布尔值,规定是否使用参数序列化的传统样式。 |
type | 规定请求的类型(GET 或 POST)。 |
url | 规定发送请求的 URL。默认是当前页面。 |
username | 规定在 HTTP 访问认证请求中使用的用户名。 |
xhr | 用于创建 XMLHttpRequest 对象的函数。 |
14、拦截器
springMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理,开发者可以自己定义一些拦截器来实现特定的功能
过滤器与拦截器的区别:拦截器AOP思想的决堤应用
拦截器:
- 是springmvc框架自己的,只有使用了springmvc框架的工程才能使用
- 拦截器只会拦截访问的控制器方法,如访问的是jsp/html/css/image/js是不会拦截的
14.1、自定义拦截器
实现HandlerInterceptor接口
package com.hty.config;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
//return true 执行下一个拦截器,放行
//return false 执行下一个拦截器,放行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("=============处理前==============");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("=============处理后==============");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("=============清理==============");
}
}
在applicationContext.xml中需要进行配置
<!--拦截器配置-->
<mvc:interceptors>
<mvc:interceptor>
<!--包括这个请求下面的所有请求-->
<mvc:mapping path="/**"/>
<bean class="com.hty.config.MyInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
14.2、登陆拦截
网站不登录不能访问主页
package com.hty.config;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
//放行的判断
//已经在登陆页面了
if(request.getRequestURI().contains("login")){
return true;
}
//已经注册了
if(session.getAttribute("userLoginInfo") != null){
return true;
}
//判断什么情况下没有登陆
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
return false;
}
}
注:一定要在spring配置文件进行注册才行
14.3、小细节
在web目录下的jsp文件拦截器不会进行拦截