Servlet
Maven添加依赖项
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
实现Servlet方法
package anti.o2;
import javax.servlet.*;
import java.io.IOException;
public class Demo implements Servlet {
/**
* @param servletConfig
* @throws ServletException
*/
public void init(ServletConfig servletConfig) throws ServletException {
}
/**
* @return
*/
public ServletConfig getServletConfig() {
return null;
}
/**
* @param servletRequest
* @param servletResponse
* @throws ServletException
* @throws IOException
*/
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
}
/**
* @return
*/
public String getServletInfo() {
return null;
}
/**
*
*/
public void destroy() {
}
}
- 实现
Servlet
接口 - 然后在注解中配置访问路径
service
方法每次请求被调用
HttpServelet
-
继承
HttpServlet
类,实现doGet和doPost方法的封装 -
继承后需要重写doXxx类
-
<form action="/WebApp/Demo2" method="post"> <input name="username"> <input type="submit" > </form> 实现将表单提交到Demo2的doPost类处理
Servlet urlPattern
-
一个Servlet可以配置多个urlPattern
-
例如
-
@WebServlet(urlPatterns = {"/Demo2","/Demo3"})
-
-
配置规则
- 精确匹配
- 配置路径和访问路径要求完全一致
- 目录匹配
- 例如
@WebServlet(urlPatterns ="/demo/*")
- 优先匹配精确匹配
- 例如
- 扩展名匹配
- 例如
@WebServlet(urlPatterns ="*.do")
- 不能在前面加斜杠
- 例如
- 任意匹配
@WebServlet(urlPatterns ="/")
@WebServlet(urlPatterns ="/*")
- 这样任意路径都可以访问
- 会覆盖掉原来的静态资源访问
- 精确匹配
-
XML配置Servlet
-
在Web.xml中配置Servlet
-
这种方法较老,不推荐
-
<servlet> <servlet-name>examppppple</servlet-name> <servlet-class>anti.o2.Demo3</servlet-class> </servlet> <servlet-mapping> <servlet-name>examppppple</servlet-name> <url-pattern>/demo3</url-pattern> </servlet-mapping>
-
Request和Response对象
Request
-
ServletRequest
-
HttpServletRequest继承
-
RequestFacade :Tomcat定义的实现类,生成Request对象
-
Request获取请求数据
-
请求数据分为3部分
-
String getMethod()获取请求方式:GET
-
String getContextPath() 获取项目路径
-
StringBuffer getRequestURL() 获取URL
-
String getRequestURI() 获取URI (后面的路径)
-
String getQueryString();
-
运行以下代码
-
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("get..."); String method = req.getMethod(); System.out.println(method); String contextpath = req.getContextPath(); System.out.println(contextpath); String URL = String.valueOf(req.getRequestURL()); System.out.println(URL); String URI = req.getRequestURI(); System.out.println(URI ); }
-
获得结果
-
请求头
- String getHeader(String name)
- 获取值
请求体
-
ServletInputStream getInputStream();
GET获取字节输入流 -
BufferedReader getReader()
POST获取字符输入流 -
通过流获取请求体信息
-
BufferedReader br = req.getReader(); System.out.println(br.readLine());
请求方法
Map<String,String[]> getParameterMap()
获取所有参数集合- 这个是get和post通用的,底层通过getReader和getInputStream对请求体解析实现
Response
- 相应数据分为3部分
响应行
HTTP/1.1 200 OK
- void setStstus(int sc)设置相应状态码
响应头
-
例如
Context-Type:text/html
-
设置返回为html代码如下
-
resp.setHeader("context-type","text/html");
-
void setHeader(String name, String value)
-
resp.setContentType("text/html;charset=utf-8"); 设置编码方式,防止中文乱码
响应体
PrintWriter getWriter()
获取字符输出流ServletOutputStream getOutputStream()
获取字节输出流
读取文件
FileInputStream fis =new FileInputStream("location");
ServletOutputStream outputStream = resp.getOutputStream();
byte[] buff = new byte[1024];
int len = 0;
while((len = fis.read(buff))!=-1){
outputStream.write(buff,0,len);
}
fis.close();
-
也可以使用封装方法
-
首先导入IOUtils工具类
-
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency>
-
然后使用copy方法直接复制
-
FileInputStream fis =new FileInputStream("C:\\Users\\Anti\\Pictures\\R6.png"); ServletOutputStream outputStream = resp.getOutputStream(); IOUtils.copy(fis,outputStream); fis.close();
-
重定向
resp.setStatus(302);
resp.setHeader("location","B的路径")
或者使用封装方法
resp.sendRedirect("location");
-
重定向会使浏览器url发生变化
-
可以重定向到任意资源
-
两次请求,不能在多个资源中使用request共享数据
-
可以通过.getContextPath获取路径
-
String context = req.getContextPath(); resp.sendRedirect(context+ "/resp2");
乱码问题处理
-
Post: getReader()
request.setCharacterEncoding("UTF-8")
解决字符乱码
-
get:
String getQueryString()
获取参数-
浏览器用UTF-8给URL编码。
- URL将编码方式转化为二进制。一个汉字->三字节->24位
- 每个字节转化为2个16进制数并在前面加上%
-
TomCat用ISO-8859-1解码,故产生乱码
-
public class Test { public static void main(String[] args) throws UnsupportedEncodingException { String user = "氧"; String encode = URLEncoder.encode(user,"utf-8"); System.out.println(encode); System.out.println(URLDecoder.decode(encode,"utf-8")); } }
-
-
输出
%E6%B0%A7
氧
-
get乱码解决思路:
-
将乱码解码为字节数组
-
String username =req.getParameter("username"); System.out.println("处理前"+username); byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1); String user = new String(bytes,"utf-8"); System.out.println("处理后"+user);
-
资源转发
- 将请求和相应给另一个类处理
- 例如定义两个类
req.getRequestDispatcher("/F2").forward(req,resp);
实现转发。Dispatcher是调度员的意思- 这是F1
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tV6xC6Zp-1664949121008)(C:\Users\Anti\AppData\Roaming\Typora\typora-user-images\image-20221004230937830.png)]这是F2
- Get请求F1的效果
- 但是上方的URL并没有改变
- 使用Request对象方法
setAttribute(String,Object)
存储数据到request域中Object getAttribute(String name)
跟据key获得值void removeAttribute(String name)
删除值
Servlet+MyBatis实现密码登陆
添加依赖项
- 先添加Maven。注意检查Mysql版本!!!
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
</dependencies>
-
添加mybatis-config
-
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!--起别名--> <typeAliases> <package name="anti.o2.pojo"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/db1"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <!--扫描mapper--> <package name="anti.o2.mapper"/> </mappers> </configuration>
-
放在resources里面
创建映射
-
创建mapper包
-
mapper下创建UserMapper接口
-
resources下创建
UserMapper.xml
配置文件 -
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="anti.o2.mapper.UserMapper"> </mapper>
HTML文件
<div id="loginDiv">
<form action="/WebApp/login" id="form">
<h1 id="loginMsg">LOGIN IN</h1>
<p>Username:<input id="username" name="username" type="text"></p>
<p>Password:<input id="password" name="password" type="password"></p>
<div id="subDiv">
<input type="submit" class="button" value="login up">
<input type="reset" class="button" value="reset">
<a href="register.html">没有账号?点击注册</a>
</div>
</form>
</div>
注册实现
-
通过检查用户名判断是否重复
-
添加用户
-
<insert id="insertUser"> insert into tb_user(username,password) values(#{username},#{password}) </insert> <select id="select" resultType="anti.o2.pojo.User"> select * from tb_user where username = #{user} and password = #{pass} </select> <select id="selectByUserName" resultType="anti.o2.pojo.User"> select * from tb_user where username = #{username} </select>
-
User selectByUserName(@Param("username")String username); void insertUser(@Param("username")String username,@Param("password")String password);
-
@WebServlet("/registerServlet") public class Register extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); String password = req.getParameter("password"); User user = new User(); user.setUsername(username); user.setPassword(password); //调用方法 String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user1 = mapper.selectByUserName(username); if(user1!=null) { resp.setContentType("text/html;charset=utf-8"); resp.getWriter().write("用户已存在 Existed"); } else { mapper.insertUser(user); sqlSession.commit(); resp.getWriter().write("用户注册成功 Success"); } sqlSession.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doGet(req,resp); } }
代码优化
-
SqlSessionFactory不应该被创建多次,否则创建了多个连接池
-
创建工具类,获得一个固定的SqlSessionFactory
-
public class SqlSession { private static SqlSessionFactory sqlSessionFactory; static { //静态代码块随着类的加载自动执行,且只会执行一次 String resource = "mybatis-config.xml"; InputStream inputStream = null; try { inputStream = Resources.getResourceAsStream(resource); } catch (IOException e) { throw new RuntimeException(e); } sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } public static SqlSessionFactory getSqlSessionFactory(){ return sqlSessionFactory; } }
-
然后在代码中修改这样就能使用固定的连接池了
-
sqlsession不能够被重复使用,否则会相互影响