从零入门的SpringMVC笔记
一、Spring概述
1. SSM框架优化的方向
图解:
MyBatis是对数据访问层的优化
SpringMVC是对控制器的优化
Spring框架时管理其他框架的框架
2.SpringMVC框架的优点
- 轻量级,基于MVC的框架
- 易于上手,容易理解,功能强大
- 它具备IOC和AOP
- 完全基于注解开发
3. 时序图解析
可以从图上看出,SpringMVC对控制器的优化
4.SpringMVC的执行流程
一个好汉三个帮:
DispatcherServlet是核心
4.分析web请求
web请求执行的流程
核心处理器
index.jsp<--------------->DispatcherServlet<------------------->SpringMVC的处理器是一个普通的方法
one.jsp <--------------->DispatcherServlet<------------------->SpringMVC的处理器是一个普通的方法
二、SpringMVC注解式开发
1. @RequestMapping功能
可以放在方法上或者放在类上
目的是为了可以让你访问到服务器的资源
执行顺序:
- 前端点击超链接
<a href="${pageContext.request.contextPath}/a/demo.action">访问服务器1</a>
- 被DispatcherServlet拦截,如果是/a/demo.action则进入action类
@Controller
@RequestMapping("/a")
public class DemoAction {
/**
* action中的规范
* public
* 返回值任意
* 名字任意
* 参数任意
* 需要@RequestMapping()
*/
@RequestMapping("/demo")
public String demo(){
System.out.println("访问了a的demo");
return "main";
}
}
- 经过包扫描,controller类自动添加前后缀
<!--添加包扫描-->
<context:component-scan base-package="com.powernode.springmvc.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>
- 最后返回到main中,加上前缀后缀/admin/main.jsp
2.识别get还是post
@RequestMapping(value = "/demo",method = RequestMethod.GET)
public String req1(){
System.out.println("我是处理get请求的");
return "main";
}
@RequestMapping(value = "/demo",method = RequestMethod.POST)
public String req2(){
System.out.println("我是处理post请求的");
return "main";
}
3.五种数据提交的方式
第1种:单个数据提交
在form表单中,对应的name即是后台Controller的参数
<h1>五种数据提交的方式</h1>
<form action="${pageContext.request.contextPath}/datasubmit.action" method="post">
名字:<input type="text" name="name"><br>
年龄:<input type="text" name="age"><br>
<input type="submit">
</form>
@RequestMapping("datasubmit")
public String one(String name,Integer age){
System.out.println("名字是:"+name+",年龄为:"+age);
return "main";
}
第2种:对象封装提交数据
<h1>第二种提交方式,对象封装提交</h1>
<form action="${pageContext.request.contextPath}/two.action">
名字:<input type="text" name="user"><br>
年龄:<input type="text" name="age"><br>
<input type="submit">
</form>
第3种:动态占位符提交数据(从路径中)
在html中用 斜杆+值提交,后台用斜杆+大括号接收数据,在后台参数位置加上@PathVariable接收
<h1>第三种提交方式,动态占位符提交</h1>
<form action="${pageContext.request.contextPath}/three/林泽培/20.action">
<input type="submit">
</form>
@RequestMapping("/three/{name}/{age}")
public String three(@PathVariable String name,@PathVariable int age){
System.out.println(name+","+age);
return "main";
}
第4种:前端页面参数与后端不一致
遇到前端参数与后端不一致的情况,我们可以使用@RequestParm起别名
<h1>第四种提交方式,前端参数与后端不一致</h1>
<form action="${pageContext.request.contextPath}/fore.action">
名字:<input type="text" name="name"><br>
年:<input type="text" name="age"><br>
<input type="submit">
</form>
/**
* 双引号内填写前端参数名称
*
* @param uname
* @param uname
* @return
*/
@RequestMapping("/fore")
public String fore(@RequestParam("name") String uname, @RequestParam("age") int uage) {
System.out.println(uname + "," + uage);
return "main";
}
第5种:手工提取参数
使用古老的Servlet技术,提取request参数获取值
<h1>第五种提交方式,request提取参数</h1>
<form action="${pageContext.request.contextPath}/five.action">
名字:<input type="text" name="name"><br>
年龄:<input type="text" name="age"><br>
<input type="submit">
</form>
@RequestMapping("/five")
public String five(ServletRequest request){
String name = request.getParameter("name");
Integer age = Integer.parseInt(request.getParameter("age"));
System.out.println(name+age);
return "main";
}
8. 中文编码设置
<!--设置中文过滤器-->
<filter>
<!--过滤器名称-->
<filter-name>encode</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>
<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方法的返回值
- String:客户端资源的地址,自动拼接前缀和后缀.还可以屏蔽自动拼接字符串,可以指定返回的路径.
- Object:返回json格式的对象.自动将对象或集合转为json.使用的jackson工具进行转换,必须要添加jackson依赖.一般用于ajax请求.
- void:无返回值,一般用于ajax请求.
- 基本数据类型,用于ajax请求.
- ModelAndView:返回数据和视图对象,现在用的很少.
10.ajax请求json数组功能实现
<a href="javascript:showStu()">访问服务器返回学生集合</a>
<div id="mydiv">等待服务器返回数据</div>
<script type="text/javascript">
function showStu() {
//使用jQuery封装的ajax()方法发送请求
$.ajax({
url:"${pageContext.request.contextPath}/list.action",
type:"get",
dataType:"json",
success:function(stuList) {
var s = "";
$.each(stuList,function(i,stu) {
s+=stu.name + "----" + stu.age+"<br>";
});
//回显数据
$("#mydiv").html(s);
}
})
}
</script>
@Controller
public class StudentListAction {
@RequestMapping("/list")
@ResponseBody //解析ajax,必须在springmvc.xml中配置
public List<Student> list(){
Student stu1 = new Student("李白",21);
Student stu2 = new Student("林白",22);
Student stu3 = new Student("白白",23);
List<Student> students = new ArrayList<>();
students.add(stu1);
students.add(stu2);
students.add(stu3);
//返回的学生数组,springmvc自动转成json格式
return students;
}
}
11.请求转发和重定向的区别
请求转发:是基于服务端的跳转,因此显示的URL还是xx.action
重定向:是基于客户端的跳转,等同于重新访问一个网址,所以URL为正常
<a href="${pageContext.request.contextPath}/one.action"><h1>方法1:请求转发</h1></a>
<a href="${pageContext.request.contextPath}/two.action"><h1>方法2:请求转发action</h1></a>
<a href="${pageContext.request.contextPath}/three.action"><h1>方法3:重定向</h1></a>
<a href="${pageContext.request.contextPath}/fore.action"><h1>方法4:重定向action</h1></a>
<a href="${pageContext.request.contextPath}/five.action"><h1>方法5:随便访问</h1></a>
@Controller
public class JumpAction1 {
/**
* 方法1:请求转发(默认)
* @return
*/
@RequestMapping("/one")
public String one(){
return "main";
}
/**
* 方法2:请求转发action
* @return
*/
@RequestMapping("/two")
public String two(){
return "forward:/haha.action";
}
/**
* 方法3:重定向
* @return
*/
@RequestMapping("/three")
public String three(){
return "redirect:/admin/main.jsp";
}
/**
* 方法4:重定向action
* @return
*/
@RequestMapping("/fore")
public String fore(){
return "redirect:/haha.action";
}
/**
* 方法5:随便访问一个
*/
@RequestMapping("/five")
public String five(){
return "redirect:/aaa.jsp";
}
}
12. 默认参数传递数据
/**
* 带参数跳转到页面,请求转发到页面
* 只能用请求转发,如果用重定向会导致参数丢失(除了session
* @return
*/
@RequestMapping("/six")
public String six(HttpServletRequest request,
HttpServletResponse response,
Map map,
Model model,
HttpSession session){
User u = new User("王无",21);
request.setAttribute("user1",u);
map.put("user2",u);
model.addAttribute("user3",u);
session.setAttribute("user4",u);
return "main";
}
<html>
<head>
<title>Title</title>
</head>
<body>
${user1}
${user2}
${user3}
${user4}
main,....
</body>
</html>
13.单个日期注入
在springmvc中,前端传来的日期会被当成字符串传过来,所以我们在后端接收到要使用注解@DateTimeFormat,此注解必须搭配springmvc.xml文件中的mvc:annotationdriven标签
<form action="${pageContext.request.contextPath}/datesubmit.action">
日期:<input type="date" name="date">
<input type="submit">
</form>
@RequestMapping("/datesubmit")
public String datesubmit(@DateTimeFormat(pattern = "yyyy-MM-dd") Date date){
System.out.println(date);
return "forward:/aaa.jsp";
}
14. 多个日期格式转换
注册一个注解,用来解析本类中所有的日期类型,自动转换.
/**
* 绑定全局日期格式转换
* @param dataBinder
*/
@InitBinder
public void initBinder(WebDataBinder dataBinder){
dataBinder.registerCustomEditor(
Date.class,new CustomDateEditor(
new SimpleDateFormat("yyyy-MM-dd"),true
)
);
}
@RequestMapping("/datesubmit")
public String datesubmit(Date date){
System.out.println(date);
return "forward:/aaa.jsp";
}
15.日期的显示处理
在页面上显示好看的日期,必须使用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" %>
C)使用标签显示数据
<table width="800px" border="1">
<tr>
<th>姓名</th>
<th>生日</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>
16. springMVC流程复习
- DispatcherServlet接收到用户请求,开始解析数据
- 通过HandlerMapping解析出demo
- 通过HandlerAdapter判断是bean还是xml
- 创建对应的controller,进行(业务逻辑、数据访问层,如果有),处理完返回值给ModelAndView
- 返回值若是main,把值传给ViewResolver进行拼接,返回给核心处理器
- DispatcherServlet控制view显示给用户什么页面
17. 资源在WEB-INF目录下.
此目录下的动态资源,不可直接访问,只能通过请求转发的方式进行访问 .
@Controller
public class WebInfAction {
@RequestMapping("/showIndex")
public String showIndex(){
System.out.println("访问index.jsp");
return "index";
}
@RequestMapping("/showMain")
public String showMain(){
System.out.println("访问main.jsp");
return "main";
}
@RequestMapping("/showLogin")
public String showLogin(){
System.out.println("访问login.jsp");
return "login";
}
//登录的业务判断
@RequestMapping("/login")
public String login(String name, String pwd, HttpServletRequest request){
if("zar".equalsIgnoreCase(name) && "123".equalsIgnoreCase(pwd)){
return "main";
}else{
request.setAttribute("msg","用户名或密码不正确!");
return "login";
}
}
}
三. SpringMVC的拦截器
1.概述
针对请求和响应进行的额外的处理.在请求和响应的过程中添加预处理,后处理和最终处理.
2. 拦截器执行的时机
- preHandle():在请求被处理之前进行操作,预处理
- postHandle():在请求被处理之后,但结果还没有渲染前进行操作,可以改变响应结果,后处理
- afterCompletion:所有的请求响应结束后执行善后工作,清理对象,关闭资源 ,最终处理.
3.拦截器实现的两种方式
- 继承HandlerInterceptorAdapter的父类
- 实现HandlerInterceptor接口,实现的接口,推荐使用实现接口的方式
4.拦截器的步骤
- 改造登录方法,在session中存储用户信息,用于进行权限验证
@RequestMapping("/login")
public String login(String name, String pwd, HttpServletRequest request){
if("zar".equalsIgnoreCase(name) && "123".equalsIgnoreCase(pwd)){
//在session中存储用户信息,用于进行权限验证
request.getSession().setAttribute("users",name);
return "main";
}else{
request.setAttribute("msg","用户名或密码不正确!");
return "login";
}
}
- 开发拦截器的功能.实现HandlerInterceptor接口,重写preHandle()方法
if(request.getSession().getAttribute("users") == null){
//此时就是没有登录,打回到登录页面,并给出提示
request.setAttribute("msg","您还没有登录,请先去登录!");
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
return false;
}
return true;//放行请求
- 在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:interceptor>
</mvc:interceptors>
四、SSM搭建
- controller层即配置mvc相关的内容,包括扫描加有@Controller注解的类所在包、一个好汉(核心servlet)三个帮的三个帮手,并在web.xml中注册核心servlet
- service层就是业务层,包括主业务(包扫描)和切面业务(aop)相关,这里事务是一种切面业务
- dao层数据访问层,因为整合了mybatis,所以配置sqlsessionbuildFactory(需要mybatis配置+数据源(因为数据源交给spring管理,不再在mybatis中配置))
1.SSM整合的步骤
- 建库,建表
- 新建Maven项目,选择webapp模板
- 修改目录
- 修改pom.xml文件(使用老师提供)
- 添加jdbc.properties属性文件
- 添加SqlMapConfig.xml文件(使用模板)
- 添加applicationContext_mapper.xml文件(数据访问层的核心配置文件)
- 添加applicationContext_service.xml文件(业务逻辑层的核心配置文件)
- 添加spirngmvc.xml文件
- 删除web.xml文件,新建,改名,设置中文编码,并注册spirngmvc框架,并注册Spring框架
- 新建实体类user
- 新建UserMapper.java接口
- 新建UserMapper.xml实现增删查所有功能,没有更新
- 新建service接口和实现类
- 新建测试类,完成所有功能的测试
- 新建控制器,完成所有功能
- 浏览器测试功能
2.什么是跨域访问
前端是8082端口,后端是8080端口
这称之为跨端口
而跨端口是跨域的一种
跨协议也是跨域的一种
不同的服务器,跨服务也是跨域的一种
@CrossOrigin //服务器跨域访问