SpringMVC-3-CRUD
Select:
/**
* @author : zhukang
* @date : 2021-06-26
* @return :
* @description : 查询电子文档列表
*/
@RequestMapping(value = "/entries", method = RequestMethod.GET)
public String selectAllEntry(Map<String, Object> map){
// 获取文档列表,存入map中
map.put("edocEntries", edocEntryMapper.selectAllEntry());
// 返回目标视图
return "edocList";
}
mvc模式的servlet风格,使用注解的方法代替了一切。
注解中的value值表示了拦截的请求, / 可加可不加,最好加(因为专业)
返回的字符串是需要跳转的jsp页面的名字
形参中既可以接收数值,也可以是要扔出去的数值(model、map)
正删改一体的RSET风格拦截:
-
前往修改页面、增加页面都使用GET请求;
-
增删改都使用统一的拦截url,也可以携带参数,互不影响。但是需要改变请求的类型来区别:
1.增加 == POST
2.修改 == PUT
3.删除 == DELETE
接收页面的参数时,需要@PathVariable注解,实体参数可以不需要;
返回目标页面时,多级目录问题需要注意,尽量使用**return "redirect:/entries";**的形式
去往添加电子文档:
/**
* @author : Lcywings
* @date : 2021/6/26 10:10
* @acl : true
* @description : 去往添加电子文档
*/
@RequestMapping(value = "/toAddEntry", method = RequestMethod.GET)
public String toAddEntry(Map<String, Object> map) {
// 获取分类列表,存入map中
map.put("edocCategories", edocCategoryMapper.selectAllCategory());
// 默认情况下,form表单标签,必须添加一个command作为key的模型数据
// 添加,没有初始数据,直接提供一个空的电子文档实体即可,页面取的值都是空的
// map.put("command", new EdocEntry());
// 可以自定义修改表单默认的command参数
map.put("edocEntry", new EdocEntry());
// 返回目标视图
return "edocInfo";
}
添加电子文档:
/**
* @author : Lcywings
* @date : 2021/6/26 10:10
* @acl : true
* @description : 添加电子文档
*/
@RequestMapping(value = "/updateEntry", method = RequestMethod.POST)
public String addEntry(EdocEntry edocEntry) {
//填充分类数据和时间
edocEntry.setEdocCategory(edocCategoryMapper.selectCategoryById(edocEntry.getEdocCategory().getId()));
edocEntry.setCreateDate(new Date());
//根据id调用修改接口
edocEntryMapper.insertEntryById(edocEntry);
// 返回目标视图
return "redirect:/entries";
}
去往修改电子文档页:
/**
* @author : Lcywings
* @date : 2021/6/26 10:10
* @acl : true
* @description : 去往修改电子文档页
*/
@RequestMapping(value = "/toModEntry/{id}", method = RequestMethod.GET)
public String toModEntry(@PathVariable("id") Integer id, Map<String, Object> map) {
// 获取分类列表,存入map中
map.put("edocCategories", edocCategoryMapper.selectAllCategory());
// 查询一个文档实体详情,存入模型数据
// map.put("command", edocEntryMapper.selectEntryById(id));
map.put("edocEntry", edocEntryMapper.selectEntryById(id));
// 返回目标视图
return "edocInfo";
}
修改电子文档:
/**
* @author : Lcywings
* @date : 2021/6/26 10:10
* @acl : true
* @description : 修改电子文档
*/
@RequestMapping(value = "/updateEntry", method = RequestMethod.PUT)
public String modEntry(EdocEntry edocEntry) {
//填充分类数据和时间
edocEntry.setEdocCategory(edocCategoryMapper.selectCategoryById(edocEntry.getEdocCategory().getId()));
edocEntry.setCreateDate(new Date());
//根据id调用修改接口
edocEntryMapper.updateEntryById(edocEntry.getId(), edocEntry);
// 返回目标视图
return "redirect:/entries";
}
删除电子文档:
/**
* @author : Lcywings
* @date : 2021/6/26 10:10
* @acl : true
* @description : 删除电子文档
*/
@RequestMapping(value = "/updateEntry/{id}", method = RequestMethod.DELETE)
public String deleteEntry(@PathVariable("id") Integer id, Map<String, Object> map) {
// 获取文档id,删除电子文档
edocEntryMapper.deleteEntryById(id);
// 返回目标视图,rest请求存在多级,保证从项目根目录开始请求,不能少 /
return "redirect:/entries";
}
拦截这里大大减少的代码量,但是需要一些配置:
- 组件扫描
- 视图解析器
- 前端核心控制器(DispatcherServlet拦截器)
- Rest风格请求转换过滤器
前两项是在spring-config.xml中配置,后两项是在web.xml中配置
还有一个需要注意的配置点:
-
静态资源释放
这玩意不配,js之流的静态资源就会被前端核心控制器拦截并解析,但是配了组件扫描会失效,所以和mvc:annotation-driven一起使用
-
注解扫描
<!-- 组件扫描 -->
<context:component-scan base-package="com.kgc.springmvc"/>
<!-- 视图解析器-jsp视图解析
工作原理:当前请求处理方法,返回目标视图名称时,根据视图解析器解析为目标物理视图
prefix + 返回的视图(jsp页面)名称 + suffix -》真实物理视图
猜测:/WEB-INF目录是安全目录,不可以直接通过浏览器访问,springmvc底层使用的是内部转发
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀必须是/结尾,否则容易出错 -->
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 配置SpringMvc的前端核心控制器 -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置前端核心控制器的初始化参数contextConfigLocation,指定springmvc框架使用的核心配置文件 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<!-- web容器启动就创建实例 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<!-- 如果配置/*或者*.do,对rest风格支持不友好,暂时记住就是 / (好处就是可以自动放行jsp请求) -->
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- Rest风格请求转换过滤器 -->
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- springmvc默认是不会释放静态资源(js,css,image,html...),即被前端核心控制器拦截(找映射处理方法)
针对静态资源要进行释放,增加一个配置<mvc:default-servlet-handler/>即可
注意:静态资源释放会导致@RequestMapping注解失效,必须配置注解扫描使用
-->
<mvc:default-servlet-handler/>
<mvc:annotation-driven/>
前端接收:
因为后端使用框架传参的本事还是塞在request中,所以前端使用el表达式既可以顺利的取到值,但是spring还是给我们准备了很好用的spring表单来发送数据,强就强在发送的同时兼顾接收数据,直接帮你写好name等参数,方便进出数据
<!-- springmvc的form表单标签:方便实现表单开发,数据快速回显 -->
<!-- form表单标签必须写在 form:form中才可以 -->
<form:form action="/edocInfo" method="post" modelAttribute="edocEntry">
<!-- 判断是添加还是修改 -->
<c:if test="${!empty edocEntry.id}" var="flag">
<form:hidden path="id"/>
<input type="hidden" name="_method" value="put"/>
</c:if>
<table border="1px" width="50%" align="center" cellspacing="0">
<tr>
<td>文档分类:</td>
<td>
<!-- items指定遍历的集合,itemLabel对应展示的文字,itemValue对应提交的值,相当于以前的<option value="itemValue">itemLabel</option> -->
<form:select path="edocCategory.id" items="${edocCategories}" itemLabel="name" itemValue="id"/>
</td>
</tr>
<tr>
<td>书名:</td>
<td>
<form:input path="title"/>
</td>
</tr>
<tr>
<td>作者:</td>
<td><form:input path="uploadUser"/></td>
</tr>
<tr>
<td>摘要:</td>
<td><form:input path="summary"/></td>
</tr>
<tr>
<td colspan="2" align="center">
<c:if test="${flag}">
<input type="submit" value="修改"/>
</c:if>
<c:if test="${!flag}">
<input type="submit" value="添加"/>
</c:if>
<input type="button" value="返回"/>
</td>
</tr>
</table>
</form:form>
实际上就是帮你写好了id和name,方便进出数据:
<form:input path="title"/> ==>>
不需要遍历的select标签,拿到直接填满,类似于增强for:
<form:select path="edocCategory.id" items="${edocCategories}" itemLabel="name" itemValue="id"/>
↑转换为↓
<select id="edocCategory.id" name="edocCategory.id">
<option value="1">文学</option><option value="2">武侠</option>
<option value="3" selected="selected">仙侠</option>
<option value="4">玄幻</option><option value="5">都市</option>
<option value="6">言情</option>
</select>
js的标准用法:
返回的写法:
关键点:$ 这是项目的绝对路径
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.4.1.min.js"></script>
<script>
$(function () {
$("input[type=button]").click(function () {
history.back();
})
})
</script>
a标签如何发post请求:
就很离谱,本质的上是去修改表单中内容并在js中提交
<form action="#" method="post">
<input type="hidden" name="_method" value="delete"/>
</form>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-3.4.1.min.js"></script>
<script>
$(function () {
// 调试jQuery是否正常
// alert(123);
// 绑定删除操作
$(".del").click(function () {
// 提示
if (!confirm("确定要删除吗?")) {
// 去除超链接的默认跳转事件
return false;
}
// 提交form表单
$("form").attr("action", $(this).attr("href")).submit();
// 取消表单的默认提交事件
return false;
})
})
</script>
Q.E.D.