2020年4月补:
①:看着1月份自己写的代码有点看不下去了,而且之前提交数据没有用到ajax,前端没有用到框架,看着有点想吐。因为看这篇文章的伙伴大部分是新手吧(目前有个小伙伴收藏了这篇文章),出于好意,我还是要改改控制器和前端的代码,不要“误人子弟”(之前的代码没错,但不希望有人跟着之前我写的代码写),修改的内容在页面最后,有兴趣可以对比一下代码。
②:这里的spring-web.xml文件的事务配置是比较粗略的,你有兴趣还是要学一下,因为事务和AOP是很重要的。
③:前端提交数据用到了js、JQuery和前端框架layui。
1.打开IDEA,创建Maven项目。
打开IDEA,选择新建项目,这里选择maven选项,不选择模板,直接点击Next。
填写GroupId,和ArtifactId,后点Next,然后点击Finish。
这里啰嗦一下,GroupId指的是公司名称,ArtifactId指的是项目的名称。
创建完成后,删除src文件夹。
右键点击项目名称myhomes,新建一个用于存放业务层biz资料的module。
新建module界面中依旧不选择模板,直接点击Next。
填写module名称,并点击Next后保存。
继续在myhomes新建一个module,这个module用于存放DAO数据库操作类等相关文件。操作步骤跟上一个大致相同,唯一不同的地方是module的名不一样,我这里module名是myhomes_dao。
新建最后一个module,该module用于存放Web层数据的。这里要用到web模板。
之后填写该module的名字保存即可,之后等待IDEA下载模板完成。这里的module名字是myhomes_web。
项目下载完成后,myhomes_web中的src下的main文件夹应该是没有java和resources文件夹的,因此我们需要创建。
创建好后文件夹后需要进行“Mark Directory as”操作,该操作指定文件夹是用来放什么资料的。
将java文件夹设置成Sources Root
将resources文件夹设置成Resources Root(这就不放图了)
然后在每个module中所需新建文件夹,我这里这里设置如下:
2.为各个module的pom.xml文件添加相关依赖
先为myhomes_dao的pom.xml文件添加相关依赖:
<dependencies>
<!--Mybatis-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.41</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--Spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.4.RELEASE</version>
</dependency>
<!--Spring整合Mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>
为myhomes_biz的pom.xml文件添加相关依赖:
<dependencies>
<!--myhome_biz是业务层,需要依赖持久层,也就是myhome_dao-->
<dependency>
<groupId>com.myhome</groupId>
<artifactId>myhome_dao</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
</dependencies>
为myhomes_web的pom.xml文件添加相关依赖:
pom文件有些位置内容我改动了,不知道跟你创建的那时候这些位置内容是否一样。
pox文件头部的project标签最后那个网址:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-4.0.0.xsd">
还有就是下面那个url标签内的网址:
<url>http://maven.apache.org</url>
目前我不知道不改会出现什么问题,这里就提一下。
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--导入业务层依赖-->
<dependency>
<groupId>com.myhome</groupId>
<artifactId>myhome_biz</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.4.RELEASE</version>
</dependency>
</dependencies>
3.添加xml配置文件
首先为dao层的resources资源文件夹添加xml配置文件spring-dao.xml:
<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"
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.xsd">
<!--开启自动扫描-->
<context:component-scan base-package="com.myhomes.dao"/>
<!--配置数据源-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/home?useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<!--配置SessionFactory-->
<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.myhomes.entity"/>
</bean>
<!--配置映射扫描器,让mybaits扫描映射文件包-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sessionFactory"/>
<property name="basePackage" value="com.myhomes.dao"/>
</bean>
</beans>
接着为biz层的resources资源文件夹添加xml配置文件spring-biz.xml:
<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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--声明式事务配置在业务层-->
<!--导入dao层配置文件-->
<import resource="spring-dao.xml"/>
<!--开启自动扫描-->
<context:component-scan base-package="com.myhomes.biz"/>
<!--aop自动代理-->
<aop:aspectj-autoproxy/>
<!--事务管理器-->
<bean id="transationManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--声明通知,定义规则-->
<tx:advice id="txAdvice" transaction-manager="transationManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/> <!--不用事务封装-->
<tx:method name="find*" read-only="true"/>
<tx:method name="search*" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--通知和切入点进行关联-->
<aop:config>
<aop:pointcut id="txpc" expression="execution(* com.myhomes.biz.*.*(..))"/> <!--第一个*号代表任意返回值-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txpc"/>
</aop:config>
</beans>
接着为web层的resources资源文件夹添加xml配置文件spring-web.xml:
<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
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!--导入biz层配置文件-->
<import resource="spring-biz.xml"/>
<!--开启自动扫描-->
<context:component-scan base-package="com.myhomes.controller"/>
<!--配置mvc自动驱动-->
<mvc:annotation-driven/>
<!--静态资源交给servlet处理-->
<mvc:default-servlet-handler/>
<!--视图转换器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".jsp"/>
</bean>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.myhomes.global.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>
紧接着在web层中的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_3_1.xsd"
version="3.1">
<!--处理中文乱码-->
<filter>
<filter-name>encoding</filter-name>
<filter-class>com.myhomes.global.EncodingFilter</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>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/assets/*</url-pattern>
<url-pattern>/js/*</url-pattern>
<url-pattern>/css/*</url-pattern>
<url-pattern>/img/*</url-pattern>
<url-pattern>/vendor/*</url-pattern>
<url-pattern>*.js</url-pattern>
<url-pattern>*.jpg</url-pattern>
<url-pattern>*.gif</url-pattern>
<url-pattern>*.png</url-pattern>
<url-pattern>*.css</url-pattern>
<url-pattern>*.ico</url-pattern>
</servlet-mapping>
<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:spring-web.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>
EncodingFilter类:
package com.myhomes.global;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class EncodingFilter implements Filter {
private String encoding = "utf-8";
public void init(FilterConfig filterConfig) throws ServletException {
if(filterConfig.getInitParameter("encoding")!=null){
encoding = filterConfig.getInitParameter("encoding");
}
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse)servletResponse;
request.setCharacterEncoding(encoding);
response.setCharacterEncoding(encoding);
filterChain.doFilter(request,response);
}
public void destroy() {
}
}
新建项目资源文件夹:
项目页面文件放在WEB-INF下的pages里面,这跟spring-web.xml文件里的视图解析器的前缀一致。
4.准备数据库文件
这里的数据库是用MySQL的,并且使用Navicat of MySQL对数据库进行管理。
数据库文件内容如下:
数据库名称:home
数据表:users 及其列名类型等,user_class是该表的外键,这个列指的是用户的类型!
(为什么要使用外键?直接将user_class列的内容直接设置成类型名不好吗(例如设置成“普通用户”)?针对这个问题,我想说的是:如果这张表有1万条普通用户数据,则这1万条数据的user_class列都设置成“普通用户”,有1万条“普通用户”的字符串。如果将user_class列设置成外键,把此列设置成数字,比如1代表普通用户。则1万条数据此列的内容为“1”,减少了数据的臃肿。添加一张用户类型表,表有两个列,id和name。id就设置成1,对应普通用户的user_class列的值1,name属性设置成“普通用户”即可。)
users表的内容:
数据表user_class:
user_class表的内容:
5.dao层内容
在entity包中新建实体类User,对应数据库users表的列,并且自动生成getter和setter(按Alt + Insert)。注意,有些属性名跟数据库对应的列的名字不一样,例如userClass属性对应的是user_class列。
在dao包中新建UserDao接口类型的类。
在类的前面添加注解@Repository,告诉Spring这个类是dao层(数据库操作)的类;
在类中添加相应的方法;
在dao层的resources的文件夹中新建一个目录,此目录的路径是:com\myhomes\dao,此路径与spring-dao.xml文件的映射扫描器的basePackage的路径一致。
创建名为UserDao的xml文件:
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.4//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.myhomes.dao.UserDao">
<resultMap id="resultMap" type="User">
<id property="id" column="id" javaType="Integer"></id>
<result property="acc" column="accound" javaType="String"></result>
<result property="password" column="password" javaType="String"></result>
<result property="name" column="name" javaType="String"></result>
<result property="userClass" column="user_class" javaType="Integer"></result>
<result property="houseId" column="house_id" javaType="String"></result>
<result property="ruzhuTime" column="ruzhu_time" javaType="java.util.Date"></result>
<result property="outTime" column="out_time" javaType="java.util.Date"></result>
<result property="ban" column="ban" javaType="String"></result>
<result property="isDelete" column="is_delete" javaType="String"></result>
</resultMap>
<select id="select" parameterType="String" resultMap="resultMap">
select * from users where accound = #{acc}
</select>
</mapper>
6.biz业务层内容
在biz包中新建一个接口类:GlobalBiz
并添加方法。
再impl包中添加其实现类:GlobalBizImpl
重写接口方法:
类前面添加@Service注解,提示Spring这个类是服务层的类;
导入的UserDao类的对象要添加@Autowired注解,自动注入;
7.web层内容
新建控制器类LoginController
类的前面添加Controller注解,提示Spring这是一个控制器类;
导入的业务层对象要进行自动注入;
toLogin()方法前添加@RequestMappiong注解,value值设置为to_login,指的是网站的url中的to_login路由。也就是说,url访问http://localhost:8080/to_login此路径的时候执行这个方法。方法的返回值login指的是访问项目静态资源文件login.jsp!
login()方法要进行登录操作,因此需要添加HttpSession类的对象,因为此方法要接收前端发送过来的账号密码数据,因此需要添加@RequestParam注解。acc和password形参跟前端的<input type="text" name="acc"/>的input标签的name属性的名字要一样;
login()方法接收数据后首先进行是否为空和长度大小等进行判断,如果有问题,则利用session添加参数的方法进行添加“键”和“值”(这里的键是warn,值是提示信息),并return 重定向(redirect:)回to_login路由,to_login路由返回到登录界面;
login()方法接收数据,进行判断无误后利用业务层方法进行登录操作,如果查询到存在此用户,则session添加参数,并把user对象添加到session,并重定向到self方法,让self方法访问登录后的self页面。
8.准备前端页面
在WEB-INF中的pages文件夹里添加login.jsp和self.jsp
login.jsp:
①:因为要用到jsp的标签 c,所以①添加
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
②:c标签,此标签是用来接收session的warn参数的信息的
③:提交到LoginController的@RequestMapping value为“login”的路由方法
注意,这里的css的引入路径,参照我的项目静态资源目录。还有就是input标签的name属性值。
self.jsp:
登录成功后,在页面中取出登录成功后用户的名称。
9.配置tomcat
点击IDEA右上角的下拉框的Edit.....,我这里配置过了的。
按顺序操作添加:
②:修改项目路径为to_login,直接访问Controller对应的方法路由。
③:也可以修改每次修改项目文件的时候服务器做什么
点击 + 号,然后选择有exploded后缀的选项,接着修改④为 /,然后点击“Apply”。
10.验证登录
开启tomcat服务器。
查看url地址:
直接点击登录按钮:
输入长度不足为5的账号密码:
输入错误的账号密码:
输入正确的账号密码:super,123456
注意url的路由名称,已经登录成功,页面显示用户的名称了。
最后
这篇文章写作的周期有几天,中途还因为SpringMVC拦截静态资源的问题,项目从头到尾弄多了一次,应该没有漏掉的地方,希望我在总结的时候能帮到您,下篇的文章讲如何防止用户未进行登录操作,在url直接输入某路由访问系统并系统操作数据,主要依赖拦截器技术。
4月更新
控制器层:
package com.myhomes.controller;
import com.myhomes.biz.GlobalBiz;
import com.myhomes.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
@Controller("loginController")
public class LoginController {
@Autowired
private GlobalBiz globalBiz;
@RequestMapping(value = "/to_login")
public String toLogin(){
return "login";
}
@RequestMapping(value = "/login")
@ResponseBody
public Map<String,String> login(HttpSession session,@RequestBody Map<String,String> map){
Map<String,String> map2 = new HashMap<>();
String acc = map.get("acc");
String password = map.get("password");
User user = globalBiz.login(acc,password);
if (user == null){
map2.put("message","false");
map2.put("error","用户名或密码输入错误!");
return map2;
}else{
session.setAttribute("userId",user.getId());
map2.put("message","success");
map2.put("uid",String.valueOf(user.getId()));
map2.put("uName",user.getName());
return map2;
}
}
@RequestMapping(value = "/self")
public ModelAndView self(@RequestParam String uid,@RequestParam String uName){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("uid",uid);
modelAndView.addObject("uName",uName);
modelAndView.setViewName("self");
return modelAndView;
}
}
前端页面及提交代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>××管理系统</title>
<link rel="stylesheet" type="text/css" href="css/index.css"/>
<link rel="stylesheet" href="layui/css/layui.css">
<script src="layui/layui.js"></script>
</head>
<body>
<div id="main">
<%--<c:if test="${not empty warn}">--%>
<%--<h2 color="red" align="center"><c:out value="${warn}" /></h2>--%>
<%--</c:if>--%>
<form class="layui-form" name="login" method="post" style="position: fixed;background-color: #FFFFFF;left: 40%;top: 30%;width: 340px;height: 220px;border-radius: 16px;box-shadow: 0 0 3px #303030;opacity: 0.8;">
<div class="layui-form-item" style="padding-top: 30px;">
<label class="layui-form-label" style="font-size: 18px;">账号:</label>
<div class="layui-input-block">
<input class="layui-input" style="width: 200px;" required lay-verify="account" type="text" name="acc" placeholder="请输入账号" maxlength="11" onkeyup="this.value=this.value.replace(/[^\w\.\/]/ig,'')"/>
</div>
</div>
<div class="layui-form-item" style="padding-top: 10px;">
<label class="layui-form-label" style="font-size: 18px;">密码:</label>
<div class="layui-input-block">
<input class="layui-input" style="width: 200px;" required lay-verify="password" type="password" name="password" placeholder="请输入密码" maxlength="20" onkeyup="this.value=this.value.replace(/[^\w\.\/]/ig,'')"/>
</div>
</div>
<div class="layui-form-item" style="padding-top: 10px;">
<input type="button" class="layui-btn layui-btn-normal" style="display:block;margin:0 auto;" value="登录" id="login_button">
</div>
</form>
</div>
</body>
<script src="js/jquery-1.8.3.min.js" type="text/javascript" ></script>
<script>
$(document).ready(function () {
layui.use('layer', function(){
var layer = layui.layer;
$("#login_button").click(function () {
var acc = $("input[name=acc]").val();
var pass = $("input[name=password]").val();
if (acc.length < 5){
layer.alert('账号长度不足',{
title:"提示"
});
return false;
}if (pass.length < 5){
layer.alert('密码长度不足',{
title:"提示"
});
return false;
}
$.ajax({
type:"post",
url:"/login",
contentType:"application/json;charset=UTF-8",
dataType:"json",
data:JSON.stringify({
acc:acc,
password:pass
}),
success:function (data) {
if (data.message === "false") {
layer.alert(data.error,{
title:"错误"
});
}
if (data.message === "success") {
var uid = data.uid;
var uName = data.uName;
window.location.href="/self?uid="+uid+"&uName="+uName;
}
}
});
});
});
});
</script>
</html>
启动成功后
直接点击【登录】按钮,提示:
密码长度不足,提示:
故意输入不存在的账号及密码:
右侧XHR栏是有数据的,状态200意味着成功将数据提交到服务器了,提交的数据能看到,服务器返回的数据也能看到。
进行成功登录操作:
成功了。
结尾
不出意外,这是最后的更新了。