转载请标明出处:https://blog.csdn.net/men_ma/article/details/106847165.
本文出自 不怕报错 就怕不报错的小猿猿 的博客
springMVC环境搭建之springMVC原理及工作流程&springMVC完成增删改查(springMVC之入门)
目标
1、Springmvc简介及配置
2、Springmvc之helloword实现
3、Springmvc常用注解及返回值处理
4、Springmvc静态资源处理
1.Springmvc简介及配置
1.1.MVC框架是什么?MVC设计模式的好处有哪些
mvc是一种设计模式(设计模式就是日常开发中编写代码的一种好的方法和经验的总结)。模型(model)-视图(view)-控制器(controller),三层架构的设计模式。用于实现前端页面的展现与后端业务数据处理的分离。
mvc设计模式的好处
1.分层设计,实现了业务系统各个组件之间的解耦,有利于业务系统的可扩展性,可维护性。
2.有利于系统的并行开发,提升开发效率。
1.2 什么是springMVC?
Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把模型-视图-控制器分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。
1.3 Spring MVC的优点
(1)可以支持各种视图技术,而不仅仅局限于JSP;
(2)与Spring框架集成(如IoC容器、AOP等);
(3)清晰的角色分配:前端控制器(dispatcherServlet) , 请求到处理器映射(handlerMapping), 处理器适配器(HandlerAdapter), 视图解析器(ViewResolver)。
(4) 支持各种请求资源的映射策略。
1.4 Spring MVC的主要组件?
(1)前端控制器 DispatcherServlet(不需要程序员开发)
作用:接收请求、响应结果,相当于转发器,有了DispatcherServlet 就减少了其它组件之间的耦合度。
(2)处理器映射器HandlerMapping(不需要程序员开发)
作用:根据请求的URL来查找Handler
(3)处理器适配器HandlerAdapter
注意:在编写Handler的时候要按照HandlerAdapter要求的规则去编写,这样适配器HandlerAdapter才可以正确的去执行Handler。
(4)处理器Handler(需要程序员开发)
(5)处理器或页面控制器(Controller)
(5)视图解析器 ViewResolver(不需要程序员开发)
(6)验证器(Validator)
作用:进行视图的解析,根据视图逻辑名解析成真正的视图(view)
(7)视图View(需要程序员开发jsp)
View是一个接口, 它的实现类支持不同的视图类型(jsp,freemarker,pdf等等)
1.5 SpringMVC处理请求的流程(工作原理)
阿拉伯数字代表图中的步骤解释
第一步:http请求到DispatcherServlet
1.用户(客户端)发送请求至前端控制器DispatcherServlet;
第二步:HandlerMapping寻找处理器
2.由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller;
第三步:调用处理器Controller
3.DispatcherServlet将请求提交到Controller;
第四步:Controller调用业务逻辑处理后,返回ModelAndView
(4、5).调用业务处理和返回结果:Controller调用业务逻辑处理后,返回ModelAndView;
第五步:DispatcherServlet查询ModelAndView
(6、7).处理视图映射并返回模型:DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图;
第六步:ModelAndView反馈浏览器HTTP
8.Http响应:视图负责将结果显示到客户端
1.6 SpringMVC核心开发步骤
1 DispatcherServlet在web.xml中的部署描述,从而拦截请求到springMVC
2 HandlerMapping的配置,从而将请求映射到处理器
3 HandlerAdapter的配置,从而支持多种类型的处理器
4 处理器(页面控制器)的配置,从而刊行功能处理
5 ViewResolver的配置,从而将逻辑视图名解析为具体的视图技术
1.7 SpringMVC的配置
1.7.1 SpringMVC的环境搭建(带SSM框架整合)
第一步:添加相关依赖(pom.xml)
添加spring-webmvc依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
添加JSTL依赖(为做页面版的增删改查使用):
<!-- 缺少下面的这两个jar包会报java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/core/Config-->
<!-- 原因:org.springframework.web.servlet.view.JstlView在视图解析时需要这二个jar包-->
<!--版本号:-->
<jstl.version>1.2</jstl.version>
<standard.version>1.1.2</standard.version>
<tomcat-jsp-api.version>8.0.47</tomcat-jsp-api.version>
<!--依赖包:-->
<!-- 5.3、jstl、standard -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>${standard.version}</version>
</dependency>
<!-- 5.4、tomcat-jsp-api -->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jsp-api</artifactId>
<version>${tomcat-jsp-api.version}</version>
</dependency>
第二步:在WEB-INF下添加springmvc-servlet.xml(spring-mvc.xml)
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" 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/context/spring-context-4.3.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 通过context:component-scan元素扫描指定包下的控制器-->
<!--1) 扫描com.javaxl.zf及子子孙孙包下的控制器(扫描范围过大,耗时)-->
<aop:aspectj-autoproxy/>
<context:component-scan base-package="com.xiaoqing.ssm"/>
<!--2) 此标签默认注册DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter -->
<!--两个bean,这两个bean是spring MVC为@Controllers分发请求所必须的。并提供了数据绑定支持,-->
<!--@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,读写XML的支持(JAXB),读写JSON的支持(Jackson)-->
<!--开启注解驱动器-->
<mvc:annotation-driven></mvc:annotation-driven>
<!--3) ViewResolver -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- viewClass需要在pom中引入两个包:standard.jar and jstl.jar -->
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView"></property>
<property name="prefix" value="/WEB-INF/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!--4) 单独处理图片、样式、js等资源 -->
<!--<mvc:resources location="/css/" mapping="/css/**"/>-->
<!-- <mvc:resources location="/images/" mapping="/images/**"/>-->
<!--<mvc:resources location="/js/" mapping="/js/**"/>-->
<!--<mvc:resources location="/static/" mapping="/images/**"/>-->
</beans>
第三步:修改web.xml(配置中央控制器DispatcherServlet)
web.xml:
<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_3_1.xsd"
version="3.1">
<display-name>Archetype Created Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- 读取Spring上下文的监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring MVC servlet -->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!--此参数可以不配置,默认值为:/WEB-INF/springmvc-servlet.xml-->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/springmvc-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<!--web.xml 3.0的新特性,是否支持异步-->
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 3、添加过滤器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
1.7.2 测试springMVC环境搭建是否成功
第一步:建立HelloController.java类
HelloController.java:
注释打的比较清楚了
第二步:建立hello.jsp、hello2.jsp页面
hello.jsp:
hello2.jsp:
第三步:配置此项目的Tomcat发布项目
第四步:点击运行
第五步:看结果
如果访问http:8080/say1或http:8080/say2页面出现了hello.jsp或hello2.jsp中body的内容,说明我们的springMVC的环境搭建成功了
综上所述,现以/say1请求来用大白话回温一下springmvc框架的运作原理(整个流程,结合上述案例):
1、浏览器发送请求:http://localhost:8080/say1(dispatcherservlet)
request对象去处理这个url,可以获取到除去ip+port+项目这一个固定的串,拿到/say1
2、在dispatcherservlet去寻找HandlerMapping
HandlerMapping:在整个spring上下文中寻找了所有的被@requestMapping注解所标记的方法,如果@requestMapping这个注解里面的值有/say1,那么进行下一步
3、从前面已经能够获取到需要被调用的方法,那么dispatcherservlet就会寻找到handlerAdapt适配器来动态调用方法,然后会出一个结果
4、dispatcherservlet将结果封装成一个modelAndView对象,然后将其返回给viewReslover进行解析
5、viewReslover解析完毕之后,会将对应的视图展现给用户
2、Springmvc常用注解及返回值处理(通过案例讲解:书籍的增删改查)
2.1 目录(本次增删改查所常用)
2.2 准备工作(提前准备好工具类)
web.xml(添加过滤器包):
<!-- 3、添加过滤器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
PageTag.java(分页标签):
package com.xiaoqing.ssm.tag;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.BodyTagSupport;
import com.xiaoqing.ssm.utils.PageBean;
public class PageTag extends BodyTagSupport{
private static final long serialVersionUID = -258029245678348536L;
private PageBean pageBean;
public PageBean getPageBean() {
return pageBean;
}
public void setPageBean(PageBean pageBean) {
this.pageBean = pageBean;
}
@Override
public int doStartTag() throws JspException {
// TODO Auto-generated method stub
JspWriter out = pageContext.getOut();
try {
out.print(toHTML());
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return super.doStartTag();
}
private String toHTML() {
// TODO Auto-generated method stub
StringBuilder sb=new StringBuilder();
//上一次查询的form表单的HTML拼接
sb.append(" <form id='pageBeanForm' action='"+pageBean.getUrl()+"' method='post'>");
//查第几页的数据
sb.append(" <input type='hidden' name='page'>");
Map<String, String[]> parameterMap = pageBean.getParameterMap();
if(parameterMap.size()>0) {
Set<Entry<String,String[]>> entrySet = parameterMap.entrySet();
for (Entry<String, String[]> entry : entrySet) {
if(!"page".equals(entry.getKey())) {
for (String val : entry.getValue()) {
sb.append("<input type='hidden' value='"+val+"' name='"+entry.getKey()+"'>");
}
}
}
}
sb.append("</form> ");
//默认展示前面4页,当前页 ,后面5也
int page=pageBean.getPage();
int max=pageBean.getMaxPage();
int before=page>4?4:page-1;
int after=10-1-before;//5
after=max-page>after?after:max-page;
//用来控制上一页的点击按钮特效的
boolean startFlag=page>1;
//用来控制下一页的点击按钮特效的
boolean endFlag=page<max;
//拼接分页条
sb.append("<ul class='pagination'>");
sb.append("<li class='page-item "+(startFlag ? "" : "")+"'><a class='page-link' href='javascript:gotoPage(1)'>首页</a></li>");
sb.append("<li class='page-item "+(startFlag ? "" : "")+"'><a class='page-link' href='javascript:gotoPage("+pageBean.getPrevPage()+")'><</a></li>");
//代表了当前页的前4页
for (int i = before; i > 0 ; i--) {
sb.append("<li class='page-item'><a class='page-link' href='javascript:gotoPage("+(page-i)+")'>"+(page-i)+"</a></li>");
}
sb.append("<li class='page-item active'><a class='page-link' href='javascript:gotoPage("+pageBean.getPage()+")'>"+pageBean.getPage()+"</a></li>");
//代表了当前页的后5页
for (int i = 1; i <= after; i++) {
sb.append("<li class='page-item'><a class='page-link' href='javascript:gotoPage("+(page+i)+")'>"+(page+i)+"</a></li>");
}
sb.append("<li class='page-item "+(endFlag ? "" : "")+"'><a class='page-link' href='javascript:gotoPage("+pageBean.getNextPage()+")'>></a></li>");
sb.append("<li class='page-item "+(endFlag ? "" : "")+"'><a class='page-link' href='javascript:gotoPage("+pageBean.getMaxPage()+")'>尾页</a></li>");
sb.append("<li class='page-item go-input'><b>到第</b><input class='page-link' type='text' id='skipPage' name='' /><b>页</b></li>");
sb.append("<li class='page-item go'><a class='page-link' href='javascript:skipPage()'>确定</a></li>");
sb.append("<li class='page-item'><b>共"+pageBean.getTotal()+"条</b></li>");
sb.append("</ul>");
//拼接分页的js代码
sb.append("<script type='text/javascript'>");
sb.append("function gotoPage(page) {");
sb.append("document.getElementById('pageBeanForm').page.value = page;");
sb.append("document.getElementById('pageBeanForm').submit();");
sb.append("}");
sb.append("function skipPage() {");
sb.append("var page = document.getElementById('skipPage').value;");
sb.append("if (!page || isNaN(page) || parseInt(page) < 1 || parseInt(page) > '+max+') {");
sb.append("alert('请输入1~N的数字');");
sb.append("return;");
sb.append("}");
sb.append("gotoPage(page);");
sb.append("}");
sb.append("</script>");
return sb.toString();
}
}
PageBean.java(分页工具类):
package com.xiaoqing.ssm.utils;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
* 分页工具类
*
*/
public class PageBean {
private int page = 1;// 当前页码
private int rows = 5;// 页大小
private int total = 0;//总记录数
//上一次查询的url
private String url;
//上一次查询所携带的查询条件
private Map<String, String[]> parameterMap=new HashMap<String, String[]>();
//对pagebean进行初始化
public void setRequest(HttpServletRequest req) {
//初始化jsp页面传递过来的当前页
this.setPage(req.getParameter("page"));
//初始化jsp页面传递过来的页大小
this.setRows(req.getParameter("rows"));
//初始化jsp页面 传递过来是否分页
this.setPagination(req.getParameter("pagination"));
//保留上一次的查询请求
this.setUrl(req.getRequestURL().toString());
//保留上一次的查询条件
this.setParameterMap(req.getParameterMap());
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Map<String, String[]> getParameterMap() {
return parameterMap;
}
public void setParameterMap(Map<String, String[]> parameterMap) {
this.parameterMap = parameterMap;
}
private void setPage(String page) {
if(StringUtils.isNotBlank(page)) {
this.setPage(Integer.valueOf(page));
}
}
private void setRows(String rows) {
if(StringUtils.isNotBlank(rows)) {
this.setRows(Integer.valueOf(rows));
}
}
private void setPagination(String pagination) {
//只有填了false字符串,才代表不分页
this.setPagination(!"false".equals(pagination));;
}
private boolean pagination = true;// 是否分页
public PageBean() {
super();
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getRows() {
return rows;
}
public void setRows(int rows) {
this.rows = rows;
}
public int getTotal() {
return total;
}
public void setTotal(int total) {
this.total = total;
}
public void setTotal(String total) {
this.total = Integer.parseInt(total);
}
public boolean isPagination() {
return pagination;
}
public void setPagination(boolean pagination) {
this.pagination = pagination;
}
/**
* 获得起始记录的下标
*
* @return
*/
public int getStartIndex() {
return (this.page - 1) * this.rows;
}
@Override
public String toString() {
return "PageBean [page=" + page + ", rows=" + rows + ", total=" + total + ", pagination=" + pagination + "]";
}
//上一页
public int getPrevPage() {
return this.page>1?this.page-1:this.page;
}
//下一页
public int getNextPage() {
return this.page<this.getMaxPage()?this.page+1:this.page;
}
//最大页
public int getMaxPage() {
return this.total%this.rows==0?this.total/this.rows:(this.total/this.rows)+1;
}
}
StringUtils.java(判断字符是否为空):
package com.xiaoqing.ssm.utils;
public class StringUtils {
// 私有的构造方法,保护此类不能在外部实例化
private StringUtils() {
}
/**
* 如果字符串等于null或去空格后等于"",则返回true,否则返回false
*
* @param s
* @return
*/
public static boolean isBlank(String s) {
boolean b = false;
if (null == s || s.trim().equals("")) {
b = true;
}
return b;
}
/**
* 如果字符串不等于null或去空格后不等于"",则返回true,否则返回false
*
* @param s
* @return
*/
public static boolean isNotBlank(String s) {
return !isBlank(s);
}
}
z.tld(标签助手类):
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">
<description>JSTL 1.1 core library</description>
<display-name>JSTL core</display-name>
<tlib-version>1.1</tlib-version>
<short-name>z</short-name>
<uri>/xiaoqing</uri>
<tag>
<name>page</name>
<tag-class>com.xiaoqing.ssm.tag.PageTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>pageBean</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>
2.3 增删改查的业务逻辑代码
BookService(接口类):
package com.xiaoqing.ssm.service;
import com.xiaoqing.ssm.model.Book;
import com.xiaoqing.ssm.utils.PageBean;
import java.util.List;
import java.util.Map;
/**
* @author 晴sister
* @site https://blog.csdn.net/men_ma
* @company
* @create 2020-10-1111:01
*/
public interface BookService {
int deleteByPrimaryKey(Integer bid);
int insert(Book record);
int insertSelective(Book record);
Book selectByPrimaryKey(Integer bid);
int updateByPrimaryKeySelective(Book record);
int updateByPrimaryKey(Book record);
List<Map> listPager(Map map, PageBean pageBean);
List<Map> listPager(Book book, PageBean pageBean);
}
BookServiceImpl(接口实现类):
package com.xiaoqing.ssm.service.impl;
import com.xiaoqing.ssm.mapper.BookMapper;
import com.xiaoqing.ssm.model.Book;
import com.xiaoqing.ssm.service.BookService;
import com.xiaoqing.ssm.utils.PageBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author 晴sister
* @site https://blog.csdn.net/men_ma
* @company
* @create 2020-10-1111:18
*/
/*@Service:通常作用在业务层*/
@Service
public class BookServiceImpl implements BookService {
/*@Repository:将DAO类声明为Bean*/
@Autowired
private BookMapper bookMapper;
@Override
public int deleteByPrimaryKey(Integer bid) {
return bookMapper.deleteByPrimaryKey(bid);
}
@Override
public int insert(Book record) {
return bookMapper.insert(record);
}
@Override
public int insertSelective(Book record) {
return bookMapper.insertSelective(record);
}
@Override
public Book selectByPrimaryKey(Integer bid) {
return bookMapper.selectByPrimaryKey(bid);
}
@Override
public int updateByPrimaryKeySelective(Book record) {
return bookMapper.updateByPrimaryKeySelective(record);
}
@Override
public int updateByPrimaryKey(Book record) {
return bookMapper.updateByPrimaryKey(record);
}
@Override
public List<Map> listPager(Map map, PageBean pageBean) {
return bookMapper.listPager(map);
}
@Override
public List<Map> listPager(Book book, PageBean pageBean) {
Map map=new HashMap();
map.put("bname",book.getBname());
return bookMapper.listPager(map);
}
}
BookController.java:
package com.xiaoqing.ssm.controller;
import com.xiaoqing.ssm.model.Book;
import com.xiaoqing.ssm.service.BookService;
import com.xiaoqing.ssm.utils.PageBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
/**
* @author 晴sister
* @site https://blog.csdn.net/men_ma
* @company
* @create 2020-10-141:49
*/
@Controller
@RequestMapping("/book")
public class BookController {
@Autowired
private BookService bookService;
@RequestMapping("/list")
public String list(Book book, HttpServletRequest req){
PageBean pageBean=new PageBean();
pageBean.setRequest(req);
List<Map> list = bookService.listPager(book, pageBean);
req.setAttribute("bookList",list);
req.setAttribute("pageBean",pageBean);
return "bookList";
}
@RequestMapping("/preSave")
public String preSave(Book book, HttpServletRequest req){
if(book==null||book.getBid()==null||book.getBid()==0){
return "bookEdit";
}
Map map = bookService.listPager(book,null).get(0);
req.setAttribute("b",map);
return "bookEdit";
}
@RequestMapping("/add")
public String add(Book book){
bookService.insertSelective(book);
return "redirect:/book/list";
}
@RequestMapping("/edit")
public String edit(Book book){
bookService.updateByPrimaryKeySelective(book);
return "redirect:/book/list";
}
@RequestMapping("/del/{bid}")
public String del(@PathVariable("bid")Integer bid){
/**
语法:
* @PathVariable是spring3.0的一个新功能:接收请求路径中占位符的值
*
* @PathVariable("xxx")
* 通过 @PathVariable 可以将URL中占位符参数{xxx}绑定到处理器类的方法形参中@PathVariable(“xxx“)
*
* @RequestMapping(”/del/{bid}”)
* 请求路径:http://localhost:8080/book/del/1
*/
bookService.deleteByPrimaryKey(bid);
return "redirect:/book/list";
}
}
bookList.jsp(页面展示):
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@taglib uri="/xiaoqing" prefix="z" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>书籍展示</title>
<style type="text/css">
.page-item input {
padding: 0;
width: 40px;
height: 100%;
text-align: center;
margin: 0 6px;
}
.page-item input,
.page-item b {
line-height: 38px;
float: left;
font-weight: 400;
}
.page-item.go-input {
margin: 0 10px;
}
</style>
</head>
<body>
<form class="form-inline" action="${pageContext.request.contextPath }/book/list" method="post">
书名:
<div class="form-group mb-2">
<input type="text" name="bname" class="form-control-plaintext" id="staticEmail2" placeholder="请输入书籍名称">
</div>
<button type="submit" class="btn btn-primary mb-2">查询</button>
<!--
href="/bookAdd.jsp" 相对路径 ,相对的是Tomcat工程的根目录
href="bookAdd.jsp" 相当于请求
${pageContext.request.contextPath }/bookAdd.jsp 带上项目名的绝对路径
href="${pageContext.request.contextPath }/book.action?methodName=toAdd"通过后台转发到前台的jsp页面
-->
<a href="${pageContext.request.contextPath }/book/preSave" class="btn btn-primary mb-2 ml-4">新增</a>
</form>
<table class="table table-striped">
<thead>
<tr>
<th scope="col">书籍ID</th>
<th scope="col">书籍名</th>
<th scope="col">价格</th>
<th scope="col">操作</th>
</tr>
</thead>
<tbody>
<c:forEach var="b" items="${bookList }">
<tr>
<td>${b.bid }</td>
<td>${b.bname }</td>
<td>${b.price }</td>
<td>
<a href="${pageContext.request.contextPath }/book/del/${b.bid}" class="btn btn-sm btn-danger btn-primary mb-2 ml-4">删除</a>
<a href="${pageContext.request.contextPath }/book/preSave?bid=${b.bid}" class="btn btn-sm btn-success btn-primary mb-2 ml-4">修改</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
<z:page pageBean="${pageBean }"></z:page>
</body>
</html>
bookEdit.jsp(页面修改及增加):
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>书籍修改页面</title>
</head>
<body>
<form action="${pageContext.request.contextPath }${b.bname==null?'/book/add':'/book/edit'}" method="post">
<div class="form-group row">
<label for="bid" class="col-sm-2 col-form-label">书籍ID</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="bid" name="bid" value="${b.bid }">
</div>
</div>
<div class="form-group row">
<label for="bname" class="col-sm-2 col-form-label">书籍名称</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="bname" name="bname" value="${b.bname }">
</div>
</div>
<div class="form-group row">
<label for="price" class="col-sm-2 col-form-label">书籍价格</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="price" name="price" value="${b.price}">
</div>
</div>
<div class="form-group row">
<div class="col-sm-12">
<input type="submit" class="form-control bg-success" value="提交">
</div>
</div>
</form>
</body>
</html>
注意点:由于目前博主没有开启Redis数据库,所以我们的先注释Redis缓存及数据库,如下所示:
2.4 测试结果
查询(展示页面):
模糊查询效果:
增加效果:
修改效果:
删除效果:
3、Springmvc静态资源处理
3.1 语法
- springmvc中五种返回值处理情况
- 转发3种:
- 1、转发到安全目录web-inf下
- 2、转发到根目录
- 3、转发到requestMapping
- 重定向2种:
- 1、重定向到根目录
- 2、重定向到requestMapping
3.2 测试以上的返回值情况
HelloController.java:
package com.xiaoqing.ssm.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/**
* @author 晴sister
* @site https://blog.csdn.net/men_ma
* @company
* @create 2020-10-141:11
*/
/**
* springmvc中五种返回值处理情况
* 转发3种:
* 1、转发到安全目录web-inf下
* 2、转发到根目录
* 3、转发到requestMapping
*
* 重定向2种:
* 1、重定向到根目录
* 2、重定向到requestMapping
*/
/**
* @Controller注解相当于<bean id="helloController" class="hellController的全路径名"></bean>
*/
@Controller
public class HelloController {
/*
equestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。
用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
*/
/**
* 返回ModelAndView的逻辑视图名(方法一)
* @return
*/
@RequestMapping("/say1")
public String say1(){
// hello代表返回的页面
return "hello";
}
/**
* 返回ModelAndView的逻辑视图名(方法二)
* say2方法是严格按照springmvc的流程来编写代码的,say1是简化的
* @return
*/
@RequestMapping("/say2")
public ModelAndView say2(){
ModelAndView mv=new ModelAndView();
mv.setViewName("/hello2");
mv.addObject("msg","换种方式跟你玩!!!");
return mv;
}
//1、转发到安全目录web-inf下
@RequestMapping("/req1")
public String req1(){
System.out.println("转发到安全目录web-inf下....");
return "a";
}
//2、转发到根目录
@RequestMapping("/req2")
public String req2(){
System.out.println("转发到根目录....");
return "forward:/b.jsp";
}
//3、转发到requestMapping
@RequestMapping("/req3")
public String req3(){
System.out.println("转发到requestMapping....");
return "forward:/req2";
}
// 1、重定向到根目录
@RequestMapping("/red1")
public String red1(){
System.out.println("red1....");
return "redirect:/b.jsp";
}
// 1、重定向到requestMapping
@RequestMapping("/red2")
public String red2(){
System.out.println("red2....");
return "redirect:/req2";
}
}
3.3 、测试效果
req1:(为减少篇幅长度就不一一截图了)