标签:clist lang 发布者 target http icon 运行时 代码冗余 lock
C/S Client Server面向于客户端,用户通过客户端跟程序进行交互(需要维护客户端,成本较高)
B/S Browser Server面向于浏览器,用户通过浏览器进行程序交互
http :// localhost:8080 / news/index.html
URL组成:
http:协议,除此之外还有(FTP,HTTPS,RMI,DUBBO)
localhost:代表主机IP地址
8080:代表端口号
news/index.html:资源地址
WebLogic
Ngnix
Resin
目录介绍:
/bin 存放各种平台下用于启动和停止Tomcat的脚本文件
/conf 存放Tomcat服务器的各种配置文件
/lib 存放Tomcat服务器所需的各种JAR文件
/logs 存放Tomcat的日志文件
/temp Tomcat运行时用于存放临时文件
/webapps 当发布Web应用时,默认情况下会将Web应用的文件存放于此目录中
/work Tomcat把由JSP生成的Servlet放于此目录下
启动方式:
/bin目录下:startup.bat启动脚本 shutdown.bat停止脚本
如果遇到闪退的问题则在上述两个文件中添加如下代码:
SET JAVA_HOME=D:\Java\jdk1.7 (java jdk目录)
SET TOMCAT_HOME=E:\tomcat-7.0 (解压后的tomcat文件目录)
配置环境变量:
添加系统变量,名称为CATALINA_HOME,值为Tomcat的安装目录,在Path系统变量中添加一个%CATALINA_HOME%\bin
Eclipse环境中新建一个Dynamic web project--->Target Runntime代表启动的web服务器----->Dynamic Web model version代表项目版本(3.0)--->点击Next直到
---->Generate web.xml xxxxx将此勾选上才在WEB-INFO文件夹下有web.xml文件
web.xml文件是web工程的配置文件,其中welcome-file-list代表首次访问的页面集合,welcome-file代表首次访问的页面
目录结构:
/ Web应用的根目录,该目录下所有文件在客户端都可以访问(JSP、HTML等)
/WEB-INF 存放应用使用的各种资源,该目录及其子目录对客户端都是不可以访问
/WEB-INF/classes 存放Web项目的所有的class文件
/WEB-INF/lib 存放Web应用使用的JAR文件
组成内容:
page指令:<%@ page 属性1="属性值" 属性2="属性值1,属性值2"… 属性n="属性值n"%>
属性 描述 默认值
language 指定JSP页面使用的脚本语言 java
import 通过该属性来引用脚本语言中使用到的类文件 无
contentType 用来指定JSP页面所采用的编码方式 text/html, ISO-8859-1
小脚本:<%Java代码%>
表达式:<%=表达式%>
声明:<%!声明方法%>
注释:<!--注释-->;<%--注释,页面无法看见-->
request 请求对象:可以获取用户提交请求的数据 可以对数据进行保存 转发
response 响应对象:可以向页面中响应数据 重定向
out 输出对象
application 全局上下文对象
session 会话对象
page 当前页面对象
pageContext
config 配置对象
exception 异常对象
案例:注册页面
<!-- form表单提交方式
post:安全并且没有数据长度限制
get:不安全,只能提交较小的数据
-->
<form action="request/checkdata.jsp" method="get">
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
性别:<input type="radio" name="sex" value="man" checked="checked"/>男<input type="radio" name="sex" value="woman"/>女<br/>
爱好:<input type="checkbox" name="hobby" value="打篮球"/>打篮球
<input type="checkbox" name="hobby" value="踢足球"/>踢足球
<input type="checkbox" name="hobby" value="打豆豆"/>打豆豆<br/>
地址:<select name="city">
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="guangzhou">广州</option>
</select><br/>
<input type="submit" value="提交"/> <input type="reset" value="重置"/>
</form>
处理数据页面
<%
//解決POST請求亂碼
request.setCharacterEncoding("UTF-8");
//用户在页面点击提交就是发送了一条请求,那么我们在获取数据时用的是request请求对象
String username=request.getParameter("username");
//解決GET請求亂碼
//username=new String(username.getBytes("ISO-8859-1"),"utf-8");
String password=request.getParameter("password");
String sex=request.getParameter("sex");
//获取用户提交的相同name属性值
String [] hobbys=request.getParameterValues("hobby");
String city=request.getParameter("city");
System.out.println("姓名:"+username+"\t密碼:"+password+"\t性別:"+sex+"\t愛好:"+hobbys[0]+"\t地址:"+city);
%>
POST处理乱码:request.setCharacterEncoding("UTF-8");
GET处理乱码方案一:
String username=request.getParameter("username");
//解決GET請求亂碼
//username=new String(username.getBytes("ISO-8859-1"),"utf-8");
GET处理乱码方案二:
在Tomcat的Server.xml文件中添加URLEncoding
<Connector URIEncoding="UTF-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
login.jsp:
<form action="<%=basePath %>/login/check.jsp" method="post">
用户名:<input type="text" name="username"/><br/>
密码:<input type="password" name="password"/><br/>
<input type="submit" value="提交"/> <input type="reset" value="重置"/>
</form>
check.jsp:
<%
//解决乱码
request.setCharacterEncoding("UTF-8");
//步骤一:获取用户在页面输入的数据
String username=request.getParameter("username");
String password=request.getParameter("password");
//步骤二:校验用户名和密码
if((username!=""&&username!=null)&&(password!=""&&password!=null)){
if(username.equals("admin")&&password.equals("admin")){
//第一件事情:保存用户信息(可以用request对象也可以用session对象)
request.getSession().setAttribute("username", username);
//第二件事情:跳转页面(使用转发或者重定向)
//转发:同一次请求,在服务器内部进行,转发可以携带数据
request.getRequestDispatcher("welcome.jsp").forward(request, response);
//重定向:不同请求,在客户端执行,而且不能携带数据,需要制定全路径
//response.sendRedirect("/WebProject_Chap02/login/welcome.jsp");
}else{
System.out.println("登陆失败~");
response.sendRedirect("/WebProject_Chap02/login/login.jsp");
}
}else{
out.println("<script type=‘text/javascript‘>");
out.println("alert(‘请输入用户名或者密码‘)");
out.println("location.href=‘http://localhost:8080/WebProject_Chap02/login/login.jsp‘");
out.println("</script>");
}
%>
welcome.jsp:
欢迎登陆:${username }
会话是客户端与服务器建立的一次连接,会话有对应的过期时间,一旦会话过期或者关闭,那么存放再回话当中的数据将会自动释放
//设置session的失效时间
//session.setMaxInactiveInterval(5);
//获取会话ID,不同浏览器会话是不同的
out.print(session.getId());
//向session当中存放数据:一般用于存放用户的登陆信息
session.setAttribute("sessionKey", "张三");
//获取session中数据
Object value=session.getAttribute("sessionKey");
//删除session会话中的数据:当用户退出系统时,我们利用session的remove方法删除数据
session.removeAttribute("sessionKey");
session登陆拦截:在要拦截的页面中加入如下代码(思想为:登陆成功会往session存放用户数据,我们去页面中判断是否有用户数据就可以)
<%
//步骤一:先获取session对象中保存的userName值
Object value=session.getAttribute("username");
//步骤二:判断value是否为空
if(value==null){
response.sendRedirect("/WebProject_Chap02/login/login.jsp");
}
%>
sessionCheck.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
//步骤一:先获取session对象中保存的userName值
Object value=session.getAttribute("username");
//步骤二:判断value是否为空
if(value==null){
response.sendRedirect("/WebProject_Chap02/login/login.jsp");
}
%>
其他页面引入,在page指令下方
<%@ include file="sessionCheck.jsp" %>
<%
//返回相對路徑的真實路徑
//out.print(application.getRealPath("application.jsp"));
//获取当前的网站访问次数
Integer count = (Integer)application.getAttribute("count");
//当前访问为第一次时
if(count==null){
count=1;
}else{
count++;
}
//更改完访问次数后添加到application对象当中
application.setAttribute("count", count);
%>
<%="当前您是第"+application.getAttribute("count")+"访问的网站~" %>
jsp4大作用域,从小到大为:
1.page:当前页面有效
2.request:同一次请求有效
3.session:同一个会话有效
4.application:同一个应用有效
1.cookie和session区别
1.1 cookie不是内置对象,session是
1.2 session是在服务器内部存放信息的,而cookie由服务器创建,但是数据保存到客户端
1.3 session保存的数据为Object类型,而cookie保存的是字符串
1.4 session由会话结束而失效,但是cookie是长期保存到客户端的
1.5 session对比cookie安全一些
2.cookie案例:保存用户名信息
login.jsp代码:
<%
String username="";
//获取cookie
Cookie[] cookies=request.getCookies();
if(cookies!=null){
for(int i=0;i<cookies.length;i++){
//先看当前cookie当中有没有存放的name值
if(cookies[i].getName().equals("username")){
//获取value
username=cookies[i].getValue();
}
}
}
%>
<form action="<%=basePath %>/cookie/check.jsp" method="post">
用户名:<input type="text" name="username" value="<%=username%>"/><br/>
密码:<input type="password" name="password"/><br/>
<input type="submit" value="提交"/> <input type="reset" value="重置"/>
</form>
check.jsp页面代码:
<%
//解决乱码
request.setCharacterEncoding("UTF-8");
//步骤一:获取用户在页面输入的数据
String username=request.getParameter("username");
String password=request.getParameter("password");
//步骤二:校验用户名和密码
if((username!=""&&username!=null)&&(password!=""&&password!=null)){
if(username.equals("admin")&&password.equals("admin")){
//第一件事情:保存用户信息(可以用request对象也可以用session对象)
request.getSession().setAttribute("username", username);
//用Cookie存放数据
Cookie cookie=new Cookie("username",username);
//利用response对象将cookie保存到客户端
response.addCookie(cookie);
//第二件事情:跳转页面(使用转发或者重定向)
//转发:同一次请求,在服务器内部进行,转发可以携带数据
request.getRequestDispatcher("welcome.jsp").forward(request, response);
//重定向:不同请求,在客户端执行,而且不能携带数据,需要制定全路径
//response.sendRedirect("/WebProject_Chap02/login/welcome.jsp");
}else{
System.out.println("登陆失败~");
response.sendRedirect("/WebProject_Chap02/cookie/login.jsp");
}
}else{
out.println("<script type=‘text/javascript‘>");
out.println("alert(‘请输入用户名或者密码‘)");
out.println("location.href=‘http://localhost:8080/WebProject_Chap02/cookie/login.jsp‘");
out.println("</script>");
}
%>
Servlet是一个自定义的类,暴露给客户端一个访问地址,可以实现跟用户交互
方法一:新建一个类,实现Servlet接口
@WebServlet(urlPatterns= {"/FirstServlet"},loadOnStartup=1)
public class FirstServlet implements Servlet{
/**
* 初始化Servlet
*/
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("========================Servlet初始化工作完成~");
}
/**
* 获取Servlet配置
*/
@Override
public ServletConfig getServletConfig() {
return null;
}
/**
* 处理用户请求的方法
*/
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
//接受用户携带的参数数据
String parameter = req.getParameter("address");
System.out.println("==========================处理用户请求~\t"+parameter);
}
/**
* 获取Servlet信息
*/
@Override
public String getServletInfo() {
return null;
}
/**
* Servlet销毁方法
*/
@Override
public void destroy() {
System.out.println("==========================Servlet销毁~");
}
}
方法二:新建一个类,继承GenericServlet
@WebServlet("/SecondServlet")
public class SecondServlet extends GenericServlet{
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("GenericServlet方法二的请求方法service");
}
}
方法三:新建一个类,继承HttpServlet(手动重写doGet和doPost)
@WebServlet("/ThreadServlet")
public class ThreadServlet extends HttpServlet{
/**
* doGet专门处理HTTP Get请求
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Get和Post请求都能执行");
}
}
方式一:基于web.xml
<!-- 配置Servlet -->
<servlet>
<servlet-name>FouthServlet</servlet-name> <!--名称:建议和类名相同-->
<servlet-class>com.wdksoft.servlet.FouthServlet</servlet-class> <!--地址-->
</servlet>
<servlet-mapping>
<servlet-name>FouthServlet</servlet-name> <!--名称:与上面servlet节点的servlet-name相同-->
<url-pattern>/FouthServlet</url-pattern> <!--访问地址:不要忘记加/-->
</servlet-mapping>
方式二:基于注解
在类上加入@WebServlet("/FouthServlet")注解,括号内一个参数时直接传入地址,不要忘记加/
默认初始化时机为客户端请求时执行init方法,可以根据loadOnStartUp属性(默认为-1)控制
更改初始化时机:
<servlet>
<servlet-name>FouthServlet</servlet-name>
<servlet-class>com.wdksoft.servlet.FouthServlet</servlet-class>
<!-- 初始化时机:值越大,越先加载 -->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>FouthServlet</servlet-name>
<url-pattern>/FouthServlet</url-pattern>
</servlet-mapping>
注解方式:
@WebServlet(urlPatterns= {"/FirstServlet"},loadOnStartup=1)
1.由Servlet容器进行创建实例
2.初始化
3.执行处理请求方法
4.销毁
客户端发送请求时,Servlet容器会创建对应Servlet实例,然后执行init初始化方法,然后执行service处理请求方法,最终Servlet容器释放会调度Servlet的destroy方法
login.jsp页面
<form action="UserServlet?action=login" method="post">
用户名:<input type="text" name="username"/>
密码:<input type="password" name="password"/>
<input type="submit" value="提交"/><input type="reset" value="重置"/>
</form>
UserSerlvet代码:
@WebServlet("/UserServlet")
public class UserServlet extends HttpServlet {
// 序列化标识ID
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 区分不同功能
String action = request.getParameter("action");
if (action != null) {
if (action.equals("login")) {
// 获取到用户提交的数据
String username = request.getParameter("username");
String password = request.getParameter("password");
// 判断用户名和密码是否正确
if (username.equals("admin") && password.equals("admin")) {
// 保存用户信息
request.getSession().setAttribute("user", username);
// 跳转到Welcome.jsp页面
response.sendRedirect("/WebProject_Chap03/welcome.jsp");
} else {
// 解决服务器向客户端发送信息乱码
response.setContentType("text/html;charset=utf-8");
// 提示:用响应对象构建提示页面
response.getWriter().write("<script type=‘text/javascript‘>");
response.getWriter().write("alert(‘请输入用户名或者密码‘);");
response.getWriter().write("location.href=‘/WebProject_Chap03/login.jsp‘");
response.getWriter().write("</script>");
}
} else if (action.equals("logOut")) {
// 清除session数据
request.getSession().removeAttribute("user");
response.sendRedirect("/WebProject_Chap03/login.jsp");
}
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
welcome.jsp页面代码
欢迎登陆:${user } <a href="UserServlet?action=logOut">退出</a>
局部Servlet:利用ServletConfig接口
web.xml文件配置
<!-- 配置Servlet -->
<servlet>
<servlet-name>FouthServlet</servlet-name>
<servlet-class>com.wdksoft.servlet.FouthServlet</servlet-class>
<!-- 配置初始化参数 -->
<init-param>
<param-name>init</param-name>
<param-value>initValue</param-value>
</init-param>
<init-param>
<param-name>init2</param-name>
<param-value>initValue2</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>FouthServlet</servlet-name>
<url-pattern>/FouthServlet</url-pattern>
</servlet-mapping>
Servlet内获取:
String initValue = getInitParameter("init");
System.out.println("ServletConfig:"+initValue);
全局:所有Servlet共享:
web.xml文件配置
<context-param>
<param-name>context</param-name>
<param-value>contextValue</param-value>
</context-param>
获取:
//获取全局初始化参数
String context = getServletContext().getInitParameter("context2");
System.out.println("ServletContext:"+context);
软开当中:分层概念
1.实体层:Entity(一个类对应的一个数据库表) Grade:GradeId GradeName
2.数据访问层:Dao层(数据访问:将数据库的数据取出来保存到Entity当中,同样将Entity中的数据保存数据库)
3.业务逻辑层:Service层(书写业务逻辑的)
4.UI层:Servlet 跟用户进行交互的
传统开发:代码冗余,代码耦合
//步骤一:加载驱动
Class.forName("com.mysql.jdbc.Driver");
//步骤二:获取连接
Connection con=DriverManager.getConnection("jdbc:mysql:///myschool","root","root");
//步骤三:准备一条SQL
String sql="select * from student where studentName=? and StudentNo=?";
//步骤四:获取PreparedStatment对象
PreparedStatment ps=con.preparedStatement(sql);
ps.setObject.setObject
//步骤五:执行SQL
ResultSet rs=ps.executeQuery();
//步骤六:处理数据
if(rs!=null){
while(rs.next()){
String name=rs.getxxx(COLUNM);
String sex=rs.getxxx();
}
}
//最后回收资源
insert into Student(xxxxxxxx) values(?,?,?,?,?)
BaseDao工具类
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class BaseDao {
// 步骤一:创建数据库4大连接参数
private static final String DRIVER = "com.mysql.jdbc.Driver";
private static final String URL = "jdbc:mysql://localhost:3306/myschool?useUniCode=true&characterEncoding=utf-8";
private static final String USERNAME = "root";
private static final String PASSWORD = "root";
private Connection conn;
private PreparedStatement ps;
private ResultSet rs;
// 封装一个获取连接的方法
public void getConnection() throws Exception {
// 加载驱动
Class.forName(DRIVER);
// 获取连接
if (conn == null) {
conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
}
}
// 增删改方法
public int executeUpdate(String sql, Object... objs) throws Exception {
// 获取连接
getConnection();
// 获取PreparedStatement对象
ps = conn.prepareStatement(sql);
// 循环给?赋值
for (int i = 1; i <= objs.length; i++) {
ps.setObject(i, objs[i - 1]);
}
// 执行SQL
int count = ps.executeUpdate();
return count;
}
// 查询
public ResultSet executeQuery(String sql, Object... objs) throws Exception {
// 获取连接
getConnection();
// 获取PreparedStatement对象
ps = conn.prepareStatement(sql);
// 循环给?赋值
for (int i = 1; i <= objs.length; i++) {
ps.setObject(i, objs[i - 1]);
}
// 执行SQL
rs = ps.executeQuery();
return rs;
}
// 关闭资源
public void closeResource() throws Exception {
if (rs != null) {
rs.close();
}
if (ps != null) {
ps.close();
}
if (conn != null) {
conn.close();
}
}
}
Entity实体:
import java.io.Serializable;
import java.util.Date;
public class Student implements Serializable{
/**
* 序列化标识ID
*/
private static final long serialVersionUID = 8000378773322768639L;
private Integer studentNo;
private String loginPwd;
private String studentName;
private Integer sex;
private Integer gradeId;
private String phone;
private String address;
private Date bornDate;
private String email;
private String identityCard;
public Integer getStudentNo() {
return studentNo;
}
public void setStudentNo(Integer studentNo) {
this.studentNo = studentNo;
}
public String getLoginPwd() {
return loginPwd;
}
public void setLoginPwd(String loginPwd) {
this.loginPwd = loginPwd;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public Integer getGradeId() {
return gradeId;
}
public void setGradeId(Integer gradeId) {
this.gradeId = gradeId;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Date getBornDate() {
return bornDate;
}
public void setBornDate(Date bornDate) {
this.bornDate = bornDate;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getIdentityCard() {
return identityCard;
}
public void setIdentityCard(String identityCard) {
this.identityCard = identityCard;
}
@Override
public String toString() {
return "Student [studentNo=" + studentNo + ", loginPwd=" + loginPwd + ", studentName=" + studentName + ", sex="
+ sex + ", gradeId=" + gradeId + ", phone=" + phone + ", address=" + address + ", bornDate=" + bornDate
+ ", email=" + email + ", identityCard=" + identityCard + "]";
}
public Student(Integer studentNo, String loginPwd, String studentName, Integer sex, Integer gradeId, String phone,
String address, Date bornDate, String email, String identityCard) {
this.studentNo = studentNo;
this.loginPwd = loginPwd;
this.studentName = studentName;
this.sex = sex;
this.gradeId = gradeId;
this.phone = phone;
this.address = address;
this.bornDate = bornDate;
this.email = email;
this.identityCard = identityCard;
}
public Student() {
}
}
Dao层接口
public interface IStudentDao {
//添加数据
public int insertStudent(Student student) throws Exception;
//修改数据
public int updateStudent(Student student) throws Exception;
//删除数据
public int deleteStudent(Integer studentNo) throws Exception;
//查询单条数据
public Student findOneStudent(Integer studentNo) throws Exception;
//查询多条
public List<Student> findAllStudent() throws Exception;
}
DaoImpl实现类
public class IStudentDaoImpl extends BaseDao implements IStudentDao {
@Override
public int insertStudent(Student student) throws Exception {
//创建SQL语句
String sql="insert into Student(StudentNo,LoginPwd,StudentName,Sex,GradeId,Phone,Address,BornDate,Email,IdentityCard) Values(?,?,?,?,?,?,?,?,?,?)";
Object [] objects= {student.getStudentNo(),student.getLoginPwd(),student.getStudentName(),student.getSex(),student.getGradeId(),student.getPhone(),student.getAddress(),student.getBornDate(),student.getEmail(),student.getIdentityCard()};
int count = executeUpdate(sql, objects);
return count;
}
@Override
public int updateStudent(Student student) throws Exception {
String sql="update Student set StudentName=? where StudentNo=?";
int count = executeUpdate(sql, student.getStudentName(),student.getStudentNo());
return count;
}
@Override
public int deleteStudent(Integer studentNo) throws Exception {
String sql="delete from student where StudentNo=?";
return executeUpdate(sql, studentNo);
}
@Override
public Student findOneStudent(Integer studentNo) throws Exception {
Student student=new Student();
String sql="select * from student where StudentNo=?";
ResultSet rs = executeQuery(sql, studentNo);
if(rs!=null) {
while (rs.next()) {
student.setStudentNo(rs.getInt("studentNo"));
student.setLoginPwd(rs.getString("loginPwd"));
student.setStudentName(rs.getString("studentName"));
student.setSex(rs.getInt("sex"));
student.setGradeId(rs.getInt("gradeId"));
student.setPhone(rs.getString("phone"));
student.setAddress(rs.getString("address"));
student.setBornDate(rs.getDate("BornDate"));
student.setEmail(rs.getString("email"));
student.setIdentityCard(rs.getString("identityCard"));
}
}
return student;
}
@Override
public List<Student> findAllStudent() throws Exception {
List<Student> stuList=new ArrayList<>();
String sql="select * from student";
ResultSet rs = executeQuery(sql);
if(rs!=null) {
while (rs.next()) {
Student student=new Student();
student.setStudentNo(rs.getInt("studentNo"));
student.setLoginPwd(rs.getString("loginPwd"));
student.setStudentName(rs.getString("studentName"));
student.setSex(rs.getInt("sex"));
student.setGradeId(rs.getInt("gradeId"));
student.setPhone(rs.getString("phone"));
student.setAddress(rs.getString("address"));
student.setBornDate(rs.getDate("BornDate"));
student.setEmail(rs.getString("email"));
student.setIdentityCard(rs.getString("identityCard"));
stuList.add(student);
}
}
return stuList;
}
}
调用测试:
public static void main(String[] args) throws Exception {
//创建Dao层对象
IStudentDao iStudentDao=new IStudentDaoImpl();
String date="1999-8-5";
//将字符串转换为日期类型
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");
Date bornDate = simpleDateFormat.parse(date);
/*int insertCount = iStudentDao.insertStudent(new Student(1020, "123", "徐士康", 1, 1, "120120120120", "北京", bornDate, "123@qq.com", "123456789987456213"));
System.out.println("添加结果:"+insertCount);*/
System.out.println("===============================修改=======================================================");
Student student=new Student();
student.setStudentName("余博");
student.setStudentNo(1020);
int updateCount = iStudentDao.updateStudent(student);
System.out.println("修改结果:"+updateCount);
System.out.println("===============================删除=======================================================");
int deleteCount = iStudentDao.deleteStudent(1020);
System.out.println("删除结果:"+deleteCount);
System.out.println("===============================单条查询=======================================================");
Student oneStudent = iStudentDao.findOneStudent(1000);
System.out.println(oneStudent.toString());
System.out.println("===============================多条查询=======================================================");
List<Student> stuList = iStudentDao.findAllStudent();
for (Student stuItem : stuList) {
System.out.println(stuItem.toString());
}
}
JNDI案例:配置Tomcat文件,达到资源共享效果
在Tomcat中的context.xml文件中配置JNDI
<!-- 配置JNDI name属性对应资源名称 value对应资源 type对应资源的数据类型-->
<Environment name="jndiResource" value="T26" type="java.lang.String"/>
获取JNDI资源
<%
//获取Context上下文对象
Context ctx=new InitialContext();
//定位JNDI资源
String jndiValue=(String)ctx.lookup("java:comp/env/jndiResource");
out.print(jndiValue);
%>
传统连接数据库时,需要创建连接对象,连接池是帮我们管理和维护连接对象
使用连接池:
1.将数据库驱动jar放到tomcat中lib文件夹下
2.配置Tomcat配置文件context.xml
<!-- 连接池 -->
<Resource name="jdbc/news" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000" username="root"
password="root" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://127.0.0.1:3306/newsmanagersystem?
useUnicode=true&characterEncoding=utf-8" />
3.使用连接池(更改BaseDao)
public void getConnection() throws Exception {
//创建上下文对象
Context context=new InitialContext();
//获取连接池对象
DataSource dataSource=(DataSource)context.lookup("java:comp/env/jdbc/news");
//获取连接
conn=dataSource.getConnection();
}
文件上传组件:commons-fileupload组件
文件上传步骤:
commons-fileupload.jar
commons-io.jar
<form action="" method="post" enctype="multipart/form-data">
作者:<input type="text" name="author"/>
简介:<input type="text" name="summary"/>
<input type="file" name="file"/>
<input type="submit" value="上传"/>
</form>
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//判断当前提交的form表单是否是文件上传表单
boolean isMultipart = ServletFileUpload.isMultipartContent(req);
//如果当前是文件上传表单则拿到所有提交的数据
if(isMultipart) {
FileItemFactory fileItemFactory=new DiskFileItemFactory();
//创建ServletFileUpload对象
ServletFileUpload fileUpload=new ServletFileUpload(fileItemFactory);
fileUpload.setHeaderEncoding("UTF-8");
//获取提交的所有数据
try {
//每一个FileItem代表了每一个表单提交的数据
List<FileItem> fileItemList = fileUpload.parseRequest(req);
/*System.out.println("当前表单提交数据个数:"+fileItemList.size());*/
//循环拿到表单上传每一个元素
for (FileItem fileItem : fileItemList) {
//判断当前元素是普通的还是文件数据
if(fileItem.isFormField()) {
//判断普通表单元素的name值
if(fileItem.getFieldName().equals("author")) {
//获取当前普通表单元素的值
System.out.println("作者:"+fileItem.getString("UTF-8"));
}else if(fileItem.getFieldName().equals("summary")) {
System.out.println("内容:"+fileItem.getString("UTF-8"));
}
}else {
//判断文件大小
if(fileItem.getSize()<=2048000) {
//获取文件名字
String fileName=fileItem.getName();
//判断文件上传格式
int lastIndex = fileName.lastIndexOf(".");
//截取
String suffix = fileName.substring(lastIndex+1);
if(suffix.equals("jpg")||suffix.equals("gif")||suffix.equals("png")) {
//获取文件上传路径
String path=getServletContext().getRealPath("upload");
System.out.println(path);
//上传
File file=new File(path,fileName);
try {
//将内存中的文件写入到服务器
fileItem.write(file);
} catch (Exception e) {
e.printStackTrace();
}
}else {
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().write("文件上传格式不正确");
}
}else {
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().write("文件太大,无法上传~");
}
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
}
Servlet后台:
String name="张三";
req.setAttribute("variable", name);
req.getSession().setAttribute("variable", "李四");
req.getRequestDispatcher("/index.jsp").forward(req, resp);
JSP页面:
EL表达式获取变量的值:${requestScope.variable }
默认情况下会根据page--request--session--application找到即返回,如果没有找到返回的是Null
可以指定作用域取值,如${xxxScope.xxx}
Users users=new Users();
users.setUser_id(1);
users.setUser_name("张三");
req.setAttribute("obj", users);
req.getRequestDispatcher("/index.jsp").forward(req, resp);
EL表达式获取对象值:${obj.user_name }
List<Users> userList=new ArrayList<>();
Users users1=new Users();
users1.setUser_id(1);
users1.setUser_name("张三");
userList.add(users1);
Users users2=new Users();
users2.setUser_id(2);
users2.setUser_name("李四");
userList.add(users2);
req.setAttribute("userList", userList);
req.getRequestDispatcher("/index.jsp").forward(req, resp);
EL表达式获取List集合值:${userList[1].user_name }
Users users1=new Users();
users1.setUser_id(1);
users1.setUser_name("张三");
Users users2=new Users();
users2.setUser_id(2);
users2.setUser_name("李四");
Map<String, Users> userMap=new HashMap<>();
userMap.put("user1", users1);
userMap.put("user2", users2);
req.setAttribute("userMap", userMap);
req.getRequestDispatcher("/index.jsp").forward(req, resp);
EL表达式获取Map值:${userMap["user2"].user_name }
步骤一:在工程中加入jstl-xxx.jar
步骤二:在页面中使用taglib指令导入(uri属性代表地址,导入的是http://java.sun.com/jsp/jstl/core prefix属性代表前缀,可任意,推荐c)
JSP三大指令:page incloud taglib
<!-- set标签给变量赋值 var代表变量名 value代表变量值 scope代表作用域-->
<c:set var="name" value="张三" scope="session"/>
${name }
<!-- set标签给对象属性赋值 target代表目标对象 property代表属性 value代表给属性的值-->
<%
Users users=new Users();
request.setAttribute("users", users);
%>
<%-- <c:set target="${users }" property="user_name" value="李四"/> --%>
<hr/>
<!-- out标签用于计算值并且输出到页面上 value代表页面输出的内容 default代表如果输出内容为null,可以给默认值-->
<c:out value="呵呵,low"/>
<c:out value="${users.user_name }" default="王五"/>
<!-- out标签转义 -->
<c:out escapeXml="false" value="<a href=‘http://www.baidu.com‘>百度</a>"/>
<hr/>
<!-- remove标签删除数据 var代表变量名 scope作用域-->
<c:remove var="name" scope="session"/>
<!-- c:if 属性test代表表达式返回true或者false var属性代表返回值结果 scope保存值得作用域 -->
<c:if test="${‘admin‘ eq ‘admin‘ }" var="flag" scope="page">
${flag }
</c:if>
<hr/>
<c:choose>
<c:when test="${1==2 }">
第一个when
</c:when>
<c:when test="${1==2 }">
第二个when
</c:when>
<c:otherwise>
其他情况
</c:otherwise>
</c:choose>
<!-- items代表要遍历的集合 var代表集合中的每一项 step代表步长 begin代表开始位置 end代表结束位置 varStatus每一项数据的引用 -->
<c:forEach items="${userList }" var="item" step="2" varStatus="i">
${item.user_name }
</c:forEach>
<!-- forEach遍历map -->
<c:forEach items="${userMap }" var="mapItem">
${mapItem.value.user_name }
</c:forEach>
同步请求,客户端向服务器发送请求,服务器响应整合页面
异步请求,客户端发送请求,服务器响应对应数据
//原生态Ajax请求的核心对象XMLHttpRequest
var xhr=null;
if(window.XMLHttpRequest){
//IE7+
xhr=new XMLHttpRequest();
}else{
xhr=new ActiveXObject("Microsoft.XMLHTTP");
}
//构建一个异步请求
xhr.open("POST","AjaxServlet",true);
//设置请求头
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
//发送请求
xhr.send("name="+username.value);
//接受响应
xhr.onreadystatechange=function(){
//服务器响应结束并且是正常响应
if(xhr.readyState==4&&xhr.status==200){
//获取响应回来的数据Text
if(xhr.responseText=="false"){
document.getElementById("message").innerText="不能注册~";
}else{
document.getElementById("message").innerText="可以注册~";
}
}
}
//用Jquery提供的$.ajax发送请求
$.ajax({
url:"AjaxServlet", //请求发送地址
type:"POST", //请求方式,默认为Get
data:{name:$("#username").val()}, //传递给服务器的数据,推荐JSON
dataType:"text", //解析数据类型,必须确切匹配
success:function(result){ //成功响应回调函数 result代表服务器响应的数据
if(result=="false"){
$("#message").text("不能注册~");
}else{
$("#message").text("可以注册~");
}
},
error:function(){ //异常回调
alert("服务器响应错误,请稍后重试");
}
});
Json数据格式:JavaScript Object notation
Json格式字符串:{key:value,key2:value2}
JSON格式数组:
//定义Json格式数组
var jsonArray = [ {
"name" : "张三",
"address" : "北京"
}, {
"name" : "李四",
"address" : "上海"
}, {
"name" : "王五",
"address" : "河南"
}, {
"name" : "赵六",
"address" : "内蒙古"
} ];
JSON获取数据和遍历
//遍历数组
$.each(jsonArray,function(i,item){
alert(item.name);
})
一.导入Jar包
二.将Java对象转换为json格式数组
String userStr = JSON.toJSONString(user);
三.将JSON字符串反序列化为对象
Users parseObject = JSON.parseObject(userStr, Users.class);
一.驱动jar的加载
将jar包copy到web-inf下的lib文件夹,自动导包
二.登陆功能
1.创建实体
/**
* 承载用户信息的实体
* @author FLC
*
*/
public class News_Users implements Serializable{
/**
* 序列化ID
*/
private static final long serialVersionUID = -4385525238332285976L;
private Integer uid; //用户编号
private String uname; //用户名称
private String upwd; //登陆密码
private String telephone; //手机号
private String email; //邮箱
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public String getUpwd() {
return upwd;
}
public void setUpwd(String upwd) {
this.upwd = upwd;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "News_Users [uid=" + uid + ", uname=" + uname + ", upwd=" + upwd + ", telephone=" + telephone
+ ", email=" + email + "]";
}
public News_Users(Integer uid, String uname, String upwd, String telephone, String email) {
this.uid = uid;
this.uname = uname;
this.upwd = upwd;
this.telephone = telephone;
this.email = email;
}
public News_Users() {
}
}
2.搭建Dao层接口,创建一个方法,用于登陆功能,方法实现过程如下:
拿到用户名去数据库匹配,如果成功则返回有数据的对象,如果失败,返回null
/**
* 用户接口
* @author FLC
*
*/
import com.news.entity.News_Users;
public interface INewsUsersDao {
//登陆方法
public News_Users userLogin(String uname) throws Exception;
}
3.搭建Dao层实现类,用于跟数据库进行交互
/**
* 用户接口实现类
*
* @author FLC
*
*/
public class INewsUsersDaoImpl extends BaseDao implements INewsUsersDao {
@Override
public News_Users userLogin(String uname) throws Exception {
// 创建用户对象,并且返回
News_Users users = null;
// 准备一条SQL语句
String sql = "select * from news_users where uname=?";
// 执行SQL
ResultSet rs = executeQuery(sql, uname);
// 处理数据
if (rs != null) {
while (rs.next()) {
users=new News_Users();
users.setUid(rs.getInt("uid"));
users.setUname(rs.getString("uname"));
users.setUpwd(rs.getString("upwd"));
users.setTelephone(rs.getString("telephone"));
users.setEmail(rs.getString("email"));
}
}
return users;
}
}
4.service层接口,创建一个方法,用于校验用户名和密码,实现思路如下:
先拿到Servlet传递的用户名和密码,先跟Dao层进行用户名验证,如果验证有返回值结果,则再次验证密码,如果返回值为null,则直接返回NULL
/**
* 用户业务逻辑层接口
* @author FLC
*
*/
import com.news.entity.News_Users;
public interface INewsUsersService {
//登录业务方法定义
public News_Users userLogin(String uname,String upwd) throws Exception;
}
5.service层实现类:实现service层接口,重写接口中方法,将上述的逻辑编码到方法当中,实现功能
/**
* 用户业务逻辑处理类
* @author FLC
*
*/
public class INewsUsersServiceImpl implements INewsUsersService{
//植入Dao层对象
private INewsUsersDao iNewsUsersDao=new INewsUsersDaoImpl();
@Override
public News_Users userLogin(String uname, String upwd) throws Exception {
//验证用户名和密码
News_Users user = iNewsUsersDao.userLogin(uname);
if(user!=null) {
//验证密码
if(user.getUpwd().equals(upwd)) {
return user;
}
}
return null;
}
}
6.Servlet层,用于接收用户输入,传递给service做数据校验,校验完成则登陆成功,返回值为null则登陆失败,登陆成功保存用户信息,跳转首页
@WebServlet("/INewsUsersServlet")
public class INewsUsersServlet extends HttpServlet {
//创建Service层对象
private INewsUsersService iNewsUsersService=new INewsUsersServiceImpl();
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取action参数值,用于区分不同功能
String action = request.getParameter("action");
if(action!=null) {
//判断登录功能
if(action.equals("login")) {
//接收用户传递的用户名和密码
String username = request.getParameter("username");
String userpwd = request.getParameter("userpwd");
try {
//校验用户名密码
News_Users user = iNewsUsersService.userLogin(username, userpwd);
if(user!=null) {
//保存用户信息
request.getSession().setAttribute("user", user);
//跳转页面
response.sendRedirect("/NewsManager/index.jsp");
}else {
response.sendRedirect("/NewsManager/page/login/login.jsp");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
7.页面,提供给用户直观效果,共用户输入和提交
<form class="layui-form" action="<%=basePath %>INewsUsersServlet?action=login" method="post" id="myform">
<div class="login_face"><img src="<%=basePath %>images/face.jpg" class="userAvatar"></div>
<div class="layui-form-item input-item">
<label for="userName">用户名</label>
<input type="text" placeholder="请输入用户名" id="userName" name="username" class="layui-input">
</div>
<div class="layui-form-item input-item">
<label for="password">密码</label>
<input type="password" placeholder="请输入密码" id="password" name="userpwd" class="layui-input" >
</div>
<div class="layui-form-item input-item" id="imgCode">
<label for="code">验证码</label>
<input type="text" placeholder="请输入验证码" autocomplete="off" id="code" class="layui-input">
<img src="<%=basePath %>images/code.jpg">
</div>
<div class="layui-form-item">
<!-- <button class="layui-btn layui-block" lay-filter="login" lay-submit>登录</button> -->
<input type="submit" class="layui-btn layui-block" value="登录"/>
</div>
<div class="layui-form-item layui-row">
<a href="javascript:;" class="seraph icon-qq layui-col-xs4 layui-col-sm4 layui-col-md4 layui-col-lg4"></a>
<a href="javascript:;" class="seraph icon-wechat layui-col-xs4 layui-col-sm4 layui-col-md4 layui-col-lg4"></a>
<a href="javascript:;" class="seraph icon-sina layui-col-xs4 layui-col-sm4 layui-col-md4 layui-col-lg4"></a>
</div>
</form>
1.首先用户在页面中点击新闻请求,将请求发送到Servlet
找到json文件夹下的nav.json,修改href为Servlet地址
"title": "新闻列表",
"icon": "icon-text",
"href": "/NewsManager/INewsServlet?action=newsList",
"spread": false
2.构建Servlet实现和用户数据的交互过程,servlet需要调用service拿到数据,然后将取到的数据保存到request作用域当中,然后转发到页面
@WebServlet("/INewsServlet")
public class INewsServlet extends HttpServlet{
//植入Service层对象
private INewsService iNewsService=new INewsServiceImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action=req.getParameter("action");
if(action!=null) {
if(action.equals("newsList")) {
try {
List<News> newsList = iNewsService.getAllNews();
//保存集合数据
req.setAttribute("newsList", newsList);
//转发
req.getRequestDispatcher("/page/news/newsList.jsp").forward(req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
3.构建Service层,提供给Servlet数据,数据来源于Dao层
Service层接口定义方法,用于查询所有新闻
public interface INewsService {
// 查询所有新闻数据
public List<News> getAllNews() throws Exception;
}
ServiceImpl实现类调用Dao层拿到数据
public class INewsServiceImpl implements INewsService{
//植入Dao层对象
private INewsDao iNewsDao=new INewsDaoImpl();
@Override
public List<News> getAllNews() throws Exception {
return iNewsDao.getAllNews();
}
}
4.构建Dao层,用于操作数据
Dao层接口定义方法,用于查询所有新闻
public interface INewsDao {
// 查询所有新闻数据
public List<News> getAllNews() throws Exception;
}
DaoImpl实现类访问数据库拿到数据
public class INewsDaoImpl extends BaseDao implements INewsDao{
@Override
public List<News> getAllNews() throws Exception {
List<News> newsList=new ArrayList<>();
//创建SQL语句
String sql="select * from news,topic where news.ntid=topic.tid";
//执行SQL
ResultSet rs = executeQuery(sql);
//将数据封装到实体对象当中
if(rs!=null) {
while (rs.next()) {
News news=new News();
news.setNid(rs.getInt("nid"));
news.setNtitle(rs.getString("ntitle"));
news.setNtid(rs.getInt("ntid"));
news.setNauthor(rs.getString("nauthor"));
news.setNcontent(rs.getString("ncontent"));
news.setNpicPath(rs.getString("npicpath"));
news.setNcreateDate(rs.getDate("ncreateDate"));
news.setNmodifyDate(rs.getDate("nmodifyDate"));
news.setNsummary(rs.getString("nsummary"));
Topic topic=new Topic();
topic.setTid(rs.getInt("tid"));
topic.setTname(rs.getString("tname"));
news.setTopic(topic);
newsList.add(news);
}
}
return newsList;
}
}
5.数据封装到实体News Topic
6.渲染页面
<table class="layui-table">
<thead>
<tr>
<th><input type="checkbox" name="allChecked" /></th>
<th>新闻编号</th>
<th>新闻标题</th>
<th>新闻类别</th>
<th>发布者</th>
<th>发布时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<%
List<News> newsList=(List<News>)request.getAttribute("newsList");
for(News news:newsList){
%>
<tr>
<th><input type="checkbox" name="allChecked" /></th>
<td><%=news.getNid() %></td>
<td><%=news.getNtitle() %></td>
<td><%=news.getTopic().getTname() %></td>
<td><%=news.getNauthor() %></td>
<td><%=news.getNcreateDate() %></td>
<td><a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="del">删除</a>
<a class="layui-btn layui-btn-xs layui-btn-primary" lay-event="look">预览</a></td>
</tr>
<%
}
%>
</tbody>
</table>
1.绑定添加新闻页面的下拉框分类列表
1.1 新建Dao层接口,提供查询所有新闻分类的方法
public interface ITopicDao {
//新闻添加页面中的分类列表绑定
public List<Topic> getAllTopic() throws Exception;
}
1.2 创建Dao层接口的实现类,从数据库查询数据并保存
public class ITopicDaoImpl extends BaseDao implements ITopicDao {
@Override
public List<Topic> getAllTopic() throws Exception {
List<Topic> topicList=new ArrayList<>();
String sql="select * from topic";
ResultSet rs = executeQuery(sql);
if(rs!=null) {
while (rs.next()) {
Topic topic=new Topic();
topic.setTid(rs.getInt("tid"));
topic.setTname(rs.getString("tname"));
topicList.add(topic);
}
}
return topicList;
}
}
1.3 新建Service层接口,方法与Dao层方法相同
public interface ITopicService {
//新闻添加页面中的分类列表绑定
public List<Topic> getAllTopic() throws Exception;
}
1.4 创建Service层接口的实现类,重写接口中的方法,调用Dao层方法,实现数据传递
public class ITopicServiceImpl implements ITopicService {
private ITopicDao iTopicDao=new ITopicDaoImpl();
@Override
public List<Topic> getAllTopic() throws Exception {
return iTopicDao.getAllTopic();
}
}
1.5 新建Servlet层,控制用户发送请求的访问,调度Service层获取数据,保存到request作用域当中,转发到newsAdd.jsp页面上
@WebServlet("/ITopicServlet")
public class ITopicServlet extends HttpServlet {
private ITopicService iTopicService=new ITopicServiceImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action=req.getParameter("action");
if(action!=null) {
if(action.equals("getTopicList")) {
try {
List<Topic> topicList = iTopicService.getAllTopic();
req.setAttribute("topicList", topicList);
req.getRequestDispatcher("/page/news/newsAdd.jsp").forward(req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
1.6 更改newsList.jsp页面中添加文章的按钮请求
<div class="layui-inline">
<a href="<%=basePath %>ITopicServlet?action=getTopicList" class="layui-btn layui-btn-normal">添加文章</a>
</div>
1.7 渲染newsAdd.jsp页面的下拉框
<div class="border category">
<select name="ntid">
<option value="0">请选择</option>
<%
List<Topic> topicList =(List<Topic>)request.getAttribute("topicList");
for(Topic topic:topicList){
%>
<option value="<%=topic.getTid() %>"><%=topic.getTname() %></option>
<%
}
%>
</select>
</div>
2.添加新闻
2.1添加新闻的页面更改(1.监控form表单提交 2.给元素name属性 3.更改提交按钮)
<form class="layui-form layui-row layui-col-space10" id="myform" action="<%=basePath%>INewsServlet?action=insertNews" method="post">
<div class="layui-col-md9 layui-col-xs12">
<div class="layui-row layui-col-space10">
<div class="layui-col-md9 layui-col-xs7">
<div class="layui-form-item magt3">
<label class="layui-form-label">文章标题</label>
<div class="layui-input-block">
<input type="text" class="layui-input newsName" name="ntitle" lay-verify="newsName" placeholder="请输入文章标题">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">内容摘要</label>
<div class="layui-input-block">
<textarea placeholder="请输入内容摘要" lay-verify="nsummary" name="nsummary" class="layui-textarea abstract"></textarea>
</div>
</div>
</div>
<div class="layui-col-md3 layui-col-xs5">
<div class="layui-upload-list thumbBox mag0 magt3">
<img class="layui-upload-img thumbImg">
</div>
</div>
</div>
<div class="layui-form-item magb0">
<label class="layui-form-label">文章内容</label>
<div class="layui-input-block">
<textarea class="layui-textarea layui-hide" name="ncontent" lay-verify="content" id="news_content"></textarea>
</div>
</div>
</div>
<div class="layui-col-md3 layui-col-xs12">
<blockquote class="layui-elem-quote title"><i class="seraph icon-caidan"></i> 分类目录</blockquote>
<div class="border category">
<select name="ntid">
<option value="0">请选择</option>
<%
List<Topic> topicList =(List<Topic>)request.getAttribute("topicList");
for(Topic topic:topicList){
%>
<option value="<%=topic.getTid() %>"><%=topic.getTname() %></option>
<%
}
%>
</select>
</div>
<hr class="layui-bg-gray" />
<div class="layui-right">
<input type="submit" value="提交" class="layui-btn layui-btn-sm"/>
<!-- <a class="layui-btn layui-btn-sm" lay-filter="addNews" lay-submit><i class="layui-icon"></i>发布</a> -->
<a class="layui-btn layui-btn-primary layui-btn-sm" lay-filter="look" lay-submit>预览</a>
</div>
</div>
</div>
</form>
2.2 获取富文本编辑器的纯文本内容(在newsAdd.js文件中监控表单提交,获取纯文本内容)
$("#myform").submit(function() {
//获取富文本编辑器的纯文本内容
var text=layedit.getText(editIndex);
//定位到新闻内容text
$("[name=ncontent]").val(text);
})
2.3 在INewsDao层中创建添加新闻的方法
public interface INewsDao {
//查询所有新闻数据
public List<News> getAllNews() throws Exception;
//添加新闻
public int insertNews(News news) throws Exception;
}
2.4 在INewsDaoImpl实现类中重写方法,实现数据添加
@Override
public int insertNews(News news) throws Exception {
//准备一条SQL语句
String sql="insert into news(ntid,ntitle,nauthor,ncreateDate,ncontent,nmodifyDate,nsummary) values(?,?,?,?,?,?,?)";
Object [] objs= {news.getNtid(),news.getNtitle(),news.getNauthor(),news.getNcreateDate(),news.getNcontent(),news.getNmodifyDate(),news.getNsummary()};
return executeUpdate(sql, objs);
}
2.5 在INewsService接口中创建和Dao层同样的方式,实现数据传递
public interface INewsService {
// 查询所有新闻数据
public List<News> getAllNews() throws Exception;
// 添加新闻
public int insertNews(News news) throws Exception;
}
2.6 在INewsServiceImpl实现类中重写方法,调度Dao层
@Override
public int insertNews(News news) throws Exception {
return iNewsDao.insertNews(news);
}
2.7 编写INewsServlet,区分功能,实现接受页面输入,封装数据,传递给service层,判断返回值,是否添加成功~
else if(action.equals("insertNews")) {
//将数据封装到News对象当中
News news=new News();
news.setNtitle(req.getParameter("ntitle"));
news.setNsummary(req.getParameter("nsummary"));
news.setNcontent(req.getParameter("ncontent"));
news.setNtid(Integer.parseInt(req.getParameter("ntid")));
news.setNcreateDate(new Date());
news.setNmodifyDate(new Date());
//作者是登陆成功之后保存到Session中的数据
News_Users user = (News_Users)req.getSession().getAttribute("user");
news.setNauthor(user.getUname());
try {
int count = iNewsService.insertNews(news);
if(count>0) {
//重新查询数据库数据
req.getRequestDispatcher("/INewsServlet?action=newsList").forward(req, resp);
}else {
req.getRequestDispatcher("/INewsServlet?action=newsList").forward(req, resp);
}
} catch (Exception e) {
e.printStackTrace();
}
}
1.将页面中所有用到分页的零散数据封装到pageUtil当中
public class PageUtil<T> {
// 当前页码
private Integer pageIndex;
// 每页显示的记录数
private Integer pageSize;
// 总记录数
private Integer pageTotalCount;
// 总页数
private Integer pageTotalNumbers;
//页面显示的集合数据
private List<T> pageList;
public Integer getPageIndex() {
return pageIndex;
}
public void setPageIndex(Integer pageIndex) {
if(pageIndex<=0) {
pageIndex=1;
}else if(pageIndex>getPageTotalNumbers()) {
pageIndex=getPageTotalNumbers();
}
this.pageIndex = pageIndex;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Integer getPageTotalCount() {
return pageTotalCount;
}
public void setPageTotalCount(Integer pageTotalCount) {
this.pageTotalCount = pageTotalCount;
}
public Integer getPageTotalNumbers() {
pageTotalNumbers=this.getPageTotalCount()%this.getPageSize()==0 ? this.getPageTotalCount()/this.getPageSize() : this.getPageTotalCount()/this.getPageSize()+1;
return pageTotalNumbers;
}
public List<T> getPageList() {
return pageList;
}
public void setPageList(List<T> pageList) {
this.pageList = pageList;
}
}
2.在INewsDao中创建两个方法,一个用于待条件查询分页的列表数据,第二个用于待条件查询所有记录数
public interface INewsDao {
//查询所有新闻数据
public List<News> getAllNews() throws Exception;
//添加新闻
public int insertNews(News news) throws Exception;
//分页查询新闻数据
public List<News> getPageNewsList(int pageIndex,int pageSize,String ntitle) throws Exception;
//查询总记录数
public int getPageCount(String ntitle) throws Exception;
}
3.在INewsDaoImpl实现类中重写方法,实现数据查询,利用StringBuffer对象动态拼接SQL
@Override
public List<News> getPageNewsList(int pageIndex, int pageSize,String ntitle) throws Exception {
List<News> newsList=new ArrayList<>();
StringBuffer sBuffer=new StringBuffer("select * from news,topic where news.ntid=topic.tid ");
if(ntitle!=null) {
sBuffer.append(" and ntitle like ‘%"+ntitle+"%‘ ");
}
sBuffer.append(" order by nCreateDate desc limit ?,? ");
//执行SQL
ResultSet rs = executeQuery(sBuffer.toString(),(pageIndex-1)*pageSize,pageSize);
//将数据封装到实体对象当中
if(rs!=null) {
while (rs.next()) {
News news=new News();
news.setNid(rs.getInt("nid"));
news.setNtitle(rs.getString("ntitle"));
news.setNtid(rs.getInt("ntid"));
news.setNauthor(rs.getString("nauthor"));
news.setNcontent(rs.getString("ncontent"));
news.setNpicPath(rs.getString("npicpath"));
news.setNcreateDate(rs.getDate("ncreateDate"));
news.setNmodifyDate(rs.getDate("nmodifyDate"));
news.setNsummary(rs.getString("nsummary"));
Topic topic=new Topic();
topic.setTid(rs.getInt("tid"));
topic.setTname(rs.getString("tname"));
news.setTopic(topic);
newsList.add(news);
}
}
return newsList;
}
@Override
public int getPageCount(String ntitle) throws Exception {
//总记录数
int count=0;
StringBuffer sBuffer=new StringBuffer("select count(*) as count from news where 1=1");
if(ntitle!=null) {
sBuffer.append(" and ntitle like ‘%"+ntitle+"%‘ ");
}
ResultSet rs = executeQuery(sBuffer.toString());
if(rs.next()) {
count=rs.getInt("count");
}
return count;
}
4.在INewsService接口中添加与Dao层相同的方法
public interface INewsService {
// 查询所有新闻数据
public List<News> getAllNews() throws Exception;
// 添加新闻
public int insertNews(News news) throws Exception;
// 分页查询新闻数据
public List<News> getPageNewsList(int pageIndex, int pageSize, String ntitle) throws Exception;
// 查询总记录数
public int getPageCount(String ntitle) throws Exception;
}
5.在INewsServiceImpl实现类中重写方法,调度Dao层
public class INewsServiceImpl implements INewsService{
//植入Dao层对象
private INewsDao iNewsDao=new INewsDaoImpl();
@Override
public List<News> getAllNews() throws Exception {
return iNewsDao.getAllNews();
}
@Override
public int insertNews(News news) throws Exception {
return iNewsDao.insertNews(news);
}
@Override
public List<News> getPageNewsList(int pageIndex, int pageSize,String ntitle) throws Exception {
return iNewsDao.getPageNewsList(pageIndex, pageSize,ntitle);
}
@Override
public int getPageCount(String ntitle) throws Exception {
return iNewsDao.getPageCount(ntitle);
}
}
6.在Servlet中新建功能分支,接收页面传递的当前页码,以及条件进行查询
protected void getPage(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//创建分页工具类对象
PageUtil<News> pageUtil=new PageUtil<>();
//获取条件数据
String ntitle=req.getParameter("ntitle");
//封装每页显示的记录数
int pageSize=3;
pageUtil.setPageSize(pageSize);
try {
//封装总记录数
int count = iNewsService.getPageCount(ntitle);
pageUtil.setPageTotalCount(count);
//封装当前页码
String pageIndex=req.getParameter("pageIndex");
if(pageIndex!=null) {
pageUtil.setPageIndex(Integer.parseInt(pageIndex));
}else {
pageIndex="1";
pageUtil.setPageIndex(Integer.parseInt(pageIndex));
}
//封装集合数据
pageUtil.setPageList(iNewsService.getPageNewsList(pageUtil.getPageIndex(), pageUtil.getPageSize(),ntitle));
//保存pageUtil对象啊
req.setAttribute("pageUtil", pageUtil);
req.setAttribute("ntitle", ntitle);
//转发页面
req.getRequestDispatcher("/page/news/newsList.jsp").forward(req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
7.newsList.jsp页面数据回显以及上一页下一页带条件搜索
<input type="text" name="ntitle" class="layui-input"
placeholder="请输入搜索的内容" value="${ntitle }" />
数据显示:
<table class="layui-table">
<thead>
<tr>
<th><input type="checkbox" name="allChecked" /></th>
<th>新闻编号</th>
<th>新闻标题</th>
<th>新闻类别</th>
<th>发布者</th>
<th>发布时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<%
PageUtil<News> pageUtil = (PageUtil<News>) request.getAttribute("pageUtil");
for (News news : pageUtil.getPageList()) {
%>
<tr>
<th><input type="checkbox" name="allChecked" /></th>
<td><%=news.getNid()%></td>
<td><%=news.getNtitle()%></td>
<td><%=news.getTopic().getTname()%></td>
<td><%=news.getNauthor()%></td>
<td><%=news.getNcreateDate()%></td>
<td><a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="del">删除</a>
<a class="layui-btn layui-btn-xs layui-btn-primary"
lay-event="look">预览</a></td>
</tr>
<%
}
%>
</tbody>
</table>
<a href="<%=basePath %>INewsServlet?action=getPage&ntitle=${ntitle}"
class="layui-btn" data-type="reload">首页</a> <a
href="<%=basePath %>INewsServlet?action=getPage&pageIndex=<%=pageUtil.getPageIndex()-1 %>&ntitle=${ntitle}"
class="layui-btn" data-type="reload">上一页</a> ${pageUtil.pageIndex }/${pageUtil.pageTotalNumbers }
<a
href="<%=basePath %>INewsServlet?action=getPage&pageIndex=<%=pageUtil.getPageIndex()+1 %>&ntitle=${ntitle}"
class="layui-btn" data-type="reload">下一页</a> <a
href="<%=basePath %>INewsServlet?action=getPage&pageIndex=<%=pageUtil.getPageTotalNumbers() %>&ntitle=${ntitle}"
class="layui-btn" data-type="reload">尾页</a>
修改新闻:
1.点击编辑按钮,请求后台Servlet获取到当前要编辑的单条新闻数据
<a class=‘layui-btn layui-btn-xs‘ lay-event=‘edit‘ href=‘/NewsManager/INewsServlet?action=getNewsInfo&nid="+news.nid+"‘>编辑</a>
else if(action.equals("getNewsInfo")) {
//查询当前选择的新闻数据
String nid=req.getParameter("nid");
try {
News news = iNewsService.getOneNews(Integer.parseInt(nid));
List<Topic> allTopic = iTopicService.getAllTopic();
req.setAttribute("news", news);
req.setAttribute("topicList", allTopic);
req.getRequestDispatcher("/page/news/newsAdd.jsp").forward(req, resp);
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
2.将数据绑定到newsAdd.jsp中,完成数据回显
<input type="text" class="layui-input newsName" name="ntitle" lay-verify="newsName" value="${news.ntitle }" placeholder="请输入文章标题">
<textarea placeholder="请输入内容摘要" lay-verify="nsummary" name="nsummary" class="layui-textarea abstract">${news.nsummary }</textarea>
<img class="layui-upload-img" id="selectImg" width="200px" height="130px" src="/NewsManager/images/${news.npicPath }"/>
<textarea class="layui-textarea layui-hide" name="ncontent" lay-verify="content" id="news_content">${news.ncontent }</textarea>
<select name="ntid">
<option value="0">请选择</option>
<c:forEach items="${topicList }" var="topic">
<c:choose>
<c:when test="${topic.tid eq news.ntid}">
<option value="${topic.tid }" selected="selected">${topic.tname }</option>
</c:when>
<c:otherwise>
<option value="${topic.tid }">${topic.tname }</option>
</c:otherwise>
</c:choose>
</c:forEach>
</select>
3.区分添加功能or修改功能(公用一个页面,实现思路为修改时肯定通过nid修改,添加时没有nid,所以在地址栏action中加入nid属性,然后取后台判断)
action="<%=basePath%>INewsServlet?action=updateNews&nid=${news.nid}"
if(action.equals("updateNews")) {
String nid=req.getParameter("nid");
if(nid==null||nid.equals("")) {
insertNews(req, resp);
}else {
updateNews(req,resp);
}
}
4.实现修改操作,当点击提交,将数据传递给数据库
DaoImpl层:
@Override
public int updateNews(News news) throws Exception {
// 准备一条SQL语句
String sql = "update news set ntitle=?,nsummary=?,ncontent=?,npicpath=?,nauthor=?,nmodifyDate=?,ntid=? where nid=?";
Object[] objs = {news.getNtitle(), news.getNsummary(),news.getNcontent(),news.getNpicPath(),news.getNauthor(),news.getNmodifyDate(),news.getNtid(),news.getNid()};
return executeUpdate(sql, objs);
}
Servlet:其中有一个文件判断,如过用户没有选择文件则获取之前的,如果选择了则修改文件名字
protected void updateNews(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
News news=new News();
news.setNid(Integer.parseInt(req.getParameter("nid")));
//步骤一:判断是否是文件表单
boolean isMultipartContent = ServletFileUpload.isMultipartContent(req);
if(isMultipartContent) {
FileItemFactory fileItemFactory=new DiskFileItemFactory();
//步骤二:创建ServletFileUpload对象
ServletFileUpload servletFileUpload=new ServletFileUpload(fileItemFactory);
try {
//步骤三:获取表单提交的数据
List<FileItem> fileItems = servletFileUpload.parseRequest(req);
//步骤四:解析数据
for (FileItem fileItem : fileItems) {
//判断是否是普通表单数据
if(fileItem.isFormField()) {
if(fileItem.getFieldName().equals("ntitle")) {
news.setNtitle(fileItem.getString("UTF-8"));
}else if(fileItem.getFieldName().equals("nsummary")) {
news.setNsummary(fileItem.getString("UTF-8"));
}else if(fileItem.getFieldName().equals("ncontent")) {
news.setNcontent(fileItem.getString("UTF-8"));
}else if(fileItem.getFieldName().equals("ntid")) {
news.setNtid(Integer.parseInt(fileItem.getString("UTF-8")));
}
}else {
//获取文件数据
String fileName = fileItem.getName();
if(fileName==null||fileName.equals("")) {
try {
//获取之前的
News oneNews = iNewsService.getOneNews(Integer.parseInt(req.getParameter("nid")));
news.setNpicPath(oneNews.getNpicPath());
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}else {
//获取上传路径
String realPath = getServletContext().getRealPath("/images");
//创建文件对象
File file=new File(realPath,fileName);
try {
fileItem.write(file);
news.setNpicPath(fileName);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
try {
News_Users user = (News_Users)req.getSession().getAttribute("user");
news.setNauthor(user.getUname());
news.setNmodifyDate(new Date());
iNewsService.updateNews(news);
req.getRequestDispatcher("/page/news/newsList.jsp").forward(req, resp);
} catch (Exception e) {
e.printStackTrace();
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
}
全选和反选:
//全选和反选
$("input[name=allChecked]").click(function() {
//判断当前是选中的还是未选中的
if($(this).is(":checked")){
//所有的复选框都选中
$("input[name=newsChecked]").attr("checked",true);
}else{
//所有的复选框都选中
$("input[name=newsChecked]").attr("checked",false);
}
});
//单个复选框选中
function newsCheck(checkbox) {
//找到单个的复选框
//如果当前复选框是勾选上的,那么拿到所有的复选框,判断是否是勾选上的,如果是都勾选上,那么全选按钮也要勾选
//如果当前复选框是未勾选的,那么你需要将全选框去取消勾选
if($(checkbox).is(":checked")){
var flag=true;
$("input[name=newsChecked]").each(function(index,item) {
if($(item).is(":checked")){
flag=true;
}else{
flag=false;
return false;
}
});
if(flag){
$("input[name=allChecked]").attr("checked",true);
}
}else{
$("input[name=allChecked]").attr("checked",false);
}
}
批量删除:
1.点击批量删除按钮,需要将当前所选中的内容的id拿到
2.将ID数组传递到后台
3.在后台遍历数组,然后循环删除
//批量删除
$("#deleteall").click(function() {
var array=new Array();
//获取到所有的选中的复选框
$("input[name=newsChecked]:checked").each(function(index,item) {
array[index]=$(item).val();
});
$.ajax({
url:"/NewsManager/INewsServlet",
data:{action:"deleteAll","array":array},
type:"POST",
dataType:"JSON",
success:function(resultMap){
if(resultMap.flag==true){
layer.alert(‘删除成功~‘);
load(1);
}else{
layer.alert(resultMap.newsId+"有评论数据,无法删除~");
load(1);
}
}
})
});
});
else if(action.equals("deleteAll")) {
//判断删除成功还是失败
boolean falg=false;
List<String> newsId=new ArrayList<String>();
Map<String, Object> resultMap=new HashMap();
//获取传递的数组
String[] parameterValues = req.getParameterValues("array[]");
for (int i = 0; i < parameterValues.length; i++) {
try {
iNewsService.deleteNews(Integer.parseInt(parameterValues[i]));
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (Exception e) {
falg=false;
//当新闻有评论无法删除
newsId.add(parameterValues[i]);
}
}
resultMap.put("flag", falg);
resultMap.put("newsId", newsId);
resp.getWriter().write(JSON.toJSONString(resultMap));
}
1.过滤器:
生活当中,净水器,渔网
在程序当中过滤器就是用来拦截过滤请求,假设浏览器发送了请求到达服务器,先会到达过滤器,可以处理一些内容,
比如解决乱码,拦截非法登陆用户,过滤敏感词汇
创建过滤器:
1.创建一个类 实现Filter接口
2.重写接口中的方法
3.配置拦截的路径
web.xml
<!-- 配置过滤器 -->
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>com.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
注解
@WebFilter("/*") //拦截所有的请求
public class MyFilter implements Filter {
/**
* 服务器启动时,会创建Filter的实例,然后执行init初始化方法
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter过滤器初始化完毕。。。。。。。。。。。。。。。。。。");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("监控到了当前请求。。。。。。。。。。。。。");
//放行资源
chain.doFilter(request, response);
System.out.println("放行资源后再次执行Filter");
}
@Override
public void destroy() {
System.out.println("filter销毁,释放资源..............................");
}
}
过滤器执行流程:
1.客户端发送了一个请求,请求静态资源,过滤器先会监控到当前请求
2.如果过滤器放行了当前请求,则会请求到对应资源
3.请求完毕后,还会执行过滤器放行资源后的代码
过滤器生命周期:
1.在容器启动时,会创建Filter的实例,然后执行init初始化方法,该方法只执行一次
2.当监控到请求后,会执行doFIlter方法,该方法执行多次
3.当容器停止后,会调用destroy(),该方法执行一次
过滤器请求地址配置:
1.配置方案一:/* 代表所有请求的资源地址都会拦截
2.配置方案二:/*.jsp 代表只拦截.jsp结尾的请求
3.配置方案三:/user/* 分请求层次的方式进行拦截
4.配置方案四:/index.jsp 请求确切资源时拦截
过滤器请求方式配置:
注解方式配置
DispatcherType定一了请求方式:
REQUEST:默认的,代表直接请求资源时会拦截
FORWARD:转发时拦截
ASYNC:拦截异步请求
INCLUDE:代表嵌套请求时才会拦截
ERROR:错误请求拦截
web.xml方式配置:再filter-mapping中加入如下配置
<dispatcher>FORWARD</dispatcher>
过滤器执行连执行顺序:
注解:
根据名称排序A-Z
web.xml
按照Filter配置的先后顺序执行
2.监听器:
1.监听事件,例如我们向session中存放了一个数据,我在session删除了一个数据
2.监听器的使用
1.创建一个监听器,实现对应接口
2.重写接口方法,进行监听
3.配置监听器
注解
@WebListener
public class News_Users implements Serializable,HttpSessionBindingListener{
/**
* 序列化ID
*/
private static final long serialVersionUID = -4385525238332285976L;
private Integer uid; //用户编号
private String uname; //用户名称
private String upwd; //登陆密码
private String telephone; //手机号
private String email; //邮箱
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public String getUpwd() {
return upwd;
}
public void setUpwd(String upwd) {
this.upwd = upwd;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "News_Users [uid=" + uid + ", uname=" + uname + ", upwd=" + upwd + ", telephone=" + telephone
+ ", email=" + email + "]";
}
public News_Users(Integer uid, String uname, String upwd, String telephone, String email) {
this.uid = uid;
this.uname = uname;
this.upwd = upwd;
this.telephone = telephone;
this.email = email;
}
public News_Users() {
}
//往session存当前对象时会监听到
@Override
public void valueBound(HttpSessionBindingEvent event) {
System.out.println("Listener监听到了当前对象存放到了session当中");
UserCount.COUNT++;
System.out.println(this.toString());
System.out.println("当前值:"+UserCount.COUNT);
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
System.out.println("Listener监听到了当前对象从session当中删除");
UserCount.COUNT--;
System.out.println(this.toString());
System.out.println("当前值:"+UserCount.COUNT);
}
}
web.xml
<listener>
<listener-class>com.news.entity.News_Users</listener-class>
</listener>
标签:clist lang 发布者 target http icon 运行时 代码冗余 lock
原文地址:https://www.cnblogs.com/zhaoyun01/p/13336666.html